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
@@ -0,0 +1,95 @@
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 'set'
18
+ require_relative 'command_option'
19
+
20
+ module Terraform
21
+ # Options for commands
22
+ class CommandOptions
23
+ def color=(value)
24
+ store key: { false => 'no-color' }.fetch(value) { return }
25
+ end
26
+
27
+ def destroy=(value)
28
+ store key: 'destroy', value: value
29
+ end
30
+
31
+ def input=(value)
32
+ store key: 'input', value: value
33
+ end
34
+
35
+ def json=(value)
36
+ store key: 'json', value: value
37
+ end
38
+
39
+ def out
40
+ fetch key: 'out'
41
+ end
42
+
43
+ def out=(value)
44
+ store key: 'out', value: value
45
+ end
46
+
47
+ def parallelism=(value)
48
+ store key: 'parallelism', value: value
49
+ end
50
+
51
+ def state
52
+ fetch key: 'state'
53
+ end
54
+
55
+ def state=(value)
56
+ store key: 'state', value: value
57
+ end
58
+
59
+ def update=(value)
60
+ store key: 'update', value: value
61
+ end
62
+
63
+ def var=(value)
64
+ value.each_pair do |variable_name, variable_value|
65
+ store key: 'var', value: "'#{variable_name}=#{variable_value}'"
66
+ end
67
+ end
68
+
69
+ def var_file=(value)
70
+ value.each { |file| store key: 'var-file', value: file }
71
+ end
72
+
73
+ def to_s
74
+ options.each_with_object ::String.new do |option, string|
75
+ string.concat "#{option} "
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ attr_accessor :options
82
+
83
+ def fetch(key:)
84
+ options.find { |option| option.key == key }.value
85
+ end
86
+
87
+ def initialize(options: ::Set.new)
88
+ self.options = options
89
+ end
90
+
91
+ def store(**keyword_arguments)
92
+ options.add ::Terraform::CommandOption.new(**keyword_arguments)
93
+ end
94
+ end
95
+ end
@@ -16,45 +16,70 @@
16
16
 
17
17
  require 'forwardable'
18
18
  require 'kitchen'
19
- require_relative 'version'
19
+ require 'pathname'
20
+ require 'terraform/client'
21
+ require 'terraform/debug_logger'
22
+ require 'terraform/project_version'
20
23
 
21
24
  module Terraform
22
- # Common logic for classes that include Kitchen::Configurable
25
+ # Behaviour for objects that extend ::Kitchen::Configurable
23
26
  module Configurable
24
- extend Forwardable
27
+ extend ::Forwardable
28
+
29
+ def_delegator :config, :[]=
25
30
 
26
31
  def_delegators :instance, :driver, :provisioner, :transport
27
32
 
28
33
  def self.included(configurable_class)
29
- configurable_class.plugin_version VERSION
34
+ configurable_class.plugin_version ::Terraform::PROJECT_VERSION
35
+ end
36
+
37
+ def client
38
+ ::Terraform::Client.new config: verbose_config, logger: logger
30
39
  end
31
40
 
32
- def config_deprecated(attribute:, remediation:, type:, version:)
33
- log_deprecation aspect: "#{formatted(attribute: attribute)} as #{type}",
34
- remediation: remediation, version: version
41
+ def config_deprecated(attr:, remediation:, type:)
42
+ log_deprecation aspect: "#{formatted_config attr: attr} as #{type}",
43
+ remediation: remediation
35
44
  end
36
45
 
37
- def config_error(attribute:, expected:)
38
- raise Kitchen::UserError, "#{formatted attribute: attribute} must be " \
39
- "interpretable as #{expected}"
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
40
53
  end
41
54
 
42
55
  def instance_pathname(filename:)
43
- File.join config[:kitchen_root], '.kitchen', 'kitchen-terraform',
44
- instance.name, filename
56
+ ::Pathname.new(config[:kitchen_root])
57
+ .join '.kitchen', 'kitchen-terraform', instance.name, filename
45
58
  end
