kitchen-terraform 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -2
  4. data/README.md +61 -6
  5. data/lib/kitchen/driver/terraform.rb +37 -22
  6. data/lib/kitchen/provisioner/terraform.rb +14 -18
  7. data/lib/kitchen/verifier/terraform.rb +25 -48
  8. data/lib/terraform/apply_command.rb +11 -20
  9. data/lib/terraform/apply_timeout_config.rb +9 -11
  10. data/lib/terraform/cli_config.rb +29 -0
  11. data/lib/terraform/client.rb +57 -52
  12. data/lib/terraform/color_coercer.rb +35 -0
  13. data/lib/terraform/color_config.rb +9 -11
  14. data/lib/terraform/command.rb +16 -30
  15. data/lib/terraform/command_factory.rb +111 -0
  16. data/lib/terraform/command_option.rb +65 -0
  17. data/lib/terraform/command_options.rb +95 -0
  18. data/lib/terraform/configurable.rb +42 -17
  19. data/lib/terraform/{zero_six_output.rb → debug_logger.rb} +10 -7
  20. data/lib/terraform/deprecated_output_parser.rb +41 -0
  21. data/lib/terraform/deprecated_variables_coercer.rb +35 -0
  22. data/lib/terraform/{command_extender.rb → deprecated_version.rb} +10 -7
  23. data/lib/terraform/destructive_plan_command.rb +35 -0
  24. data/lib/terraform/directory_config.rb +10 -5
  25. data/lib/terraform/file_configs.rb +36 -0
  26. data/lib/terraform/get_command.rb +3 -10
  27. data/lib/terraform/group.rb +29 -29
  28. data/lib/terraform/group_attributes.rb +42 -0
  29. data/lib/terraform/group_hostnames.rb +38 -0
  30. data/lib/terraform/groups_coercer.rb +43 -0
  31. data/lib/terraform/groups_config.rb +8 -54
  32. data/lib/terraform/integer_coercer.rb +37 -0
  33. data/lib/terraform/{plan_config.rb → no_output_parser.rb} +8 -7
  34. data/lib/terraform/output_command.rb +3 -39
  35. data/lib/terraform/output_parser.rb +55 -0
  36. data/lib/terraform/parallelism_config.rb +9 -11
  37. data/lib/terraform/pathname_coercer.rb +40 -0
  38. data/lib/terraform/plan_command.rb +7 -41
  39. data/lib/terraform/prepare_input_file.rb +34 -0
  40. data/lib/terraform/{zero_seven_output.rb → prepare_output_file.rb} +11 -9
  41. data/lib/terraform/project_version.rb +19 -0
  42. data/lib/terraform/shell_out.rb +59 -0
  43. data/lib/terraform/show_command.rb +7 -16
  44. data/lib/terraform/simple_coercer.rb +36 -0
  45. data/lib/terraform/{state_config.rb → simple_config.rb} +7 -6
  46. data/lib/terraform/{color_switch.rb → unsupported_version.rb} +6 -8
  47. data/lib/terraform/validate_command.rb +3 -10
  48. data/lib/terraform/variable_files_coercer.rb +40 -0
  49. data/lib/terraform/variable_files_config.rb +9 -10
  50. data/lib/terraform/variables_coercer.rb +49 -0
  51. data/lib/terraform/variables_config.rb +9 -24
  52. data/lib/terraform/version.rb +55 -1
  53. data/lib/terraform/version_command.rb +3 -10
  54. metadata +58 -9
  55. metadata.gz.sig +0 -0
  56. data/lib/terraform/command_executor.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19a43500f0b93a18ec62875671a8a902a1ffd2ac
4
- data.tar.gz: 2f00ae9168495da55d2ef5ba87787faeb98b1202
3
+ metadata.gz: 1ad31536d7fa989d59755d148c04a6ea0895a2f6
4
+ data.tar.gz: c817dde749927ce21795cdde40a8c9d1e65713b4
5
5
  SHA512:
