Module: Beaker::Shared::HostManager

Included in:
Beaker::Shared
Defined in:
lib/beaker/shared/host_manager.rb

Overview

Methods for managing Hosts.

  • selecting hosts by role (Symbol or String)

  • selecting hosts by name (String)

  • adding additional method definitions for selecting by role

  • executing blocks of code against selected sets of hosts

Instance Method Summary collapse

Instance Method Details

#find_at_most_one_host_with_role(hosts, role) ⇒ Host

Find at most a single host with the role provided. Raise an error if more than one host is found to have the provided role.

Parameters:

  • hosts (Array<Host>)

    The hosts to examine

  • role (String)

    The host returned will have this role in its role list

Returns:

  • (Host)

    The single host with the desired role in its roles list or nil if no host is found

Raises:

  • (ArgumentError)

    Raised if more than one host has the given role defined



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/beaker/shared/host_manager.rb', line 57

def find_at_most_one_host_with_role(hosts, role)
  role_hosts = hosts_with_role(hosts, role)
  host_with_role = nil
  case role_hosts.length
  when 0
  when 1
    host_with_role = role_hosts[0]
  else
    host_string = ( role_hosts.map { |host| host.name } ).join( ', ')
    raise ArgumentError, "There should be only one host with #{role} defined, but I found #{role_hosts.length} (#{host_string})"
  end
  host_with_role
end

#hosts_with_name(hosts, name = nil) ⇒ Array<Host>

Find hosts from a given array of hosts that all have the desired name, match against host name, vmhostname and ip (the three valid ways to identify an individual host)

Parameters:

  • hosts (Array<Host>)

    The hosts to examine

  • name (String) (defaults to: nil)

    The hosts returned will have this name/vmhostname/ip

Returns:

  • (Array<Host>)

    The hosts that have the desired name/vmhostname/ip



25
26
27
28
29
# File 'lib/beaker/shared/host_manager.rb', line 25

def hosts_with_name(hosts, name = nil)
  hosts.select do |host|
    name.nil? or host.name =~ /\A#{name}/ or host[:vmhostname] =~ /\A#{name}/ or host[:ip] =~ /\A#{name}/
  end
end

#hosts_with_role(hosts, desired_role = nil) ⇒ Array<Host>

Find hosts from a given array of hosts that all have the desired role.

Parameters:

  • hosts (Array<Host>)

    The hosts to examine

  • desired_role (String) (defaults to: nil)

    The hosts returned will have this role in their roles list

Returns:

  • (Array<Host>)

    The hosts that have the desired role in their roles list



14
15
16
17
18
# File 'lib/beaker/shared/host_manager.rb', line 14

def hosts_with_role(hosts, desired_role = nil)
  hosts.select do |host|
    desired_role.nil? or host['roles'].include?(desired_role.to_s)
  end
end

#only_host_with_role(hosts, role) ⇒ Host

Find a single host with the role provided. Raise an error if more than one host is found to have the provided role.

Parameters:

  • hosts (Array<Host>)

    The hosts to examine

  • role (String)

    The host returned will have this role in its role list

Returns:

  • (Host)

    The single host with the desired role in its roles list

Raises:

  • (ArgumentError)

    Raised if more than one host has the given role defined, or if no host has the role defined.



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/beaker/shared/host_manager.rb', line 38

def only_host_with_role(hosts, role)
  a_host = hosts_with_role(hosts, role)
  case
    when a_host.length == 0
      raise ArgumentError, "There should be one host with #{role} defined!"
    when a_host.length > 1
      host_string = ( a_host.map { |host| host.name } ).join( ', ')
      raise ArgumentError, "There should be only one host with #{role} defined, but I found #{a_host.length} (#{host_string})"
  end
  a_host.first
end

#run_block_on(hosts = [], filter = nil, opts = {}, &block) ⇒ Array<Result>, ...

TODO:

(beaker3.0:BKR-571): simplify return types to Array<Result> only

Execute a block selecting the hosts that match with the provided criteria

Parameters:

  • hosts (Array<Host>, Host) (defaults to: [])

    The host or hosts to run the provided block against

  • filter (String, Symbol) (defaults to: nil)

    Optional filter to apply to provided hosts - limits by name or role

  • opts (Hash{Symbol=>String}) (defaults to: {})
  • block (Block)

    This method will yield to a block of code passed by the caller

Options Hash (opts):

  • :run_in_parallel (Boolean)

    Whether to run on each host in parallel.

Returns:

  • (Array<Result>, Result, nil)

    If an array of hosts has been passed (after filtering), then either an array of results is returned (if the array is non-empty), or nil is returned (if the array is empty). Else, a result object is returned. If filtering makes it such that only one host is left, then it's passed as a host object (not in an array), and thus a result object is returned.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/beaker/shared/host_manager.rb', line 87

def run_block_on hosts = [], filter = nil, opts = {}, &block
  result = nil
  block_hosts = hosts #the hosts to apply the block to after any filtering
  if filter
    if not hosts.empty?
      block_hosts = hosts_with_role(hosts, filter) #check by role
      if block_hosts.empty?
        block_hosts = hosts_with_name(hosts, filter) #check by name
      end
      if block_hosts.length == 1  #we only found one matching host, don't need it wrapped in an array
        block_hosts = block_hosts.pop
      end
    else
      raise ArgumentError, "Unable to sort for #{filter} type hosts when provided with [] as Hosts"
    end
  end
  if block_hosts.is_a? Array
    if block_hosts.length > 0
      if run_in_parallel? opts
        # Pass caller[1] - the line that called block_on - for logging purposes.
        result = block_hosts.map.each_in_parallel(caller[1]) do |h|
          run_block_on h, &block
        end
        hosts.each{|host| host.close}# For some reason, I have to close the SSH connection
        # after spawning a process and running commands on a host,
        # or else it gets into a broken state for the next call.
      else
        result = block_hosts.map do |h|
          run_block_on h, &block
        end
      end
    else
      # there are no matching hosts to execute against
      # should warn here
      # check if logger is defined in this context
      if ( cur_logger = (logger || @logger ) )
        cur_logger.info "Attempting to execute against an empty array of hosts (#{hosts}, filtered to #{block_hosts}), no execution will occur"
      end
    end
  else
    result = yield block_hosts
  end
  result
end