Module: PuppetLitmus::InventoryManipulation

Included in:
PuppetLitmus, PuppetLitmus
Defined in:
lib/puppet_litmus/inventory_manipulation.rb

Overview

helper functions for manipulating and reading a bolt inventory file

Instance Method Summary collapse

Instance Method Details

#add_feature_to_group(inventory_hash, feature_name, group_name) ⇒ Object

Adds a feature to the group specified/

group_name [String] group of nodes to limit the search for the group_name in

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • feature_name (String)

    feature to locate in the group

Returns:

  • inventory.yaml file with feature added to group.

  • (Hash)

    inventory_hash with feature added to group if group_name exists in inventory hash.



245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 245

def add_feature_to_group(inventory_hash, feature_name, group_name)
  i = 0
  inventory_hash['groups'].each do |group|
    if group['name'] == group_name
      group = group.merge('features' => []) if group['features'].nil? == true
      group['features'].push feature_name unless group['features'].include?(feature_name)
      inventory_hash['groups'][i] = group
    end
    i += 1
  end
  inventory_hash
end

#add_feature_to_node(inventory_hash, feature_name, node_name) ⇒ Object

Adds a feature to the node specified/

node_name [String] node of nodes to limit the search for the node_name in

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • feature_name (String)

    feature to locate in the node

Returns:

  • inventory.yaml file with feature added to node.

  • (Hash)

    inventory_hash with feature added to node if node_name exists in inventory hash.



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 279

def add_feature_to_node(inventory_hash, feature_name, node_name)
  group_index = 0
  inventory_hash['groups'].each do |group|
    node_index = 0
    group['targets'].each do |node|
      if node['uri'] == node_name
        node = node.merge('features' => []) if node['features'].nil? == true
        node['features'].push feature_name unless node['features'].include?(feature_name)
        inventory_hash['groups'][group_index]['targets'][node_index] = node
      end
      node_index += 1
    end
    group_index += 1
  end
  inventory_hash
end

#add_node_to_group(inventory_hash, node, group_name) ⇒ Hash

Adds a node to a group specified, if group_name exists in inventory hash.

group_name [String] group of nodes to limit the search for the node_name in

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node (Hash)

    node to add to the group

Returns:

  • (Hash)

    inventory_hash with node added to group if group_name exists in inventory hash.



212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 212

def add_node_to_group(inventory_hash, node, group_name)
  # check if group exists
  if inventory_hash['groups'].any? { |g| g['name'] == group_name }
    inventory_hash['groups'].each do |group|
      group['targets'].push node if group['name'] == group_name
    end
  else
    # add new group
    group = { 'name' => group_name, 'targets' => [node] }
    inventory_hash['groups'].push group
  end
  inventory_hash
end

#add_platform_field(inventory_hash, node_name) ⇒ Object