6
- metadata.gz: fa18168d24b9d081b23d181946b59452d606af078ff1e559a9bfbb501cf6e776329606b2cd6f5ec0eee751acf8e9a4fb08044d9e2275f1412c53faa733e92de2
7
- data.tar.gz: 604c970071fe3224ece676255d9d807fa3f29c93a5435d4e0f5f9a2dea963ad1da7ff3b782f808dcf4cd58dfe587a2c2cc5e907337e175e7568b1120c1c1b2d0
6
+ metadata.gz: 7882c3a7f177c5325210d8ecb5c4681ab3c0bff524b20e0d9ff929c4f6f69ec18a72c18b25e796a05ac7c512b3b0dd3db53ac113d3a1bb0bc4f43eecb66edd22
7
+ data.tar.gz: 770b9530932c84a4ecfef885f6d2c5800d4960f225d4522301b4c8edf258baff7102bd9e5ec48e9f45cfc72fcd8e44d2a1163c54bcea010e17a511359e269c26
Binary file
data.tar.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- �:����ce
2
- e�Q诣|0��6!���A2T��Hy�c�w���m��a?��&� z�Ԋ���5O�#��KsO��\{��W�Uh�9>���F�3'J0mhK�?U;1�Ţ�KS�g畝� y_��)g�}tK����*���(�ʍbLY|T}PÇ�w�鸡������F����`AEx������S�ՔJς,-{�&���?�[�$뚵d�P���MV���e��jsf���U�k�%�(
1
+ )!"��k���O��؝�L�� j꾧$3+�F��O��،$��/�>� ���s���*��~�S�=W������S0��w�:c����`zDR�xC�Ѽ��6n����g�lgꞾb�&�j8���w�$�6]��1| �Ѭ�9l��)�Ԫ�e��7��0���zKGgA����簃3H���t��r��QM��/�p~���O��[]d���.w�OPs�3�Z��
2
+ ��k�����3
data/README.md CHANGED
@@ -38,7 +38,7 @@ Once Bundler is installed, add kitchen-terraform to the project's Gemfile:
38
38
 
39
39
  ```rb
40
40
  source 'https://rubygems.org/' do
41
- gem 'kitchen-terraform', '~> 0.5'
41
+ gem 'kitchen-terraform', '~> 0.6'
42
42
  end
43
43
  ```
44
44
 
@@ -60,7 +60,7 @@ Terraform configuration.
60
60
 
61
61
  [Test Kitchen configuration]: https://docs.chef.io/config_yml_kitchen.html
62
62
 
63
- Refer to [Getting Started Readme](examples/getting_started/README.md) for a detailed walkthrough of setting up and using kitchen-terraform.
63
+ Refer to [Getting Started Readme](examples/aws_provider/getting_started.md) for a detailed walkthrough of setting up and using kitchen-terraform.
64
64
 
65
65
  Refer to the [examples directory] for a detailed example project.
66
66
 
@@ -97,16 +97,29 @@ provisioner.
97
97
 
98
98
  #### Configuration
99
99
 
100
- There are no configuration options for the driver.
100
+ ##### cli
101
101
 
102
- ##### Example .kitchen.yml
102
+ The pathname of the Terraform command-line interface (CLI) executable or
103
+ an executable that implements an equivalent interface.
104
+
105
+ [command-line interface]: https://www.terraform.io/docs/commands/index.html
106
+
107
+ ###### Example .kitchen.yml
103
108
 
104
109
  ```yaml
105
110
  ---
106
111
  driver:
107
112
  name: terraform
113
+ cli: /usr/local/bin/terraform
108
114
  ```
109
115
 
116
+ ###### Default
117
+
118
+ The default `cli` is `'terraform'`, and is assumed to exist in the
119
+ user's [PATH].
120
+
121
+ [PATH]: http://www.linfo.org/path_env_var.html
122
+
110
123
  ### Provisioner
111
124
 
112
125
  The [provisioner] is the bridge between Terraform and Test Kitchen. It
@@ -198,6 +211,47 @@ provisioner:
198
211
 
199
212
  The default `parallelism` is 10.
200
213
 
