kitchen-terraform 0.7.0 → 1.0.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 (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,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2016-2017 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/verifier/terraform"
19
+
20
+ # Configures the InSpec profile attributes for the Inspec::Runner used by the verifier to verify a group.
21
+ #
22
+ # Three different maps are merged to create the profile attributes.
23
+ #
24
+ # The first map is comprised of attributes that are external to the Terraform state.
25
+ #
26
+ # {
27
+ # "terraform_state" => "/path/to/terraform/state"
28
+ # }
29
+ #
30
+ # The second map is comprised of attributes that represent the Terraform output variables of the Terraform state. This
31
+ # map takes precedence in any key conflicts with the first map.
32
+ #
33
+ # {
34
+ # "first_output_variable_name" => "first_output_variable_value",
35
+ # "second_output_variable_name" => "second_output_variable_value"
36
+ # }
37
+ #
38
+ # The third map is comprised of attributes defined by a group's +:attributes+; the keys are converted to strings and the
39
+ # values are assumed to be Terraform output variable names which are resolved. This map takes precedence in any key
40
+ # conflicts with the second map.
41
+ #
42
+ # {
43
+ # first_attribute_name: "second_output_variable_name"
44
+ # }
45
+ #
46
+ # # becomes
47
+ #
48
+ # {
49
+ # "first_attribute_name" => "second_output_variable_value"
50
+ # }
51
+ #
52
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb Inspec::Runner
53
+ # @see https://github.com/chef/kitchen-inspec/blob/master/lib/kitchen/verifier/inspec.rb kitchen-inspec verifier
54
+ # @see https://www.inspec.io/docs/reference/profiles/ InSpec Profiles
55
+ # @see https://www.terraform.io/docs/configuration/outputs.html Terraform output variables
56
+ # @see https://www.terraform.io/docs/state/index.html Terraform state
57
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerAttributes
58
+ extend ::Dry::Monads::Either::Mixin
59
+
60
+ extend ::Dry::Monads::Maybe::Mixin
61
+
62
+ extend ::Dry::Monads::Try::Mixin
63
+
64
+ # Invokes the function
65
+ #
66
+ # @param driver [::Kitchen::Driver::Terraform] a kitchen-terraform driver
67
+ # @param group [::Hash] a kitchen-terraform verifier group
68
+ # @param terraform_state [::String] the path of a Terraform state file
69
+ # @return [::Dry::Monads::Either] the result of the function
70
+ def self.call(driver:, group:, terraform_state:)
71
+ Right("terraform_state" => terraform_state).bind do |attributes|
72
+ driver.output.fmap do |output|
73
+ [attributes, output]
74
+ end
75
+ end.bind do |attributes, output|
76
+ Try ::KeyError do
77
+ output.each_pair do |output_name, output_body|
78
+ attributes.store output_name, output_body.fetch("value")
79
+ end
80
+ [attributes, output]
81
+ end
82
+ end.fmap do |attributes, output|
83
+ Maybe(group[:attributes]).bind do |group_attributes|
84
+ group_attributes.each_pair do |attribute_name, output_name|
85
+ attributes.store attribute_name.to_s, output.fetch(output_name.to_s).fetch("value")
86
+ end
87
+ end
88
+ attributes
89
+ end.to_either.or do |error|
90
+ Left "configuring Inspec::Runner attributes failed\n#{error}"
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,32 @@
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/verifier/terraform"
18
+
19
+ # Configures the backend for the Inspec::Runner used by the verifier to verify a group's host.
20
+ #
21
+ # If the hostname is "localhost" then the existing backend is overwritten to be "local".
22
+ #
23
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb Inspec::Runner
24
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerBackend
25
+ # Invokes the function.
26
+ #
27
+ # @param hostname [::String] the hostname being verified.
28
+ # @param options [::Hash] the verifier's Inspec::Runner options.
29
+ def self.call(hostname:, options:)
30
+ hostname == "localhost" and options.store "backend", "local"
31
+ end
32
+ 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/monads"
18
+ require "kitchen/verifier/terraform"
19
+
20
+ # Configures a group's InSpec profile controls to be inclued by the Inspec::Runner used by the verifier.
21
+ #
22
+ # If a group omits +:controls+ or if +:controls+ is empty then all of the profile's controls will be included.
23
+ #
24
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb ::Inspec::Runner
25
+ # @see https://www.inspec.io/docs/reference/profiles/ InSpec profiles
26
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerControls
27
+ extend ::Dry::Monads::Either::Mixin
28
+ extend ::Dry::Monads::Maybe::Mixin
29
+
30
+ # Invokes the function
31
+ #
32
+ # @param group [::Hash] the group being verified.
33
+ # @param options [:Hash] the verifier's Inspec::Runner's options.
34
+ def self.call(group:, options:)
35
+ Maybe(group[:controls]).bind do |controls|
36
+ options.store :controls, controls
37
+ end
38
+ end
39
+ end
@@ -14,21 +14,17 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'terraform/command'
18
- require 'terraform/prepare_input_file'
19
- require 'terraform/prepare_output_file'
17
+ require "kitchen/verifier/terraform"
20
18
 
21
- module Terraform
22
- # A command to apply an execution plan
23
- class ApplyCommand < ::Terraform::Command
24
- private
25
-
26
- def initialize(target: '')
27
- super
28
- preparations.concat [
29
- ::Terraform::PrepareOutputFile.new(file: options.state_out),
30
- ::Terraform::PrepareInputFile.new(file: target)
31
- ]
32
- end
19
+ # Configures the host for the Inspec::Runner used by the verifier to verify a group's host.
20
+ #
21
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb Inspec::Runner
22
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerHost
23
+ # Invokes the function.
24
+ #
25
+ # @param hostname [::String] the hostname of a group's host.
26
+ # @param options [::Hash] the Inspec::Runner's options.
27
+ def self.call(hostname:, options:)
28
+ options.store "host", hostname
33
29
  end
34
30
  end
@@ -14,28 +14,24 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- module Terraform
18
- # A parser for deprecated output command values
19
- class DeprecatedOutputParser
20
- def each_name(&block)
21
- output.scan(/(\w+)\s*=/).flatten.each(&block)
22
- end
23
-
24
- def iterate_parsed_output(&block)
25
- Array(parsed_output)
26
- .each { |list_value| list_value.split(',').each(&block) }
27
- end
28
-
29
- def parsed_output
30
- output.strip
31
- end
32
-
33
- private
17
+ require "dry/monads"
18
+ require "kitchen/verifier/terraform"
34
19
 
35
- attr_accessor :output
20
+ # Configures the port for the Inspec::Runner used by the verifier to verify a group.
21
+ #
22
+ # The default port is the transport's +:port+.
23
+ #
24
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb Inspec::Runner
25
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerPort
26
+ extend ::Dry::Monads::Maybe::Mixin
36
27
 
37
- def initialize(output:)
38
- self.output = output
28
+ # Invokes the function.
29
+ #
30
+ # @param group [::Hash] the group being verified.
31
+ # @param options [::Hash] the Inspec::Runner's options.
32
+ def self.call(group:, options:)
33
+ Maybe(group[:port]).bind do |port|
34
+ options.store "port", port
39
35
  end
40
36
  end
41
37
  end
@@ -14,22 +14,24 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- module Terraform
18
- # Coerces deprecated variables config
19
- class DeprecatedVariablesCoercer
20
- def coerce(attr:, value:)
21
- configurable.config_deprecated attr: attr, remediation: 'Use a mapping',
22
- type: 'a list or string'
23
- configurable[attr] =
24
- ::Hash[Array(value).map { |string| string.split '=' }]
25
- end
26
-
27
- private
17
+ require "dry/monads"
18
+ require "kitchen/verifier/terraform"
28
19
 
29
- attr_accessor :configurable
20
+ # Configures the user for the Inspec::Runner used by the verifier to verify a group.
21
+ #
22
+ # The default user is the transport's +:username+.
23
+ #
24
+ # @see https://github.com/chef/inspec/blob/master/lib/inspec/runner.rb Inspec::Runner
25
+ module ::Kitchen::Verifier::Terraform::ConfigureInspecRunnerUser
26
+ extend ::Dry::Monads::Maybe::Mixin
30
27
 
31
- def initialize(configurable:)
32
- self.configurable = configurable
28
+ # Invoke the function.
29
+ #
30
+ # @param group [::Hash] the group being verified.
31
+ # @param options [::Hash] the Inspec::Runner's options.
32
+ def self.call(group:, options:)
33
+ Maybe(group[:username]).bind do |username|
34
+ options.store "user", username
33
35
  end
34
36
  end
35
37
  end
@@ -0,0 +1,67 @@
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/verifier/terraform"
19
+
20
+ # Enumerates each group and the hostnames of each group.
21
+ #
22
+ # If a group associates +:hostnames+ with a value then that value is assumed to be the name of a Terraform output
23
+ # variable which has a value of a string or array containing one or more hostnames; those hostnames will be enumerated
24
+ # with the group.
25
+ #
26
+ # If a group omits +:hostnames+ then the hostname +"localhost"+ will be enumerated with that group; this hostname will
27
+ # cause the InSpec profile to be executed locally and enable verification of resources in the Terraform state without
28
+ # the use of Secure Shell (SSH).
29
+ #
30
+ # @see https://en.wikipedia.org/wiki/Secure_Shell Secure Shell
31
+ # @see https://www.terraform.io/docs/configuration/outputs.html Terraform output variables
32
+ # @see https://www.terraform.io/docs/state/index.html Terraform state
33
+ module ::Kitchen::Verifier::Terraform::EnumerateGroupsAndHostnames
34
+ extend ::Dry::Monads::Either::Mixin
35
+ extend ::Dry::Monads::List::Mixin
36
+ extend ::Dry::Monads::Maybe::Mixin
37
+ extend ::Dry::Monads::Try::Mixin
38
+
39
+ # Invokes the function.
40
+ #
41
+ # @param driver [::Kitchen::Driver::Terraform] a kitchen-terraform driver.
42
+ # @param groups [::Array] a collection of groups.
43
+ # @return [::Dry::Monads::Either] the result of the function.
44
+ # @yieldparam group [::Hash] the group from which hostnamess are being enumerated.
45
+ # @yieldparam hostname [::String] a hostname from the group.
46
+ def self.call(driver:, groups:, &block)
47
+ List(groups).fmap(&method(:Right)).typed(::Dry::Monads::Either).traverse do |member|
48
+ member.bind do |group|
49
+ if group.key? :hostnames
50
+ driver.output.bind do |output|
51
+ Try ::KeyError do
52
+ Array(output.fetch(group.fetch(:hostnames)).fetch("value")).each do |hostname|
53
+ block.call group: group, hostname: hostname
54
+ end
55
+ end.to_either.or do |error|
56
+ Left error.to_s
57
+ end
58
+ end
59
+ else
60
+ Right block.call group: group, hostname: "localhost"
61
+ end
62
+ end
63
+ end.fmap do
64
+ "finished enumeration of groups and hostnames"
65
+ end
66
+ end
67
+ end
@@ -14,10 +14,6 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'terraform/command'
18
-
17
+ # Namespace for kitchen-terraform
19
18
  module Terraform
20
- # A command to obtain the version
21
- class VersionCommand < ::Terraform::Command
22
- end
23
19
  end
@@ -14,72 +14,29 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'forwardable'
18
- require 'kitchen'
19
- require 'pathname'
20
- require 'terraform/client'
21
- require 'terraform/debug_logger'
22
- require 'terraform/project_version'
17
+ require "forwardable"
18
+ require "kitchen"
19
+ require "terraform"
20
+ require "terraform/debug_logger"
21
+ require "terraform/project_version"
23
22
 
24
- module Terraform
25
- # Behaviour for objects that extend ::Kitchen::Configurable
26
- module Configurable
27
- extend ::Forwardable
23
+ # Miscellaneous behaviour for objects that extend ::Kitchen::Configurable.
24
+ module ::Terraform::Configurable
25
+ extend ::Forwardable
28
26
 
29
- def_delegator :config, :[]=
27
+ def_delegator :config, :[]=
30
28
 
31
- def_delegators :instance, :driver, :provisioner, :transport
29
+ def_delegators :instance, :driver, :provisioner, :transport
32
30
 
33
- def self.included(configurable_class)
34
- configurable_class.plugin_version ::Terraform::PROJECT_VERSION
35
- end
36
-
37
- def client
38
- ::Terraform::Client.new config: verbose_config, logger: logger
39
- end
40
-
41
- def config_deprecated(attr:, remediation:, type:)
42
- log_deprecation aspect: "#{formatted_config attr: attr} as #{type}",
43
- remediation: remediation
44
- end
45
-
46
- def config_error(attr:, expected:)
47
- raise ::Kitchen::UserError, "#{formatted_config attr: attr} must be " \
48
- "interpretable as #{expected}"
49
- end
50
-
51
- def debug_logger
52
- ::Terraform::DebugLogger.new logger: logger
53
- end
54
-
55
- def instance_pathname(filename:)
56
- ::Pathname.new(config[:kitchen_root])
57
- .join '.kitchen', 'kitchen-terraform', instance.name, filename
58
- end
59
-
60
- def log_deprecation(aspect:, remediation:)
61
- logger.warn 'DEPRECATION NOTICE'
62
- logger
63
- .warn "Support for #{aspect} will be dropped in kitchen-terraform v1.0"
64
- logger.warn remediation
65
- end
66
-
67
- def silent_client
68
- ::Terraform::Client.new config: silent_config, logger: debug_logger
69
- end
70
-
71
- private
72
-
73
- def formatted_config(attr:)
74
- "#{self.class}#{instance.to_str}#config[:#{attr}]"
75
- end
31
+ def self.included(configurable_class)
32
+ configurable_class.plugin_version ::Terraform::PROJECT_VERSION
33
+ end
76
34
 
77
- def silent_config
78
- verbose_config.tap { |config| config[:color] = false }
79
- end
35
+ def debug_logger
36
+ @debug_logger ||= ::Terraform::DebugLogger.new logger: logger
37
+ end
80
38
 
81
- def verbose_config
82
- provisioner.dup.tap { |config| config[:cli] = driver[:cli] }
83
- end
39
+ def instance_pathname(filename:)
40
+ ::File.join config.fetch(:kitchen_root), ".kitchen", "kitchen-terraform", instance.name, filename
84
41
  end
85
42
  end