Class: Bolt::Inventory::Inventory

Inherits:
Object
  • Object
show all
Defined in:
lib/bolt/inventory/inventory.rb

Defined Under Namespace

Classes: WildcardError

Constant Summary collapse

EXTENDED_TARGET_REGEX =

Getting targets from the inventory using ‘–targets’ supports extended glob pattern matching. In this case, use the extended regex so Bolt only uses commas outside brackets and braces as delimiters.

/[[:space:],]+(?=[^\]}]*(?:[\[{]|$))/.freeze
TARGET_REGEX =
/[[:space:],]+/.freeze
GLOB_MATCH_REGEX =

Pattern which looks for indicators that glob-based target name matching should be used.

/[*?\[\]{}]/.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, transport, transports, plugins, source = nil) ⇒ Inventory

Returns a new instance of Inventory.



27
28
29
30
31
32
33
34
35
36
# File 'lib/bolt/inventory/inventory.rb', line 27

def initialize(data, transport, transports, plugins, source = nil)
  @logger          = Bolt::Logger.logger(self)
  @data            = data || {}
  @transport       = transport
  @config          = transports
  @config_resolved = transports.values.all?(&:resolved?)
  @plugins         = plugins
  @targets         = {}
  @source          = source
end

Instance Attribute Details

#pluginsObject (readonly)

Returns the value of attribute plugins.



9
10
11
# File 'lib/bolt/inventory/inventory.rb', line 9

def plugins
  @plugins
end

#sourceObject (readonly)

Returns the value of attribute source.



9
10
11
# File 'lib/bolt/inventory/inventory.rb', line 9

def source
  @source
end

#targetsObject (readonly)

Returns the value of attribute targets.



9
10
11
# File 'lib/bolt/inventory/inventory.rb', line 9

def targets
  @targets
end

#transportObject (readonly)

Returns the value of attribute transport.



9
10
11
# File 'lib/bolt/inventory/inventory.rb', line 9

def transport
  @transport
end

Instance Method Details

#add_facts(target, new_facts = {}) ⇒ Object



355
356
357
358
# File 'lib/bolt/inventory/inventory.rb', line 355

def add_facts(target, new_facts = {})
  @targets[target.name].add_facts(new_facts)
  target
end

#add_to_group(targets, desired_group) ⇒ Object



332
333
334
335
336
337
338
339
340
341
# File 'lib/bolt/inventory/inventory.rb', line 332

def add_to_group(targets, desired_group)
  if group_names.include?(desired_group)
    targets.each do |target|
      # Add the inventory copy of the target
      add_target(groups, @targets[target.name], desired_group)
    end
  else
    raise ValidationError.new("Group #{desired_group} does not exist in inventory", nil)
  end
end

#clear_alia_from_group(group, target_name) ⇒ Object



307
308
309
310
311
312
313
314
# File 'lib/bolt/inventory/inventory.rb', line 307

def clear_alia_from_group(group, target_name)
  if group.all_target_names.include?(target_name)
    group.clear_alia(target_name)
  end
  group.groups.each do |grp|
    clear_alia_from_group(grp, target_name)
  end
end

#configHash[String, Bolt::Config::Transport]

Return a map of transport configuration for the inventory. Any unresolved plugin references are resolved.

Returns:



79
80
81
82
83
84
85
86
# File 'lib/bolt/inventory/inventory.rb', line 79

def config
  if @config_resolved
    @config
  else
    @config_resolved = true
    @config.each_value { |t| t.resolve(@plugins) unless t.resolved? }
  end
end

#create_target_from_hash(data) ⇒ Object

Add a brand new target, overriding any existing target with the same name. This method does not honor target config from the inventory. This is used when Target.new is called from a plan or with a data hash.



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/bolt/inventory/inventory.rb', line 254