46
59
 
47
- def log_deprecation(aspect:, remediation:, version:)
60
+ def log_deprecation(aspect:, remediation:)
48
61
  logger.warn 'DEPRECATION NOTICE'
49
- logger.warn "Support for #{aspect} will be dropped in " \
50
- "kitchen-terraform v#{version}"
62
+ logger
63
+ .warn "Support for #{aspect} will be dropped in kitchen-terraform v1.0"
51
64
  logger.warn remediation
52
65
  end
53
66
 
67
+ def silent_client
68
+ ::Terraform::Client.new config: silent_config, logger: debug_logger
69
+ end
70
+
54
71
  private
55
72
 
56
- def formatted(attribute:)
57
- "#{self.class}#{instance.to_str}#config[:#{attribute}]"
73
+ def formatted_config(attr:)
74
+ "#{self.class}#{instance.to_str}#config[:#{attr}]"
75
+ end
76
+
77
+ def silent_config
78
+ verbose_config.tap { |config| config[:color] = false }
79
+ end
80
+
81
+ def verbose_config
82
+ provisioner.dup.tap { |config| config[:cli] = driver[:cli] }
58
83
  end
59
84
  end
60
85
  end
@@ -15,17 +15,20 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module Terraform
18
- # Behaviour for OutputCommand with Terraform 0.6
19
- module ZeroSixOutput
20
- def options
21
- "-state=#{state}"
18
+ # Wrapper for a logger to always use the debug level
19
+ class DebugLogger
20
+ def debug(message)
21
+ logger.debug message
22
22
  end
23
23
 
24
+ alias << debug
25
+
24
26
  private
25
27
 
26
- def processed_output(raw_output:)
27
- return raw_output if return_raw
28
- raw_output.chomp.tap { |value| return list ? value.split(',') : value }
28
+ attr_accessor :logger
29
+
30
+ def initialize(logger:)
31
+ self.logger = logger
29
32
  end
30
33
  end
31
34
  end
@@ -0,0 +1,41 @@
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
+ 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
34
+
35
+ attr_accessor :output
36
+
37
+ def initialize(output:)
38
+ self.output = output
39
+ end
40
+ end
41
+ 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
+ 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
28
+
29
+ attr_accessor :configurable
30
+
31
+ def initialize(configurable:)
32
+ self.configurable = configurable
33
+ end
34
+ end
35
+ end
@@ -14,14 +14,17 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ require 'delegate'
18
+
17
19
  module Terraform
18
- # Logic to extend a command's behaviour based on the Terraform version
19
- module CommandExtender
20
- def extend_behaviour(version:)
21
- extend version_behaviours.fetch(
22
- version_behaviours.keys
23
- .find { |extended_version| extended_version =~ version }
24
- ) { return }
20
+ # A deprecated version of Terraform
21
+ class DeprecatedVersion < ::SimpleDelegator
22
+ def if_deprecated
23
+ yield
24
+ end
25
+
26
+ def if_json_not_supported
27
+ yield
25
28
  end
26
29
  end
27
30
  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 'terraform/prepare_input_file'
18
+ require 'terraform/plan_command'
19
+
20
+ module Terraform
21
+ # A command to plan a destructive execution
22
+ class DestructivePlanCommand < ::Terraform::PlanCommand
23
+ def name
24
+ 'plan'
25
+ end
26
+
27
+ private
28
+
29
+ def initialize(target: '')
30
+ super
31
+ preparations
32
+ .push ::Terraform::PrepareInputFile.new file: options.state
33
+ end
34
+ end
35
+ end
@@ -14,14 +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/pathname_coercer'
18
+ require 'terraform/simple_config'
19
+
17
20
  module Terraform
18
21
  # Behaviour for the [:directory] config option
19
22
  module DirectoryConfig
