kitchen-terraform 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -1
  4. data/README.md +33 -359
  5. data/lib/kitchen/driver/terraform.rb +273 -57
  6. data/lib/kitchen/driver/terraform/verify_client_version.rb +44 -0
  7. data/lib/kitchen/driver/terraform/workflow.rb +90 -0
  8. data/lib/kitchen/provisioner/terraform.rb +31 -37
  9. data/lib/{terraform/get_command.rb → kitchen/terraform.rb} +3 -5
  10. data/lib/{terraform/deprecated_version.rb → kitchen/terraform/client.rb} +5 -12
  11. data/lib/kitchen/terraform/client/apply.rb +38 -0
  12. data/lib/kitchen/terraform/client/execute_command.rb +56 -0
  13. data/lib/kitchen/terraform/client/get.rb +35 -0
  14. data/lib/kitchen/terraform/client/output.rb +50 -0
  15. data/lib/kitchen/terraform/client/plan.rb +42 -0
  16. data/lib/kitchen/terraform/client/process_options.rb +87 -0
  17. data/lib/kitchen/terraform/client/validate.rb +35 -0
  18. data/lib/kitchen/terraform/client/version.rb +48 -0
  19. data/lib/{terraform/apply_timeout_config.rb → kitchen/terraform/create_directories.rb} +18 -11
  20. data/lib/kitchen/terraform/define_config_attribute.rb +39 -0
  21. data/lib/kitchen/terraform/define_integer_config_attribute.rb +43 -0
  22. data/lib/kitchen/terraform/define_string_config_attribute.rb +43 -0
  23. data/lib/kitchen/verifier/terraform.rb +186 -38
  24. data/lib/kitchen/verifier/terraform/configure_inspec_runner_attributes.rb +93 -0
  25. data/lib/kitchen/verifier/terraform/configure_inspec_runner_backend.rb +32 -0
  26. data/lib/kitchen/verifier/terraform/configure_inspec_runner_controls.rb +39 -0
  27. data/lib/{terraform/apply_command.rb → kitchen/verifier/terraform/configure_inspec_runner_host.rb} +11 -15
  28. data/lib/{terraform/deprecated_output_parser.rb → kitchen/verifier/terraform/configure_inspec_runner_port.rb} +16 -20
  29. data/lib/{terraform/deprecated_variables_coercer.rb → kitchen/verifier/terraform/configure_inspec_runner_user.rb} +16 -14
  30. data/lib/kitchen/verifier/terraform/enumerate_groups_and_hostnames.rb +67 -0
  31. data/lib/{terraform/version_command.rb → terraform.rb} +1 -5
  32. data/lib/terraform/configurable.rb +18 -61
  33. data/lib/terraform/debug_logger.rb +12 -12
  34. data/lib/terraform/project_version.rb +1 -1
  35. metadata +72 -135
  36. metadata.gz.sig +0 -0
  37. data/lib/terraform/cli_config.rb +0 -29
  38. data/lib/terraform/client.rb +0 -96
  39. data/lib/terraform/color_coercer.rb +0 -35
  40. data/lib/terraform/color_config.rb +0 -32
  41. data/lib/terraform/command.rb +0 -53
  42. data/lib/terraform/command_factory.rb +0 -111
  43. data/lib/terraform/command_option.rb +0 -65
  44. data/lib/terraform/command_options.rb +0 -103
  45. data/lib/terraform/destructive_plan_command.rb +0 -35
  46. data/lib/terraform/directory_config.rb +0 -32
  47. data/lib/terraform/file_configs.rb +0 -36
  48. data/lib/terraform/group.rb +0 -61
  49. data/lib/terraform/group_attributes.rb +0 -42
  50. data/lib/terraform/group_hostnames.rb +0 -38
  51. data/lib/terraform/groups_coercer.rb +0 -43
  52. data/lib/terraform/groups_config.rb +0 -32
  53. data/lib/terraform/integer_coercer.rb +0 -37
  54. data/lib/terraform/no_output_parser.rb +0 -28
  55. data/lib/terraform/output_command.rb +0 -23
  56. data/lib/terraform/output_parser.rb +0 -55
  57. data/lib/terraform/parallelism_config.rb +0 -32
  58. data/lib/terraform/pathname_coercer.rb +0 -40
  59. data/lib/terraform/plan_command.rb +0 -30
  60. data/lib/terraform/prepare_input_file.rb +0 -34
  61. data/lib/terraform/prepare_output_file.rb +0 -36
  62. data/lib/terraform/shell_out.rb +0 -59
  63. data/lib/terraform/show_command.rb +0 -30
  64. data/lib/terraform/simple_coercer.rb +0 -36
  65. data/lib/terraform/simple_config.rb +0 -28
  66. data/lib/terraform/unsupported_version.rb +0 -26
  67. data/lib/terraform/validate_command.rb +0 -23
  68. data/lib/terraform/variable_files_coercer.rb +0 -40
  69. data/lib/terraform/variable_files_config.rb +0 -32
  70. data/lib/terraform/variables_coercer.rb +0 -49
  71. data/lib/terraform/variables_config.rb +0 -32
  72. data/lib/terraform/version.rb +0 -73