214
+ ##### plan
215
+
216
+ The pathname of the [execution plan] that Terraform will generate and
217
+ apply.
218
+
219
+ [execution plan]: https://www.terraform.io/docs/commands/plan.html#_out_path
220
+
221
+ ###### Example .kitchen.yml
222
+
223
+ ```yaml
224
+ ---
225
+ provisioner:
226
+ name: terraform
227
+ plan: /terraform/plan
228
+ ```
229
+
230
+ ###### Default
231
+
232
+ The default `plan` is under the current working directory of Test
233
+ Kitchen at `.kitchen/kitchen-terraform/<suite_name>/terraform.tfplan`.
234
+
235
+ ##### state
236
+
237
+ The pathname of the [state file] that Terraform will generate.
238
+
239
+ [state file]: https://www.terraform.io/docs/commands/apply.html#_state_out_path
240
+
241
+ ###### Example .kitchen.yml
242
+
243
+ ```yaml
244
+ ---
245
+ provisioner:
246
+ name: terraform
247
+ state: /terraform/state
248
+ ```
249
+
250
+ ###### Default
251
+
252
+ The default `state` is under the current working directory of Test
253
+ Kitchen at `.kitchen/kitchen-terraform/<suite_name>/terraform.tfstate`.
254
+
201
255
  ##### variable_files
202
256
 
203
257
  A collection of pathnames of [Terraform variable files] to be evaluated
@@ -338,8 +392,9 @@ The default `groups` collection is empty.
338
392
  For each group:
339
393
 
340
394
  - the default `attributes` mapping consists of equivalently named
341
- attributes for each output variable; additional or overridden
342
- associations can be added.
395
+ attributes for each output variable as well as a "terraform_state"
396
+ attribute containing the pathname of the state file; additional or
397
+ overridden associations can be added.
343
398
 
344
399
  - the default `controls` collection is empty
345
400
 
@@ -14,16 +14,16 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'fileutils'
18
17
  require 'kitchen'
19
- require 'terraform/client'
18
+ require 'terraform/cli_config'
20
19
  require 'terraform/configurable'
20
+ require 'terraform/version'
21
21
 
22
22
  module Kitchen
23
23
  module Driver
24
24
  # Terraform state lifecycle activities manager
25
- class Terraform < Base
26
- include ::Terraform::Client
25
+ class Terraform < ::Kitchen::Driver::Base
26
+ extend ::Terraform::CLIConfig
27
27
 
28
28
  include ::Terraform::Configurable
29
29
 
@@ -31,31 +31,46 @@ module Kitchen
31
31
 
32
32
  no_parallel_for
33
33
 
34
- def create(_state = nil)
35
- %i(plan state)
36
- .each { |option| FileUtils.mkdir_p File.dirname provisioner[option] }
37
- end
34
+ def create(_state = nil); end
38
35
 
39
36
  def destroy(_state = nil)
40
- return if !File.exist?(provisioner[:state]) || current_state.empty?
41
-
42
- create
43
- validate_configuration_files
44
- download_modules
45
- plan_execution destroy: true
46
- apply_execution_plan
37
+ load_state { client.apply_destructively }
38
+ rescue ::Kitchen::StandardError, ::SystemCallError => error
39
+ raise ::Kitchen::ActionFailed, error.message
47
40
  end
48
41
 
49
42
  def verify_dependencies
50
- case version
51
- when /(v[^0]|v0\.[^678])/
52
- raise Kitchen::UserError,
53
- 'Only Terraform v0.8, v0.7, and v0.6 are supported'
54
- when /v0\.6/
55
- log_deprecation aspect: 'v0.6', remediation: 'Update to v0.8 or v0.7',
56
- version: '1.0'
43
+ verify_supported_version
44
+ check_deprecated_version
45
+ end
46
+
47
+ private
48
+
49
+ def check_deprecated_version
50
+ version.if_deprecated do
51
+ log_deprecation aspect: version.to_s,
52
+ remediation: "Install #{::Terraform::Version.latest}"
53
+ end
54
+ end
55
+
56
+ def load_state(&block)
57
+ silent_client.load_state(&block)
58
+ rescue ::Errno::ENOENT => error
59
+ debug error.message
60
+ end
61
+
62
+ def verify_supported_version
63
+ version.if_not_supported do
64
+ raise ::Kitchen::UserError,
65
+ "#{version} is not supported\nInstall " \
66
+ "#{::Terraform::Version.latest}"
57
67
  end
58
68
  end
69
+
70
+ def version
71
+ @version ||=
72
+ ::Terraform::Client.new(config: self, logger: debug_logger).version
73
+ end
59
74
  end
