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,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