def create_target_from_hash(data)
  # If target already exists, delete old and replace with new, otherwise add to new to all group
  new_target = Bolt::Inventory::Target.new(data, self)
  existing_target = @targets.key?(new_target.name)

  validate_target_from_hash(new_target)
  @targets[new_target.name] = new_target

  if existing_target
    clear_alia_from_group(groups, new_target.name)
  else
    add_to_group([new_target], 'all')
  end

  if new_target.target_alias
    groups.insert_alia(new_target.name, Array(new_target.target_alias))
  end

  new_target
end

#create_target_from_inventory(target_name) ⇒ Object

Pull in a target definition from the inventory file and evaluate any associated references. This is used when a target is resolved by get_targets.



240
241
242
243
244
245
246
247
248
249
# File 'lib/bolt/inventory/inventory.rb', line 240

def create_target_from_inventory(target_name)
  target_data = groups.target_collect(target_name) || { 'uri' => target_name }

  target = Bolt::Inventory::Target.new(target_data, self)
  @targets[target.name] = target

  add_to_group([target], 'all')

  target
end

#facts(target) ⇒ Object



360
361
362
# File 'lib/bolt/inventory/inventory.rb', line 360

def facts(target)
  @targets[target.name].facts
end

#features(target) ⇒ Object



368
369
370
# File 'lib/bolt/inventory/inventory.rb', line 368

def features(target)
  @targets[target.name].features
end

#get_target(target) ⇒ Object



107
108
109
110
111
112
113
114
# File 'lib/bolt/inventory/inventory.rb', line 107

def get_target(target)
  target_array = get_targets(target)
  if target_array.count > 1
    raise ValidationError.new("'#{target}' refers to #{target_array.count} targets", nil)
  end

  target_array.first
end

#get_targets(targets, ext_glob: false) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/bolt/inventory/inventory.rb', line 98

def get_targets(targets, ext_glob: false)
  target_array = expand_targets(targets, ext_glob: ext_glob)
  if target_array.is_a? Array
    target_array.flatten.uniq(&:name)
  else
    [target_array]
  end
end

#group_data_for(target_name) ⇒ Object

PRIVATE ####



117
118
119
# File 'lib/bolt/inventory/inventory.rb', line 117

def group_data_for(target_name)
  groups.group_collect(target_name)
end

#group_lookupHash[String, Bolt::Inventory::Group]

Return a map of all groups in the inventory.

Returns:



70
71
72
# File 'lib/bolt/inventory/inventory.rb', line 70

def group_lookup
  @group_lookup ||= groups.collect_groups
end

#group_namesArray[String]

Return a list of all group names in the inventory.

Returns:

  • (Array[String])


62
63
64
# File 'lib/bolt/inventory/inventory.rb', line 62

def group_names
  group_lookup.keys
end

#group_names_for(target_name) ⇒ Object



88
89
90
# File 'lib/bolt/inventory/inventory.rb', line 88

def group_names_for(target_name)
  group_data_for(target_name).fetch('groups', [])
end

#groupsBolt::Inventory::Group

Load and resolve the groups in the inventory. Loading groups resolves all plugin references except for those for target data and config.



51
52
53
54
55
56
# File 'lib/bolt/inventory/inventory.rb', line 51

def groups
  @groups ||= Group.new(@data, @plugins, all_group: true).tap do |groups|
    groups.resolve_string_targets(groups.target_aliases, groups.all_targets)
    groups.validate
  end
end

#match_wildcard?(wildcard, target_name, ext_glob: false) ⇒ Boolean

Does a target match the glob-style wildcard? Ignore case; use extended globs (a,b) when running from the CLI.

Returns:

  • (Boolean)


123
124
125
126
127
128
129
# File 'lib/bolt/inventory/inventory.rb', line 123

def match_wildcard?(wildcard, target_name, ext_glob: false)
  if ext_glob
    File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD | File::FNM_EXTGLOB)
  else
    File.fnmatch(wildcard, target_name, File::FNM_CASEFOLD)
  end
end

#plugin_hooks(target) ⇒ Object



372
373
374
# File 'lib/bolt/inventory/inventory.rb', line 372