@@ -0,0 +1,87 @@
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 "dry/monads"
18
+ require "kitchen/terraform/client"
19
+
20
+ # Processes Terraform Client function options in to Terraform Command-Line Interface (CLI) flags.
21
+ #
22
+ # @see https://www.terraform.io/docs/commands/index.html Terraform commands
23
+ module ::Kitchen::Terraform::Client::ProcessOptions
24
+ extend ::Dry::Monads::Either::Mixin
25
+ extend ::Dry::Monads::Maybe::Mixin
26
+ extend ::Dry::Monads::List::Mixin
27
+ extend ::Dry::Monads::Try::Mixin
28
+
29
+ OPTIONS_FLAGS = {
30
+ color: lambda do |value:|
31
+ "-no-color" if not value
32
+ end,
33
+ destroy: lambda do |value:|
34
+ "-destroy" if value
35
+ end,
36
+ input: lambda do |value:|
37
+ "-input=#{value}"
38
+ end,
39
+ json: lambda do |value:|
40
+ "-json" if value
41
+ end,
42
+ out: lambda do |value:|
43
+ "-out=#{value}"
44
+ end,
45
+ parallelism: lambda do |value:|
46
+ "-parallelism=#{value}"
47
+ end,
48
+ state: lambda do |value:|
49
+ "-state=#{value}"
50
+ end,
51
+ state_out: lambda do |value:|
52
+ "-state-out=#{value}"
53
+ end,
54
+ update: lambda do |value:|
55
+ "-update" if value
56
+ end,
57
+ var: lambda do |value:|
58
+ value.map do |variable_name, variable_value|
59
+ "-var='#{variable_name}=#{variable_value}'"
60
+ end
61
+ end,
62
+ var_file: lambda do |value:|
63
+ value.map do |file|
64
+ "-var-file=#{file}"
65
+ end
66
+ end
67
+ }.freeze
68
+
69
+ # Invokes the function.
70
+ #
71
+ # @param unprocessed_options [::Hash{::Symbol => TrueClass, FalseClass, #to_s, #map}] underscore delimited option keys
72
+ # associated with their values.
73
+ # @return [::Dry::Monads::Either] the result of the function.
74
+ def self.call(unprocessed_options:)
75
+ List(unprocessed_options.to_a).fmap(&method(:Right)).typed(::Dry::Monads::Either).traverse do |member|
76
+ member.bind do |key, value|
77
+ Maybe(::Kitchen::Terraform::Client::ProcessOptions::OPTIONS_FLAGS[key]).bind do |processor|
78
+ Right processor.call value: value
79
+ end.or do
80
+ Left ":#{key} is not a supported Terraform Client option"
81
+ end
82
+ end
83
+ end.fmap do |options|
84
+ options.value.flatten.compact.sort
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,35 @@
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 "kitchen/terraform/client"
18
+ require "kitchen/terraform/client/execute_command"
19
+
20
+ # Validates the syntax of Terraform configuration files.
21
+ #
22
+ # @see https://www.terraform.io/docs/commands/validate.html Terraform validate command
23
+ module ::Kitchen::Terraform::Client::Validate
24
+ # Invokes the function.
25
+ #
26
+ # @param cli [::String] the path of the Terraform CLI to use to execute the validate command.
27
+ # @param directory [::String] the directory containing files to validate.
28
+ # @param logger [#<<] a logger to receive the stdout and stderr of the validate command.
29
+ # @param timeout [::Integer] the maximum execution time in seconds for the validate command.
30
+ # @return [::Dry::Monads::Either] the result of the function.
31
+ def self.call(cli:, directory:, logger:, timeout:)
32
+ ::Kitchen::Terraform::Client::ExecuteCommand.call cli: cli, command: "validate", logger: logger, target: directory,
33
+ timeout: timeout
34
+ end
35
+ end
@@ -0,0 +1,48 @@
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 "dry/monads"
18
+ require "kitchen/terraform/client"
19
+ require "kitchen/terraform/client/execute_command"
20
+
21
+ # Retrieves the version of the Terraform Command-Line Interface (CLI).
22
+ #
23
+ # @see https://www.terraform.io/docs/commands/index.html Terraform commands
24
+ module ::Kitchen::Terraform::Client::Version
25
+ extend ::Dry::Monads::Either::Mixin
26
+
27
+ extend ::Dry::Monads::Maybe::Mixin
28
+
29
+ # Invokes the function.
30
+ #
31
+ # @param cli [::String] the path of the Terraform CLI to use to execute the version command.
32
+ # @param logger [#<<] a logger to receive the stdout and stderr of the version command.
33
+ # @param timeout [::Integer] the time in seconds to wait for the version command to finish.
34
+ # @return [::Dry::Monads::Either] the result of the function.
35
+ def self.call(cli:, logger:, timeout:)
36
+ ::Kitchen::Terraform::Client::ExecuteCommand
37
+ .call(cli: cli, command: "version", logger: logger, timeout: timeout)
38
+ .bind do |output|
39
+ Maybe output.slice /v(\d+\.\d+)/, 1
40
+ end.bind do |major_minor_versions|
41
+ Right Float major_minor_versions
42
+ end.or do |error|
43
+ error.nil? and Left "Terraform client version output did not match 'vX.Y'" or Left error
44
+ end.or do |error|
45
+ Left "Unable to parse Terraform client version output\n#{error}"
46
+ end
47
+ end
48
+ end
@@ -14,19 +14,26 @@
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'
17
+ require "dry/monads"
18
+ require "fileutils"
19
+ require "kitchen/terraform"
19
20
 
