kitchen-terraform 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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