def plugin_hooks(target)
  @targets[target.name].plugin_hooks
end

#remove_from_group(target, desired_group) ⇒ Object



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/bolt/inventory/inventory.rb', line 316

def remove_from_group(target, desired_group)
  unless target.length == 1
    raise ValidationError.new("'remove_from_group' expects a single Target, got #{target.length}", nil)
  end

  if desired_group == 'all'
    raise ValidationError.new("Cannot remove Target from Group 'all'", nil)
  end

  if group_names.include?(desired_group)
    remove_target(groups, @targets[target.first.name], desired_group)
  else
    raise ValidationError.new("Group #{desired_group} does not exist in inventory", nil)
  end
end

#resource(target, type, title) ⇒ Object



388
389
390
# File 'lib/bolt/inventory/inventory.rb', line 388

def resource(target, type, title)
  @targets[target.name].resource(type, title)
end

#resources(target) ⇒ Object



384
385
386
# File 'lib/bolt/inventory/inventory.rb', line 384

def resources(target)
  @targets[target.name].resources
end

#set_config(target, key_or_key_path, value) ⇒ Object



376
377
378
# File 'lib/bolt/inventory/inventory.rb', line 376

def set_config(target, key_or_key_path, value)
  @targets[target.name].set_config(key_or_key_path, value)
end

#set_feature(target, feature, value = true) ⇒ Object



364
365
366
# File 'lib/bolt/inventory/inventory.rb', line 364

def set_feature(target, feature, value = true)
  @targets[target.name].set_feature(feature, value)
end

#set_var(target, var_hash) ⇒ Object



347
348
349
# File 'lib/bolt/inventory/inventory.rb', line 347

def set_var(target, var_hash)
  @targets[target.name].set_var(var_hash)
end

#target_config(target) ⇒ Object



380
381
382
# File 'lib/bolt/inventory/inventory.rb', line 380

def target_config(target)
  @targets[target.name].config
end

#target_implementation_classObject



42
43
44
# File 'lib/bolt/inventory/inventory.rb', line 42

def target_implementation_class
  Bolt::Target
end

#target_namesObject Also known as: node_names



92
93
94
# File 'lib/bolt/inventory/inventory.rb', line 92

def target_names
  groups.all_targets
end

#transport_data_getObject



343
344
345
# File 'lib/bolt/inventory/inventory.rb', line 343

def transport_data_get
  { transport: transport, transports: config.transform_values(&:to_h) }
end

#validate_target_from_hash(target) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/bolt/inventory/inventory.rb', line 275

def validate_target_from_hash(target)
  used_groups  = Set.new(group_names)
  used_targets = target_names

  # Make sure there are no group name conflicts
  if used_groups.include?(target.name)
    raise ValidationError.new("Target name #{target.name} conflicts with group of the same name", nil)
  end

  # Validate any aliases
  if (aliases = target.target_alias)
    unless aliases.is_a?(Array) || aliases.is_a?(String)
      msg = "Alias entry on #{t_name} must be a String or Array, not #{aliases.class}"
      raise ValidationError.new(msg, @name)
    end
  end

  # Make sure there are no conflicts with the new target aliases
  used_aliases = groups.target_aliases
  Array(target.target_alias).each do |alia|
    if used_groups.include?(alia)
      raise ValidationError.new("Alias #{alia} conflicts with group of the same name", nil)
    elsif used_targets.include?(alia)
      raise ValidationError.new("Alias #{alia} conflicts with target of the same name", nil)
    elsif used_aliases[alia] && used_aliases[alia] != target.name
      raise ValidationError.new(
        "Alias #{alia} refers to multiple targets: #{used_aliases[alia]} and #{target.name}", nil
      )
    end
  end
end

#vars(target) ⇒ Object



351
352
353
# File 'lib/bolt/inventory/inventory.rb', line 351

def vars(target)
  @targets[target.name].vars
end

#versionObject



38
39
40
# File 'lib/bolt/inventory/inventory.rb', line 38

def version
  2
end