20
- module Terraform
21
- # Behaviour for the [:apply_timeout] config option
22
- module ApplyTimeoutConfig
23
- include ::Terraform::SimpleConfig
21
+ # Creates directories on the filesystem.
22
+ module ::Kitchen::Terraform::CreateDirectories
23
+ extend ::Dry::Monads::Either::Mixin
24
+ extend ::Dry::Monads::Try::Mixin
24
25
 
25
- def self.extended(configurable_class)
26
- configurable_class
27
- .configure_required attr: :apply_timeout,
28
- coercer_class: ::Terraform::IntegerCoercer,
29
- default_value: 600
26
+ # Invokes the function.
27
+ #
28
+ # @param directories [::Array<::String>, ::String] the list of directories to create.
29
+ # @return [::Dry::Monads::Either] the result of the function.
30
+ def self.call(directories:)
31
+ Try ::SystemCallError do
32
+ ::FileUtils.makedirs directories
33
+ end.to_either.bind do
34
+ Right "Created directories #{directories}"
35
+ end.or do |error|
36
+ Left error.to_s
30
37
  end
31
38
  end
32
39
  end
@@ -0,0 +1,39 @@
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 "dry-validation"
18
+ require "kitchen"
19
+ require "kitchen/terraform"
20
+
21
+ # Defines a configuration attribute for a plugin class.
22
+ #
23
+ # @see http://dry-rb.org/gems/dry-validation/ DRY Validation
24
+ module ::Kitchen::Terraform::DefineConfigAttribute
25
+ # Invokes the function.
26
+ #
27
+ # @param attribute [::Symbol] the name of the attribute.
28
+ # @param initialize_default_value [::Proc] a proc to lazily provide a default value.
29
+ # @param plugin_class [::Class] the plugin class on which the attribute will be defined.
30
+ # @param schema [::Proc] a proc to define the validation schema of the attribute.
31
+ def self.call(attribute:, initialize_default_value:, plugin_class:, schema:)
32
+ plugin_class.required_config attribute do |_attribute, value, plugin|
33
+ ::Dry::Validation.Schema(&schema).call(value: value).messages.tap do |messages|
34
+ raise ::Kitchen::UserError, "#{plugin.class} configuration: #{attribute} #{messages}" if not messages.empty?
35
+ end
36
+ end
37
+ plugin_class.default_config attribute, &initialize_default_value
38
+ end
39
+ end
@@ -0,0 +1,43 @@
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 "dry-validation"
18
+ require "kitchen"
19
+ require "kitchen/terraform"
20
+ require "kitchen/terraform/define_config_attribute"
21
+
22
+ # Defines an integer configuration attribute for a plugin class.
23
+ #
24
+ # @see http://dry-rb.org/gems/dry-validation/ DRY Validation
25
+ module ::Kitchen::Terraform::DefineIntegerConfigAttribute
26
+ # Invokes the function.
27
+ #
28
+ # @param attribute [::Symbol] the name of the attribute.
29
+ # @param plugin_class [::Class] the plugin class on which the attribute will be defined.
30
+ # @yieldparam plugin [::Kitchen::Driver::Terraform, ::Kitchen::Provisioner::Terraform, ::Kitchen::Verifier::Terraform]
31
+ # an instance of the plugin class.
32
+ # @yieldreturn [::Object] the default value of the attribute.
33
+ def self.call(attribute:, plugin_class:, &initialize_default_value)
34
+ ::Kitchen::Terraform::DefineConfigAttribute.call(
35
+ attribute: attribute,
36
+ initialize_default_value: initialize_default_value,
37
+ plugin_class: plugin_class,
38
+ schema: lambda do
39
+ required(:value).filled :int?
40
+ end
41
+ )
42
+ end
43
+ end
@@ -0,0 +1,43 @@
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 "dry-validation"
18
+ require "kitchen"
19
+ require "kitchen/terraform"
20
+ require "kitchen/terraform/define_config_attribute"
21
+
22
+ # Defines a string configuration attribute for a plugin class.
23
+ #
24
+ # @see http://dry-rb.org/gems/dry-validation/ DRY Validation
25
+ module ::Kitchen::Terraform::DefineStringConfigAttribute
26
+ # Invokes the function.
27
+ #
28
+ # @param attribute [::Symbol] the name of the attribute.
29
+ # @param plugin_class [::Class] the plugin class on which the attribute will be defined.
30
+ # @yieldparam plugin [::Kitchen::Driver::Terraform, ::Kitchen::Provisioner::Terraform, ::Kitchen::Verifier::Terraform]
31
+ # an instance of the plugin class.
32
+ # @yieldreturn [::Object] the default value of the attribute.
33
+ def self.call(attribute:, plugin_class:, &initialize_default_value)
34
+ ::Kitchen::Terraform::DefineConfigAttribute.call(
35
+ attribute: attribute,
36
+ initialize_default_value: initialize_default_value,
37
+ plugin_class: plugin_class,
38
+ schema: lambda do
39
+ required(:value).filled :str?
40
+ end
41
+ )
42
+ end
43
+ end
@@ -14,56 +14,204 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'kitchen/verifier/inspec'
18
- require 'terraform/configurable'
19
- require 'terraform/groups_config'
17
+ require "dry/monads"
18
+ require "kitchen"
19
+ require "kitchen/terraform/define_config_attribute"
20
+ require "kitchen/verifier/inspec"
21
+ require "terraform/configurable"
20
22
 