Add the ‘litmus.platform` with platform information for the target

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node of nodes to limit the search for the node_name in



325
326
327
328
329
330
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 325

def add_platform_field(inventory_hash, node_name)
  facts_from_node(inventory_hash, node_name)
rescue StandardError => e
  warn e
  {}
end

#config_from_node(inventory_hash, node_name) ⇒ Hash

Finds a config hash in the inventory hash by searching for a node name.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

Returns:

  • (Hash)

    config for node of name node_name



167
168
169
170
171
172
173
174
175
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 167

def config_from_node(inventory_hash, node_name)
  config = targets_in_inventory(inventory_hash) do |target|
    next unless target['uri'].casecmp(node_name).zero?

    return target['config'] unless target['config'].nil?
  end

  config.empty? ? nil : config[0]
end

#facts_from_node(inventory_hash, node_name) ⇒ Hash

Finds a facts hash in the inventory hash by searching for a node name.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

Returns:

  • (Hash)

    facts for node of name node_name



182
183
184
185
186
187
188
189
190
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 182

def facts_from_node(inventory_hash, node_name)
  facts = targets_in_inventory(inventory_hash) do |target|
    next unless target['uri'].casecmp(node_name).zero?

    target['facts'] unless target['facts'].nil?
  end

  facts.empty? ? nil : facts[0]
end

#find_targets(inventory_hash, targets) ⇒ Array

Finds targets to perform operations on from an inventory hash.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • targets (Array)

Returns:

  • (Array)

    array of targets.



48
49
50
51
52
53
54
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 48

def find_targets(inventory_hash, targets)
  if targets.nil?
    inventory_hash.to_s.scan(/uri"=>"(\S*)"/).flatten
  else
    [targets]
  end
end

#groups_in_inventory(inventory_hash, &block) ⇒ Object

Recursively find and iterate over the groups in an inventory. If no block is passed to the function then only the name of the group is returned. If a block is passed then the block is executed against each group and the value of the block is returned.

Parameters:

  • inventory_hash (Hash)

    Inventory hash from inventory.yaml

  • block (Block)

    Block to execute against each node



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 62

def groups_in_inventory(inventory_hash, &block)
  inventory_hash['groups'].flat_map do |group|
    output_collector = []
    output_collector << if block
                          yield group
                        else
                          group['name'].downcase
                        end
    output_collector << groups_in_inventory({ 'groups' => group['groups'] }, &block) if group.key? 'groups'
    output_collector.flatten.compact
  end
end

#inventory_hash_from_inventory_file(inventory_full_path = nil) ⇒ Hash

Creates an inventory hash from the inventory.yaml.

Parameters:

  • inventory_full_path (String) (defaults to: nil)

    path to the litmus_inventory.yaml file

Returns:

  • (Hash)

    hash of the litmus_inventory.yaml file.



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 11

def inventory_hash_from_inventory_file(inventory_full_path = nil)
  require 'yaml'
  inventory_full_path = if inventory_full_path.nil?
                          "#{Dir.pwd}/spec/fixtures/litmus_inventory.yaml"
                        else
                          inventory_full_path
                        end
  raise "There is no inventory file at '#{inventory_full_path}'." unless File.exist?(inventory_full_path)

  YAML.load_file(inventory_full_path)
end

#localhost_inventory_hashHash

Provide a default hash for executing against localhost

Returns:

  • (Hash)

    inventory.yaml hash containing only an entry for localhost



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 26

def localhost_inventory_hash
  {
    'groups' => [
      {
        'name' => 'local',
        'targets' => [
          {
            'uri' => 'litmus_localhost',
            'config' => { 'transport' => 'local' },
            'feature' => 'puppet-agent'
          }
        ]
      }
    ]
  }
end

#nodes_with_role(role, inventory) ⇒ Object

Find all targets in an inventory that have a role. The roles for a target are specified in the vars hash for a target. This function is tolerant to the roles hash being called either ‘role’ or ‘roles’ and it is tolerant to the roles being either a single key value or an array of roles.

Parameters:

  • role (String)

    The name of a role to search for

  • inventory (Hash)

    Inventory hash from inventory.yaml



102
103
104
105
106
107
108
109
110
111
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 102

def nodes_with_role(role, inventory)
  output_collector = []
  targets_in_inventory(inventory) do |target|
    vars = target['vars']
    roles = [(vars['role'] || vars['roles'])].flatten
    roles = roles.map(&:downcase)
    output_collector << target['uri'] if roles.include? role.downcase
  end
  output_collector unless output_collector.empty?
end

#remove_feature_from_group(inventory_hash, feature_name, group_name) ⇒ Object

Removes a feature from the group specified/

group_name [String] group of nodes to limit the search for the group_name in

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • feature_name (String)

    feature to locate in the group

Returns:

  • inventory.yaml file with feature removed from the group.

  • (Hash)

    inventory_hash with feature added to group if group_name exists in inventory hash.



265
266
267
268
269
270
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 265

def remove_feature_from_group(inventory_hash, feature_name, group_name)
  inventory_hash['groups'].each do |group|
    group['features'].delete(feature_name) if group['name'] == group_name && group['features'].nil? != true
  end
  inventory_hash
end

#remove_feature_from_node(inventory_hash, feature_name, node_name) ⇒ Object

Removes a feature from the node specified/

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • feature_name (String)

    feature to locate in the node

  • node_name (String)

    node of nodes to limit the search for the node_name in

Returns:

  • inventory.yaml file with feature removed from the node.

  • (Hash)

    inventory_hash with feature added to node if node_name exists in inventory hash.



303
304
305
306
307
308
309
310
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 303

def remove_feature_from_node(inventory_hash, feature_name, node_name)
  inventory_hash['groups'].each do |group|
    group['targets'].each do |node|
      node['features'].delete(feature_name) if node['uri'] == node_name && node['features'].nil? != true
    end
  end
  inventory_hash
end

#remove_node(inventory_hash, node_name) ⇒ Hash

Removes named node from a group inside an inventory_hash.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

Returns:

  • (Hash)

    inventory_hash with node of node_name removed.



231
232
233
234
235
236
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 231

def remove_node(inventory_hash, node_name)
  inventory_hash['groups'].each do |group|
    group['targets'].delete_if { |i| i['uri'] == node_name }
  end
  inventory_hash
end

#search_for_target(target, inventory) ⇒ Object

Searches through the inventory hash to either validate that a group being targeted exists, validate that a specific target being targeted exists, or resolves role names to a list of nodes to target. Targets and roles can be specified as strings or as symbols, and the functions are tolerant to incorrect capitalization.

Parameters:

  • target (String)

    || [Array] A list of targets

  • inventory (Hash)

    inventory hash from inventory.yaml



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 120

def search_for_target(target, inventory)
  result_collector = []
  groups = groups_in_inventory(inventory)
  Array(target).map do |name|
    result_collector << name if groups.include? name.to_s.downcase
    result_collector << name if targets_in_inventory(inventory).include? name.to_s.downcase
    result_collector << nodes_with_role(name.to_s, inventory)
  end

  result_collector = result_collector.flatten.compact
  raise 'targets not found in inventory' if result_collector.empty?

  result_collector
end

#target_in_group(inventory_hash, node_name, group_name) ⇒ Boolean

Determines if a node_name exists in a group in the inventory_hash.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

  • group_name (String)

    group of nodes to limit the search for the node_name in

Returns:

  • (Boolean)

    true if node_name exists in group_name.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 141

def target_in_group(inventory_hash, node_name, group_name)
  exists = false
  inventory_hash['groups'].each do |group|
    next unless group['name'] == group_name

    group['targets'].each do |node|
      exists = true if node['uri'] == node_name
    end
  end
  exists
end

#target_in_inventory?(inventory_hash, node_name) ⇒ Boolean

Determines if a node_name exists in the inventory_hash.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

Returns:

  • (Boolean)

    true if node_name exists in the inventory_hash.



158
159
160
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 158

def target_in_inventory?(inventory_hash, node_name)
  find_targets(inventory_hash, nil).include?(node_name)
end

#targets_in_inventory(inventory_hash) ⇒ Object

Iterate over all targets in an inventory. If no block is given to the function it will return the name of every target in the inventory. If a block is passed it will execute the block on each target and return the value of the block.

Parameters:

  • inventory_hash (Hash)

    Inventory hash from inventory.yaml

  • block (Block)

    Block to execute against each node



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 81

def targets_in_inventory(inventory_hash)
  groups_in_inventory(inventory_hash) do |group|
    if group.key? 'targets'
      group['targets'].map do |target|
        if block_given?
          (yield target)
        else
          target['uri'].downcase
        end
      end
    end
  end
end

#vars_from_node(inventory_hash, node_name) ⇒ Hash

Finds a var hash in the inventory hash by searching for a node name.

Parameters:

  • inventory_hash (Hash)

    hash of the inventory.yaml file

  • node_name (String)

    node to locate in the group

Returns:

  • (Hash)

    vars for node of name node_name



197
198
199
200
201
202
203
204
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 197

def vars_from_node(inventory_hash, node_name)
  vars = targets_in_inventory(inventory_hash) do |target|
    next unless target['uri'].casecmp(node_name).zero?

    target['vars'] unless target['vars'].nil?
  end
  vars.empty? ? {} : vars[0]
end

#write_to_inventory_file(inventory_hash, inventory_full_path) ⇒ Object

Write inventory_hash to inventory_yaml file/

@param inventory_full_path [String] path to the inventory.yaml file
@param inventory_hash [Hash] hash of the inventory.yaml file
@return inventory.yaml file with feature added to group.


317
318
319
# File 'lib/puppet_litmus/inventory_manipulation.rb', line 317

def write_to_inventory_file(inventory_hash, inventory_full_path)
  File.open(inventory_full_path, 'wb+') { |f| f.write(inventory_hash.to_yaml) }
end