60
75
  end
61
76
  end
@@ -19,41 +19,37 @@ require 'terraform/apply_timeout_config'
19
19
  require 'terraform/color_config'
20
20
  require 'terraform/configurable'
21
21
  require 'terraform/directory_config'
22
+ require 'terraform/file_configs'
22
23
  require 'terraform/parallelism_config'
23
- require 'terraform/plan_config'
24
- require 'terraform/state_config'
25
24
  require 'terraform/variable_files_config'
26
25
  require 'terraform/variables_config'
27
26
 
28
27
  module Kitchen
29
28
  module Provisioner
30
- # Terraform configuration applier
31
- class Terraform < Base
32
- include ::Terraform::ApplyTimeoutConfig
29
+ # Applies constructive Terraform plans
30
+ class Terraform < ::Kitchen::Provisioner::Base
31
+ extend ::Terraform::ApplyTimeoutConfig
33
32
 
34
- include ::Terraform::ColorConfig
33
+ extend ::Terraform::ColorConfig
35
34
 
36
- include ::Terraform::Configurable
37
-
38
- include ::Terraform::DirectoryConfig
35
+ extend ::Terraform::DirectoryConfig
39
36
 
40
- include ::Terraform::ParallelismConfig
37
+ extend ::Terraform::FileConfigs
41
38
 
42
- include ::Terraform::PlanConfig
39
+ extend ::Terraform::ParallelismConfig
43
40
 
44
- include ::Terraform::StateConfig
41
+ extend ::Terraform::VariableFilesConfig
45
42
 
46
- include ::Terraform::VariableFilesConfig
43
+ extend ::Terraform::VariablesConfig
47
44
 
48
- include ::Terraform::VariablesConfig
45
+ include ::Terraform::Configurable
49
46
 
50
47
  kitchen_provisioner_api_version 2
51
48
 
52
49
  def call(_state = nil)
53
- driver.validate_configuration_files
54
- driver.download_modules
55
- driver.plan_execution destroy: false
56
- driver.apply_execution_plan
50
+ client.apply_constructively
51
+ rescue ::Kitchen::StandardError, ::SystemCallError => error
52
+ raise ::Kitchen::ActionFailed, error.message
57
53
  end
58
54
  end
59
55
  end
@@ -22,71 +22,48 @@ module Kitchen
22
22
  module Verifier
23
23
  # Runs tests post-converge to confirm that instances in the Terraform state
24
24
  # are in an expected state
25
- class Terraform < Inspec
26
- include ::Terraform::Configurable
25
+ class Terraform < ::Kitchen::Verifier::Inspec
26
+ extend ::Terraform::GroupsConfig
27
27
 
28
- include ::Terraform::GroupsConfig
28
+ include ::Terraform::Configurable
29
29
 
30
30
  kitchen_verifier_api_version 2
31
31
 
32
32
  def call(state)
33
- verify_groups options: runner_options(transport, state)
33
+ resolve_groups do |group|
34
+ self.group = group
35
+ config[:attributes] = {
36
+ 'terraform_state' => provisioner[:state].to_path
37
+ }.merge group.attributes
38
+ info "Verifying #{group.description}"
39
+ super
40
+ end
41
+ rescue ::Kitchen::StandardError, ::SystemCallError => error
42
+ raise ::Kitchen::ActionFailed, error.message
34
43
  end
35
44
 
36
45
  private
37
46
 
38
- def add_targets(runner:)
39
- collect_tests.each { |test| runner.add_target test }
40
- end
47
+ attr_accessor :group
41
48
 
42
- def execute(group:, options:)
43
- options.merge! group.options
44
- ::Inspec::Runner.new(options).tap do |runner|
45
- add_targets runner: runner
46
- validate exit_code: runner.run
49
+ def configure_backend(options:)
50
+ /(local)host/.match group.hostname do |match|
51
+ options.merge! 'backend' => match[1]
47
52
  end
48
53
  end
49
54
 
50
- def execute_local(group:, options:)
51
- options[:backend] = 'local'
52
- info "Verifying group '#{group.name}'"
53
- execute group: group, options: options
54
- end
55
-
56
- def execute_remote(group:, options:)
57
- driver.output_value list: true, name: group.hostnames do |hostname|
58
- options[:host] = hostname
59
- info "Verifying host '#{hostname}' of group '#{group.name}'"
60
- execute group: group, options: options
61
- end
55
+ def resolve_groups(&block)
56
+ config[:groups]
57
+ .each { |group| group.resolve client: silent_client, &block }
62
58
  end
