Class: Bolt::Plugin::Terraform

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

Instance Method Summary collapse

Constructor Details

#initializeTerraform

Returns a new instance of Terraform.



8
9
10
# File 'lib/bolt/plugin/terraform.rb', line 8

def initialize
  @logger = Logging.logger[self]
end

Instance Method Details

#extract_resources(state) ⇒ Object

Format the list of resources into a list of [name, attribute map] pairs. This method handles both version 4 and earlier statefiles, doing the appropriate munging based on the shape of the data.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/bolt/plugin/terraform.rb', line 64

def extract_resources(state)
  if state['version'] >= 4
    state.fetch('resources', []).flat_map do |resource_set|
      prefix = "#{resource_set['type']}.#{resource_set['name']}"
      resource_set['instances'].map do |resource|
        instance_name = prefix
        instance_name += ".#{resource['index_key']}" if resource['index_key']

        [instance_name, resource['attributes']]
      end
    end
  else
    state.fetch('modules', {}).flat_map do |mod|
      mod.fetch('resources', {}).map do |name, resource|
        [name, resource.dig('primary', 'attributes')]
      end
    end
  end
end

#hooksObject



16
17
18
# File 'lib/bolt/plugin/terraform.rb', line 16

def hooks
  ['inventory_targets']
end

#inventory_targets(opts) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/bolt/plugin/terraform.rb', line 24

def inventory_targets(opts)
  state = load_statefile(opts)

  resources = extract_resources(state)

  regex = Regexp.new(opts['resource_type'])

  resources.select do |name, _resource|
    name.match?(regex)
  end.map do |name, resource|
    target = {}

    if opts.key?('uri')
      uri = lookup(name, resource, opts['uri'])
      target['uri'] = uri if uri
    end
    if opts.key?('name')
      real_name = lookup(name, resource, opts['name'])
      target['name'] = real_name if real_name
    end
    if opts.key?('config')
      target['config'] = resolve_config(name, resource, opts['config'])
    end
    target
  end.compact
end

#load_statefile(opts) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/bolt/plugin/terraform.rb', line 51

def load_statefile(opts)
  dir = opts['dir']
  filename = opts.fetch('statefile', 'terraform.tfstate')
  statefile = File.expand_path(File.join(dir, filename))

  JSON.parse(File.read(statefile))
rescue StandardError => e
  raise Bolt::FileError.new("Could not load Terraform state file #{filename}: #{e}", filename)
end

#lookup(name, resource, path) ⇒ Object

Look up a nested value from the resource attributes. The key is of the form ‘foo.bar.0.baz`. For terraform statefile version 3, this will exactly correspond to a key in the resource. In version 4, it will correspond to a nested hash entry at {bar: [{baz: <value>]}} For simplicity’s sake, we just check both.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/bolt/plugin/terraform.rb', line 89

def lookup(name, resource, path)
  segments = path.split('.').map do |segment|
    begin
      Integer(segment)
    rescue ArgumentError
      segment
    end
  end

  value = resource[path] || resource.dig(*segments)
  unless value
    warn_missing_property(name, path)
  end
  value
end

#nameObject



12
13
14
# File 'lib/bolt/plugin/terraform.rb', line 12

def name
  'terraform'
end

#resolve_config(name, resource, config_template) ⇒ Object

Walk the “template” config mapping provided in the plugin config and replace all values with the corresponding value from the resource parameters.



108
109
110
111
112
113
114
115
116
# File 'lib/bolt/plugin/terraform.rb', line 108

def resolve_config(name, resource, config_template)
  Bolt::Util.walk_vals(config_template) do |value|
    if value.is_a?(String)
      lookup(name, resource, value)
    else
      value
    end
  end
end

#warn_missing_property(name, property) ⇒ Object



20
21
22
# File 'lib/bolt/plugin/terraform.rb', line 20

def warn_missing_property(name, property)
  @logger.warn("Could not find property #{property} of terraform resource #{name}")
end