kitchen-terraform 5.2.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df1c8cf5af302e8ff0157356cdcd17b629b4613a279f44f6776b1c83532fee55
4
- data.tar.gz: ddf2fee8e8b4191bdae7305ca3c2fb1464c58aa9eff9edbfe14495051f31d757
3
+ metadata.gz: d8dc1f0460a8fe0af7e998d2e4b9a898faee66436930a3be0701c230c6eed625
4
+ data.tar.gz: a906eb2ca2f29a01be6e8b9bbc8e555c5d666941e0f73cbd34162946b77d238e
5
5
  SHA512:
6
- metadata.gz: 179e8d7217c594ad88c2bcfe3c81537a7ac18a4b9a0ff9645a56261ec6143468e08d026e99fdd105c253a8567e19f0df9293a1b91a0143a81687ae7b69c963ac
7
- data.tar.gz: f32b9ebb0be2ca34102d51650bf0d73e83807a6d49ab38de21aac89c188be9850ff9d2c1a995d9a154c4a83fe044a3529f2ee53f3f8153158b77049bbd655aee
6
+ metadata.gz: 811fd1d6476ec8364ddd5e5c6022e487cdc8d53c54674a1d6f5c51805fb1b10d8942315f4d4efebf6ea4c20d0a44099bac4f55af6ef3ffe738d92deea2db8b43
7
+ data.tar.gz: bc8fbbae6a4ad9db3ffed99be1afcf953cee0dba241834ff5053f30738486388b2ffc9856d5c10b8dba503a3c68b15d54e9bf139c9d2b375bce9b154a688f78f
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -75,7 +75,7 @@ the semantic versioning of the Ruby gem.
75
75
 
76
76
  ```ruby
77
77
  source "https://rubygems.org/" do
78
- gem "kitchen-terraform", "~> 5.2"
78
+ gem "kitchen-terraform", "~> 5.3"
79
79
  end
80
80
  ```
81
81
 
@@ -102,7 +102,7 @@ example.
102
102
  > Installing Kitchen-Terraform with RubyGems
103
103
 
104
104
  ```sh
105
- gem install kitchen-terraform --version 5.2.0
105
+ gem install kitchen-terraform --version 5.3.0
106
106
  ```
107
107
 
108
108
  This approach is not recommended as it requires more effort to install
@@ -143,6 +143,15 @@ Terraform state.
143
143
  More information can be found in the
144
144
  [Ruby gem documentation][ruby-gem-documentation].
145
145
 