63
59
 
64
- def resolve_attributes(group:)
65
- driver.each_output_name do |output_name|
66
- group.store_attribute key: output_name, value: output_name
67
- end
68
- group.each_attribute do |key, output_name|
69
- group.store_attribute key: key,
70
- value: driver.output_value(name: output_name)
60
+ def runner_options(transport, state = {}, platform = nil, suite = nil)
61
+ super.tap do |options|
62
+ options.merge! controls: group.controls, 'host' => group.hostname,
63
+ 'port' => group.port, 'user' => group.username
64
+ configure_backend options: options
71
65
  end
72
66
  end
73
-
74
- def validate(exit_code:)
75
- return if exit_code.zero?
76
-
77
- raise ::Kitchen::InstanceFailure, "Inspec Runner returns #{exit_code}"
78
- end
79
-
80
- def verify(group:, options:)
81
- resolve_attributes group: group
82
- group.if_local { return execute_local group: group, options: options }
83
- execute_remote group: group, options: options
84
- end
85
-
86
- def verify_groups(options:)
87
- config[:groups]
88
- .each { |group| verify group: group, options: options.dup }
89
- end
90
67
  end
91
68
  end
92
69
  end
@@ -14,30 +14,21 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require_relative 'command'
18
- require_relative 'color_switch'
17
+ require 'terraform/command'
18
+ require 'terraform/prepare_input_file'
19
+ require 'terraform/prepare_output_file'
19
20
 
20
21
  module Terraform
21
- # Command to apply an execution plan
22
- class ApplyCommand < Command
23
- include ColorSwitch
24
-
25
- def name
26
- 'apply'
27
- end
28
-
29
- def options
30
- "-input=false -parallelism=#{parallelism} -state=#{state} #{color_switch}"
31
- end
32
-
22
+ # A command to apply an execution plan
23
+ class ApplyCommand < ::Terraform::Command
33
24
  private
34
25
 
35
- attr_accessor :parallelism, :state
36
-
37
- def initialize_attributes(color:, parallelism:, state:)
38
- self.color = color
39
- self.parallelism = parallelism
40
- self.state = state
26
+ def initialize(target: '')
27
+ super
28
+ preparations.concat [
29
+ ::Terraform::PrepareInputFile.new(file: target),
30
+ ::Terraform::PrepareOutputFile.new(file: options.state)
31
+ ]
41
32
  end
42
33
  end
43
34
  end
@@ -14,21 +14,19 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'terraform/integer_coercer'
18
+ require 'terraform/simple_config'
19
+
17
20
  module Terraform
18
21
  # Behaviour for the [:apply_timeout] config option
19
22
  module ApplyTimeoutConfig
20
- def self.included(configurable_class)
21
- configurable_class
22
- .required_config :apply_timeout do |_, value, configurable|
23
- configurable.coerce_apply_timeout value: value
24
- end
25
- configurable_class.default_config :apply_timeout, 600
26
- end
23
+ include ::Terraform::SimpleConfig
27
24
 
28
- def coerce_apply_timeout(value:)
29
- config[:apply_timeout] = Integer value
30
- rescue ArgumentError, TypeError
31
- config_error attribute: 'apply_timeout', expected: 'an integer'
25
+ def self.extended(configurable_class)
26
+ configurable_class
27
+ .configure_required attr: :apply_timeout,
28
+ coercer_class: ::Terraform::IntegerCoercer,
29
+ default_value: 600
32
30
  end
33
31
  end
34
32
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2016 New Context Services, 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 'ptools'
18
+
19
+ module Terraform
20
+ # Behaviour for the [:cli] config option
21
+ module CLIConfig
22
+ def self.extended(configurable_class)
23
+ configurable_class.required_config :cli do |key, value, configurable|
24
+ configurable[key] = ::File.expand_path value
25
+ end
26
+ configurable_class.default_config(:cli) { ::File.which 'terraform' }
27
+ end
28
+ end
29
+ end