20
- def self.included(configurable_class)
21
- configurable_class.default_config :directory do |configurable|
22
- configurable[:kitchen_root]
23
- end
24
- configurable_class.expand_path_for :directory
23
+ include ::Terraform::SimpleConfig
24
+
25
+ def self.extended(configurable_class)
26
+ configurable_class.configure_required(
27
+ attr: :directory, coercer_class: ::Terraform::PathnameCoercer,
28
+ default_value: ->(configurable) { configurable[:kitchen_root] }
29
+ )
25
30
  end
26
31
  end
27
32
  end
@@ -0,0 +1,36 @@
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 'terraform/pathname_coercer'
18
+ require 'terraform/simple_config'
19
+
20
+ module Terraform
21
+ # Behaviour for the [:plan] and [:state] config options
22
+ module FileConfigs
23
+ include ::Terraform::SimpleConfig
24
+
25
+ def self.extended(configurable_class)
26
+ %i(plan state).each do |attr|
27
+ configurable_class.configure_required(
28
+ attr: attr, coercer_class: ::Terraform::PathnameCoercer,
29
+ default_value: lambda do |configurable|
30
+ configurable.instance_pathname filename: "terraform.tf#{attr}"
31
+ end
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
@@ -14,17 +14,10 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require_relative 'command'
17
+ require 'terraform/command'
18
18
 
19
19
  module Terraform
20
- # Command to get modules
21
- class GetCommand < Command
22
- def name
23
- 'get'
24
- end
25
-
26
- def options
27
- '-update=true'
28
- end
20
+ # A command to get dependency modules
21
+ class GetCommand < ::Terraform::Command
29
22
  end
30
23
  end
@@ -14,48 +14,48 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require 'kitchen/util'
17
+ require 'hashie/dash'
18
+ require 'hashie/extensions/dash/coercion'
19
+ require 'terraform/group_attributes'
20
+ require 'terraform/group_hostnames'
18
21
 
19
22
  module Terraform
20
23
  # Group of Terraform server instances to be verified
21
- class Group
22
- def each_attribute(&block)
23
- data[:attributes].dup.each_pair(&block)
24
- end
24
+ class Group < ::Hashie::Dash
25
+ include ::Hashie::Extensions::Dash::Coercion
25
26
 
26
- def hostnames
27
- data[:hostnames]
28
- end
27
+ property :attributes, coerce: ::Terraform::GroupAttributes,
28
+ default: ::Terraform::GroupAttributes.new
29
29
 
30
- def if_local
31
- yield if hostnames.empty?
32
- end
30
+ property :controls, coerce: ::Array[::String], default: []
33
31
 
34
- def name
35
- data[:name]
36
- end
32
+ property :hostname, coerce: ::String
37
33
 
38
- def options
39
- {
40
- attributes: attributes, controls: data[:controls], port: data[:port],
41
- user: data[:username]
42
- }
43
- end
34
+ property :hostnames, coerce: ::Terraform::GroupHostnames,
35
+ default: ::Terraform::GroupHostnames.new
44
36
 
45
- def store_attribute(key:, value:)
46
- data[:attributes][key] = value
47
- end
37
+ property :name, coerce: ::String, required: true
48
38
 
49
- private
39
+ property :port
40
+
41
+ coerce_key :port, ->(value) { Integer value }
42
+
43
+ property :username, coerce: ::String
50
44
 
51
- attr_accessor :data
45
+ def description
46
+ "host '#{hostname}' of group '#{name}'"
47
+ end
52
48
 
53
- def attributes
54
- ::Kitchen::Util.stringified_hash data[:attributes]
49
+ def resolve(client:)
50
+ attributes.resolve client: client
51
+ hostnames
52
+ .resolve(client: client) { |hostname| yield merge hostname: hostname }
55
53
  end
56
54
 
57
- def initialize(data:)
58
- self.data = data
55
+ private
56
+
57
+ def initialize(attributes = {}, &block)
58
+ super Hash(attributes), &block
59
59
  end
60
60
  end
61
61
  end