146
+ ### Caveats
147
+
148
+ Versions of Terraform in the 0.11 series may cause `kitchen test` to
149
+ fail if the initial destroy targets an empty Terraform state. A
150
+ workaround for this problem is to use
151
+ `kitchen verify && kitchen destroy` instead of `kitchen test`. More
152
+ details about the problem are available in
153
+ [issue #271](issue-271).
154
+
146
155
  ### Example
147
156
 
148
157
  This example demonstrates how to test a simple Terraform configuration
@@ -209,7 +218,8 @@ suites:
209
218
  - name: example
210
219
  ```
211
220
 
212
- Although Kitchen-Terraform supports multiple versions of Terraform, below snippets are compatible with v0.12:
221
+ Although Kitchen-Terraform supports multiple versions of Terraform,
222
+ below snippets are compatible with v0.12:
213
223
  > ./main.tf
214
224
 
215
225
  ```hcl
@@ -380,11 +390,12 @@ Kitchen-Terraform is distributed under the [Apache License][license].
380
390
  [gem-downloads-total-shield]: https://img.shields.io/gem/dt/kitchen-terraform.svg
381
391
  [gem-downloads-version-shield]: https://img.shields.io/gem/dtv/kitchen-terraform.svg
382
392
  [gem-version-shield]: https://img.shields.io/gem/v/kitchen-terraform.svg
383
- [hakiri-shield]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/master.svg
384
- [hakiri]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/
385
393
  [gitter-shield]: https://img.shields.io/gitter/room/kitchen-terraform/Lobby.svg
386
394
  [gitter]: https://gitter.im/kitchen-terraform/Lobby
395
+ [hakiri-shield]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/master.svg
396
+ [hakiri]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/
387
397
  [inspec]: https://www.inspec.io/
398
+ [issue-271]: https://github.com/newcontext-oss/kitchen-terraform/issues/271
388
399
  [kitchen-terraform-gem]: https://rubygems.org/gems/kitchen-terraform
389
400
  [kitchen-terraform-logo]: https://raw.githubusercontent.com/newcontext-oss/kitchen-terraform/master/assets/logo.png
390
401
  [kitchen-terraform-tutorials]: https://newcontext-oss.github.io/kitchen-terraform/tutorials/
@@ -130,6 +130,8 @@ module Kitchen
130
130
  #
131
131
  # The +bastion_host+ key must be used in combination with a backend which supports remote connections.
132
132
  #
133
+ # The +bastion_host_output+ key will take priority over the +bastion_host+ key.
134
+ #
133
135
  # <em>Example kitchen.yml</em>
134
136
  # verifier:
135
137
  # name: terraform
@@ -138,12 +140,29 @@ module Kitchen
138
140
  # backend: ssh
139
141
  # bastion_host: bastion-host.domain
140
142
  #
143
+ # ====== bastion_host_output
144
+ #
145
+ # The value of the +bastion_host_output+ key is a scalar which is used to obtain the address of a bastion host in
146
+ # the system from a Terraform output.
147
+ #
148
+ # The scalar must match the name of an output with a value which is a string.
149
+ #
150
+ # The +bastion_host_output+ key must be used in combination with a backend which enables remote connections.
151
+ #
152
+ # <em>Example kitchen.yml</em>
153
+ # verifier:
154
+ # name: terraform
155
+ # systems:
156
+ # - name: a system
157
+ # backend: ssh
158
+ # bastion_host_output: an_output
159
+ #
141
160
  # ====== bastion_port
142
161
  #
143
162
  # The value of the +bastion_port+ key is an integer which is used as the port number to connect to on the bastion
144
163
  # host.
145
164
  #
146
- # The +bastion_port+ key must be used in combination with the +bastion_host+ key.
165
+ # The +bastion_port+ key must be used in combination with the +bastion_host_output+ key or the +bastion_host+ key.
147
166
  #
148
167
  # <em>Example kitchen.yml</em>
149
168
  # verifier:
@@ -151,7 +170,7 @@ module Kitchen
151
170
  # systems:
152
171
  # - name: a system
153
172
  # backend: ssh
154
- # bastion_host: bastion-host.domain
173
+ # bastion_host_output: an_output
155
174
  # bastion_port: 1234
156
175
  #
157
176
  # ====== bastion_user
@@ -159,7 +178,7 @@ module Kitchen
159
178
  # The value of the +bastion_user+ key is a scalar which is used as the username for authentication with the
160
179
  # bastion host.
161
180
  #
162
- # The +bastion_user+ key must be used in combination with the +bastion_host+ key.
181
+ # The +bastion_user+ key must be used in combination with the +bastion_host_output+ key or the +bastion_host+ key.
163
182
  #
164
183
  # <em>Example kitchen.yml</em>
165
184
  # verifier:
@@ -167,7 +186,7 @@ module Kitchen
167
186
  # systems:
168
187
  # - name: a system
169
188
  # backend: ssh
170
- # bastion_host: bastion-host.domain
189
+ # bastion_host_output: an_output
171
190
  # bastion_user: bastion-user
172
191
  #
173
192
  # ====== controls
@@ -554,6 +573,7 @@ module Kitchen
554
573
  optional(:attrs_outputs).filled :hash?
555
574
  optional(:backend_cache).value :bool?
556
575
  optional(:bastion_host).filled :str?
576
+ optional(:bastion_host_output).filled :str?
557
577
  optional(:bastion_port).value :int?
558
578
  optional(:bastion_user).filled :str?
559
579
  optional(:controls).each(:filled?, :str?)
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "inspec"
18
+ require "kitchen/terraform/system_bastion_host_resolver"
18
19
  require "kitchen/terraform/system_inspec_map"
19
20
  require "rubygems"
20
21
 
@@ -40,28 +41,46 @@ module Kitchen
40
41
  #
41
42
  # @param attributes [Hash] the attributes to be added to the InSpec options.
42
43
  # @param system_configuration_attributes [Hash] the configuration attributes of a system.
44
+ # @raise [Kitchen::ClientError] if the system bastion host fails to be resolved.
43
45
  # @return [Hash] a mapping of InSpec options.
44
46
  def build(attributes:, system_configuration_attributes:)
45
- system_configuration_attributes.lazy.select do |attribute_name, _|
46
- system_inspec_map.key?(attribute_name)
47
- end.each do |attribute_name, attribute_value|
48
- options.store system_inspec_map.fetch(attribute_name), attribute_value
49
- end
47
+ map_system_to_inspec system_configuration_attributes: system_configuration_attributes
48
+ options.store self.class.inputs_key, attributes
49
+ resolve_bastion_host system_configuration_attributes: system_configuration_attributes
50
50
 
51
- options.merge self.class.inputs_key => attributes
51
+ options
52
52
  end
53
53
 
54
54
  # #initialize prepares a new instance of the class.
55
55
  #
56
+ # @param outputs [Hash] the Terraform output variables.
56
57
  # @return [Kitchen::Terraform::InSpecOptionsFactory]
57
- def initialize
58
+ def initialize(outputs:)
58
59
  self.options = { "distinct_exit" => false }
60
+ self.system_bastion_host_resolver = ::Kitchen::Terraform::SystemBastionHostResolver.new outputs: outputs
59
61
  self.system_inspec_map = ::Kitchen::Terraform::SYSTEM_INSPEC_MAP.dup
60
62
  end
61
63
 
62
64
  private
63
65
 
64
- attr_accessor :options, :system_inspec_map
66
+ attr_accessor :options, :system_bastion_host_resolver, :system_inspec_map
67
+
68
+ def map_system_to_inspec(system_configuration_attributes:)
69
+ system_configuration_attributes.lazy.select do |attribute_name, _|
70
+ system_inspec_map.key?(attribute_name)
71
+ end.each do |attribute_name, attribute_value|
72
+ options.store system_inspec_map.fetch(attribute_name), attribute_value
73
+ end
74
+ end
75
+
76
+ def resolve_bastion_host(system_configuration_attributes:)
77
+ system_bastion_host_resolver.resolve(
78
+ bastion_host: system_configuration_attributes.fetch(:bastion_host, ""),
79
+ bastion_host_output: system_configuration_attributes.fetch(:bastion_host_output, ""),
80
+ ) do |bastion_host:|
81
+ options.store :bastion_host, bastion_host
82
+ end
83
+ end
65
84
  end
66
85
  end
67
86
  end
@@ -81,7 +81,7 @@ module Kitchen
81
81
  def run
82
82
  yield exit_code: runner.run
83
83
  rescue => error
84
- raise ::Kitchen::TransientFailure, "#{action} failed:\n\t#{error.message}"
84
+ raise ::Kitchen::TransientFailure, "#{action} failed:\n\t\t#{error.message}"
85
85
  end
86
86
  end
87
87
  end
@@ -75,9 +75,10 @@ module Kitchen
75
75
  # @param workspace_name [String] the name of the Terraform workspace to select or to create.
76
76
  # @return [Kitchen::Terraform::Driver::Converge]
77
77
  def initialize(config:, logger:, version_requirement:, workspace_name:)
78
+ client = config.fetch :client
78
79
  hash_config = config.to_hash.merge workspace_name: workspace_name
79
80
  self.command_executor = ::Kitchen::Terraform::CommandExecutor.new(
80
- client: config.fetch(:client),
81
+ client: client,
81
82
  logger: logger,
82
83
  )
83
84
  self.logger = logger
@@ -86,11 +87,9 @@ module Kitchen
86
87
  self.apply = ::Kitchen::Terraform::Command::Apply.new config: config
87
88
  self.get = ::Kitchen::Terraform::Command::Get.new
88
89
  self.output = ::Kitchen::Terraform::Command::Output.new
90
+ initialize_outputs_handlers client: client, logger: logger
89
91
  self.validate = ::Kitchen::Terraform::Command::Validate.new config: config
90
92
  self.workspace_select = ::Kitchen::Terraform::Command::WorkspaceSelect.new config: hash_config
91
- self.outputs_manager = ::Kitchen::Terraform::OutputsManager.new
92
- self.outputs_parser = ::Kitchen::Terraform::OutputsParser.new
93
- self.outputs_reader = ::Kitchen::Terraform::OutputsReader.new command_executor: command_executor
94
93
  self.variables = config.fetch :variables
95
94
  self.variables_manager = ::Kitchen::Terraform::VariablesManager.new
96
95
  self.verify_version = ::Kitchen::Terraform::VerifyVersion.new(
@@ -144,6 +143,17 @@ module Kitchen
144
143
  build_infrastructure
145
144
  end
146
145
 
146
+ def initialize_outputs_handlers(client:, logger:)
147
+ self.outputs_manager = ::Kitchen::Terraform::OutputsManager.new
148
+ self.outputs_parser = ::Kitchen::Terraform::OutputsParser.new
149
+ self.outputs_reader = ::Kitchen::Terraform::OutputsReader.new(
150
+ command_executor: ::Kitchen::Terraform::CommandExecutor.new(
151
+ client: client,
152
+ logger: ::Kitchen::Terraform::DebugLogger.new(logger),
153
+ ),
154
+ )
155
+ end
156
+
147
157
  def parse_outputs(json_outputs:)
148
158
  logger.warn "Parsing the Terraform output variables as JSON..."
149
159
  outputs_parser.parse json_outputs: json_outputs do |parsed_outputs:|
@@ -19,31 +19,31 @@ require "kitchen"
19
19
  module Kitchen
20
20
  module Terraform
21
21
  module Raise
22
- # ActionFailed is the class of objects which handle errors resulting in failed actions.
23
- class ActionFailed
24
- # #call logs an error message and raises an error with the message.
25
- #
26
- # @param message [String] the error message.
27
- # @raise [Kitchen::ActionFailed]
28
- # @return [void]
29
- def call(message:)
30
- logger.error message
22
+ # ActionFailed is the class of objects which handle errors resulting in failed actions.
23
+ class ActionFailed
24
+ # #call logs an error message and raises an error with the message.
25
+ #
26
+ # @param message [String] the error message.
27
+ # @raise [Kitchen::ActionFailed]
28
+ # @return [void]
29
+ def call(message:)
30
+ logger.error message
31
31
 
32
- raise ::Kitchen::ActionFailed, message
33
- end
32
+ raise ::Kitchen::ActionFailed, message
33
+ end
34
34
 
35
- # #initialize prepares a new instance of the class.
36
- #
37
- # @param logger [Kitchen::Logger] a logger to log messages.
38
- # @return [Kitchen::Terraform::ActionFailed]
39
- def initialize(logger:)
40
- self.logger = logger
41
- end
35
+ # #initialize prepares a new instance of the class.
36
+ #
37
+ # @param logger [Kitchen::Logger] a logger to log messages.
38
+ # @return [Kitchen::Terraform::ActionFailed]
39
+ def initialize(logger:)
40
+ self.logger = logger
41
+ end
42
42
 
43
- private
43
+ private
44
44
 
45
- attr_accessor :logger
45
+ attr_accessor :logger
46
+ end
46
47
  end
47
48
  end
48
49
  end
49
- end
@@ -46,7 +46,6 @@ module Kitchen
46
46
  self.hosts = configuration_attributes.fetch :hosts do
47
47
  []
48
48
  end.dup
49
- self.inspec_options_factory = ::Kitchen::Terraform::InSpecOptionsFactory.new
50
49
  self.logger = logger
51
50
  end
52
51
 
@@ -72,17 +71,20 @@ module Kitchen
72
71
 
73
72
  private
74
73
 
75
- attr_accessor :attrs, :attrs_outputs, :configuration_attributes, :hosts, :inspec_options_factory, :logger
74
+ attr_accessor :attrs, :attrs_outputs, :configuration_attributes, :hosts, :logger
76
75
 
77
- def execute_inspec_runner(fail_fast:)
76
+ def execute_inspec_runner(fail_fast:, options:)
78
77
  ::Kitchen::Terraform::InSpecFactory.new(fail_fast: fail_fast, hosts: hosts).build(
79
- options: inspec_options,
78
+ options: options,
80
79
  profile_locations: configuration_attributes.fetch(:profile_locations),
81
80
  ).exec
82
81
  end
83
82
 
84
- def inspec_options
85
- inspec_options_factory.build attributes: attrs, system_configuration_attributes: configuration_attributes
83
+ def inspec_options(outputs:)
84
+ ::Kitchen::Terraform::InSpecOptionsFactory.new(outputs: outputs).build(
85
+ attributes: attrs,
86
+ system_configuration_attributes: configuration_attributes,
87
+ )
86
88
  end
87
89
 
88
90
  def resolve(outputs:, variables:)
@@ -102,7 +104,7 @@ module Kitchen
102
104
  def resolve_and_execute(fail_fast:, outputs:, variables:)
103
105
  logger.warn "Verifying the '#{self}' system..."
104
106
  resolve outputs: outputs, variables: variables
105
- execute_inspec_runner fail_fast: fail_fast
107
+ execute_inspec_runner fail_fast: fail_fast, options: inspec_options(outputs: outputs)
106
108
  logger.warn "Finished verifying the '#{self}' system."
107
109
  end
108
110
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2016-2019 New Context, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "kitchen"
18
+
19
+ module Kitchen
20
+ module Terraform
21
+ # SystemBastionHostResolver is the class of objects which resolve a bastion host of a system which may be either
22
+ # dynamically obtained from a Terraform output variable or statically defined.
23
+ class SystemBastionHostResolver
24
+ # #initialize prepares a new instance of the class.
25
+ #
26
+ # @param outputs [Hash] a map of Terraform output variables.
27
+ # @return [Kitchen::Terraform::SystemBastionHostResolver]
28
+ def initialize(outputs:)
29
+ self.outputs = Hash[outputs]
30
+ end
31
+
32
+ # #resolve resolves a bastion host from either the specified Terraform output or the static value.
33
+ #
34
+ # @param bastion_host [String] a statically defined host.
35
+ # @param bastion_host_output [String] the name of the Terraform output which contains a bastion host.
36
+ # @yieldparam bastion_host [String] the bastion host.
37
+ # @raise [Kitchen::ClientError] if the specified Terraform output is not found.
38
+ # @return [self]
39
+ def resolve(bastion_host:, bastion_host_output:)
40
+ if !bastion_host.empty?
41
+ yield bastion_host: bastion_host
42
+ elsif !bastion_host_output.empty?
43
+ yield bastion_host: resolved_output(bastion_host_output: bastion_host_output).fetch(:value)
44
+ end
45
+
46
+ self
47
+ rescue ::KeyError
48
+ raise(
49
+ ::Kitchen::ClientError,
50
+ "Resolving the system bastion host failed due to the absence of the 'value' key from the " \
51
+ "'#{bastion_host_output}' Terraform output of the Kitchen instance state. This error indicates that the " \
52
+ "output format of `terraform output -json` is unexpected."
53
+ )
54
+ end
55
+
56
+ private
57
+
58
+ attr_accessor :outputs
59
+
60
+ def resolved_output(bastion_host_output:)
61
+ outputs.fetch bastion_host_output.to_sym
62
+ rescue ::KeyError
63
+ raise(
64
+ ::Kitchen::ClientError,
65
+ "Resolving the system bastion host failed due to the absence of the '#{bastion_host_output}' key from the " \
66
+ "Terraform outputs of the Kitchen instance state. This error indicates either that `kitchen converge` must " \
67
+ "be executed again to update the Terraform outputs or that the wrong key was provided."
68
+ )
69
+ end
70
+ end
71
+ end
72
+ end
@@ -21,7 +21,6 @@ module Kitchen
21
21
  attrs: :input_file,
22
22
  backend_cache: :backend_cache,
23
23
  backend: :backend,
24
- bastion_host: :bastion_host,
25
24
  bastion_port: :bastion_port,
26
25
  bastion_user: :bastion_user,
27
26
  color: "color",
@@ -71,7 +71,7 @@ module Kitchen
71
71
 
72
72
  # @api private
73
73
  def value
74
- self.value = ::Gem::Version.new "5.2.0" if not @value
74
+ self.value = ::Gem::Version.new "5.3.0" if not @value
75
75
  @value
76
76
  end
77
77
 
@@ -183,9 +183,9 @@ module Kitchen
183
183
  end
184
184
 
185
185
  def verify_systems
186
- logger.banner "Starting verification of the systems."
186
+ logger.warn "Verifying the systems..."
187
187
  systems_verifier.verify outputs: outputs, variables: variables
188
- logger.banner "Finished verification of the systems."
188
+ logger.warn "Finished verifying the systems."
189
189
  end
190
190
  end
191
191
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-terraform
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Lane
@@ -61,7 +61,7 @@ cert_chain:
61
61
  JH4yGDzVEYaZHaohSDcYuGLK6OQylPu7oM75S+TNLWseDIT8bWgQk6NelVjtQQ2Q
62
62
  XSbgfu863jyey/0qO01cUo3+iTqzl85cWg==
63
63
  -----END CERTIFICATE-----
64
- date: 2020-02-28 00:00:00.000000000 Z
64
+ date: 2020-03-08 00:00:00.000000000 Z
65
65
  dependencies:
66
66
  - !ruby/object:Gem::Dependency
67
67
  name: bundler
@@ -508,6 +508,7 @@ files:
508
508
  - lib/kitchen/terraform/system.rb
509
509
  - lib/kitchen/terraform/system_attrs_inputs_resolver.rb
510
510
  - lib/kitchen/terraform/system_attrs_outputs_resolver.rb
511
+ - lib/kitchen/terraform/system_bastion_host_resolver.rb
511
512
  - lib/kitchen/terraform/system_hosts_resolver.rb
512
513
  - lib/kitchen/terraform/system_inspec_map.rb
513
514
  - lib/kitchen/terraform/systems_verifier.rb
metadata.gz.sig CHANGED
Binary file