21
- module Kitchen
22
- module Verifier
23
- # Runs tests post-converge to confirm that instances in the Terraform state
24
- # are in an expected state
25
- class Terraform < ::Kitchen::Verifier::Inspec
26
- extend ::Terraform::GroupsConfig
23
+ # The verifier utilizes the InSpec infrastructure testing framework to verify the behaviour and state of resources in
24
+ # the Terraform state.
25
+ #
26
+ # InSpec profiles are assumed to be located in `test/integration/<suite-name>/`.
27
+ #
28
+ # === Configuration
29
+ #
30
+ # ==== Example .kitchen.yml snippet
31
+ #
32
+ # verifier:
33
+ # name: terraform
34
+ # groups:
35
+ # - name: group_one
36
+ # attributes:
37
+ # foo: bar
38
+ # controls:
39
+ # - biz
40
+ # hostnames: hostnames_output
41
+ # port: 123
42
+ # username: test-user
43
+ # - name: group_two
44
+ #
45
+ # ==== Attributes
46
+ #
47
+ # ===== groups
48
+ #
49
+ # Description:: A collection of maps that configure which InSpec profile will be run against different resources in the
50
+ # Terraform state.
51
+ #
52
+ # Type:: Array
53
+ #
54
+ # Status:: Optional
55
+ #
56
+ # Default:: +[]+
57
+ #
58
+ # ====== name
59
+ #
60
+ # Description:: A label that is used to identify the group.
61
+ #
62
+ # Type:: String
63
+ #
64
+ # Status:: Required
65
+ #
66
+ # ====== attributes
67
+ #
68
+ # Description:: A map that associates InSpec profile attribute names to Terraform output variable names.
69
+ #
70
+ # Type:: Hash
71
+ #
72
+ # Status:: Optional
73
+ #
74
+ # Default:: +{}+
75
+ #
76
+ # ====== controls
77
+ #
78
+ # Description:: A collection of controls to selectively include from the suite's InSpec profile.
79
+ #
80
+ # Type:: Array
81
+ #
82
+ # Status:: Optional
83
+ #
84
+ # Default:: +[]+
85
+ #
86
+ # ====== hostnames
87
+ #
88
+ # Description:: The name of a Terraform output variable of type String or Array which contains one or more hostnames
89
+ # from the Terraform state that will be targeted with the suite's InSpec profile.
90
+ #
91
+ # Type:: String
92
+ #
93
+ # Status:: Optional
94
+ #
95
+ # ====== port
96
+ #
97
+ # Description:: The port to use when connecting to the group's hosts with Secure Shell (SSH).
98
+ #
99
+ # Type:: Integer
100
+ #
101
+ # Status:: Optional
102
+ #
103
+ # ====== username
104
+ #
105
+ # Description:: The username to use when connecting to the group's hosts with SSH.
106
+ #
107
+ # Type:: String
108
+ #
109
+ # Status:: Optional
110
+ #
111
+ # @see https://en.wikipedia.org/wiki/Secure_Shell Secure Shell
112
+ # @see https://www.inspec.io/ InSpec
113
+ # @see https://www.inspec.io/docs/reference/dsl_inspec/ InSpec Controls
114
+ # @see https://www.inspec.io/docs/reference/profiles/ InSpec Profiles
115
+ # @see https://www.terraform.io/docs/configuration/outputs.html Terraform Output Variables
116
+ # @see https://www.terraform.io/docs/state/index.html Terraform State
117
+ # @version 2
118
+ class ::Kitchen::Verifier::Terraform < ::Kitchen::Verifier::Inspec
119
+ kitchen_verifier_api_version 2
27
120
 
28
- include ::Terraform::Configurable
121
+ ::Kitchen::Terraform::DefineConfigAttribute.call(
122
+ attribute: :groups,
123
+ initialize_default_value: lambda do |_plugin|
124
+ []
125
+ end,
126
+ plugin_class: self,
127
+ schema: lambda do
128
+ configure do
129
+ def self.messages
130
+ super.merge en: {
131
+ errors: {
132
+ keys_are_strings_or_symbols?: "keys must be strings or symbols",
133
+ values_are_strings?: "values must be strings"
134
+ }
135
+ }
136
+ end
29
137
 
30
- kitchen_verifier_api_version 2
138
+ def keys_are_strings_or_symbols?(hash)
139
+ hash.keys.all? do |key|
140
+ key.is_a?(::String) | key.is_a?(::Symbol)
141
+ end
142
+ end
31
143
 
32
- def call(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
144
+ def values_are_strings?(hash)
145
+ hash.values.all? do |value|
146
+ value.is_a? ::String
147
+ end
148
+ end
149
+ end
150
+ required(:value).each do
151
+ schema do
152
+ required(:name).filled :str?
153
+ optional(:attributes).value :hash?, :keys_are_strings_or_symbols?, :values_are_strings?
154
+ optional(:controls).each :filled?, :str?
155
+ optional(:hostnames).value :str?
156
+ optional(:port).value :int?
157
+ optional(:username).value :str?
40
158
  end
41
- rescue ::Kitchen::StandardError, ::SystemCallError => error
42
- raise ::Kitchen::ActionFailed, error.message
43
159
  end
160
+ end
161
+ )
44
162
 
45
- private
163
+ include ::Dry::Monads::Either::Mixin
46
164
 
47
- attr_accessor :group
165
+ include ::Terraform::Configurable
48
166
 
49
- def configure_backend(options:)
50
- /(local)host/.match group.hostname do |match|
51
- options.merge! 'backend' => match[1]
52
- end
53
- end
167
+ # The verifier enumerates through each hostname of each group and verifies the associated InSpec controls.
168
+ #
169
+ # @example
170
+ # `kitchen verify suite-name`
171
+ # @param state [::Hash] the mutable instance and verifier state.
172
+ # @raise [::Kitchen::ActionFailed] if the result of the action is a failure.
173
+ # @return [::Dry::Monads::Either] the result of the action.
174
+ def call(state)
175
+ self.class::EnumerateGroupsAndHostnames.call driver: driver, groups: config.fetch(:groups) do |group:, hostname:|
176
+ state.store :group, group
177
+ state.store :hostname, hostname
178
+ info "Verifying host '#{hostname}' of group '#{group.fetch :name}'"
179
+ super state
180
+ end.fmap do |success|
181
+ logger.debug success
182
+ end.or do |failure|
183
+ raise ::Kitchen::ActionFailed, failure
184
+ end
185
+ end
54
186
 
55
- def resolve_groups(&block)
56
- config[:groups]
57
- .each { |group| group.resolve client: silent_client, &block }
58
- end
187
+ private
59
188
 
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
189
+ # Modifies the Inspec Runner options generated by the kitchen-inspec verifier to support the verification of each
190
+ # group's hosts.
191
+ #
192
+ # @api private
193
+ # @return [::Hash] Inspec Runner options.
194
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb ::Inspec::Runner
195
+ # @see https://github.com/chef/kitchen-inspec/blob/master/lib/kitchen/verifier.rb kitchen-inspec verifier
196
+ def runner_options(transport, state = {}, platform = nil, suite = nil)
197
+ super(transport, state, platform, suite).tap do |options|
198
+ self.class::ConfigureInspecRunnerBackend.call hostname: state.fetch(:hostname), options: options
199
+ self.class::ConfigureInspecRunnerHost.call hostname: state.fetch(:hostname), options: options
200
+ self.class::ConfigureInspecRunnerPort.call group: state.fetch(:group), options: options
201
+ self.class::ConfigureInspecRunnerUser.call group: state.fetch(:group), options: options
202
+ self.class::ConfigureInspecRunnerAttributes
203
+ .call(driver: driver, group: state.fetch(:group), terraform_state: driver[:state]).bind do |attributes|
204
+ config.store :attributes, attributes
65
205
  end
66
- end
206
+ self.class::ConfigureInspecRunnerControls.call group: state.fetch(:group), options: options
67
207
  end
68
208
  end
69
209
  end
210
+
211
+ require "kitchen/verifier/terraform/configure_inspec_runner_attributes"
212
+ require "kitchen/verifier/terraform/configure_inspec_runner_backend"
213
+ require "kitchen/verifier/terraform/configure_inspec_runner_controls"
214
+ require "kitchen/verifier/terraform/configure_inspec_runner_host"
215
+ require "kitchen/verifier/terraform/configure_inspec_runner_port"
216
+ require "kitchen/verifier/terraform/configure_inspec_runner_user"
217
+ require "kitchen/verifier/terraform/enumerate_groups_and_hostnames"