kitchen-terraform 3.0.0 → 3.1.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +342 -46
- data/lib/kitchen/driver/terraform.rb +62 -130
- data/lib/kitchen/provisioner/terraform.rb +7 -8
- data/lib/kitchen/terraform/client_version_verifier.rb +25 -23
- data/lib/kitchen/terraform/command.rb +21 -0
- data/lib/kitchen/terraform/command/output.rb +71 -0
- data/lib/kitchen/terraform/config_attribute/backend_configurations.rb +1 -1
- data/lib/kitchen/terraform/config_attribute/groups.rb +60 -33
- data/lib/kitchen/terraform/config_attribute/variables.rb +1 -1
- data/lib/kitchen/terraform/error.rb +21 -0
- data/lib/kitchen/terraform/shell_out.rb +51 -32
- data/lib/kitchen/terraform/version.rb +1 -1
- data/lib/kitchen/verifier/terraform.rb +20 -27
- data/lib/kitchen/verifier/terraform/configure_inspec_runner_attributes.rb +16 -27
- data/lib/kitchen/verifier/terraform/configure_inspec_runner_controls.rb +9 -7
- data/lib/kitchen/verifier/terraform/configure_inspec_runner_port.rb +9 -6
- data/lib/kitchen/verifier/terraform/configure_inspec_runner_ssh_key.rb +8 -10
- data/lib/kitchen/verifier/terraform/configure_inspec_runner_user.rb +9 -6
- data/lib/kitchen/verifier/terraform/enumerate_groups_and_hostnames.rb +41 -44
- metadata +144 -34
- metadata.gz.sig +2 -3
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
require "kitchen/provisioner"
|
18
18
|
require "kitchen/terraform/configurable"
|
19
|
+
require "kitchen/terraform/error"
|
19
20
|
|
20
21
|
# The provisioner utilizes the driver to apply changes to the Terraform state in order to reach the desired
|
21
22
|
# configuration of the root module.
|
@@ -88,19 +89,17 @@ class ::Kitchen::Provisioner::Terraform < ::Kitchen::Provisioner::Base
|
|
88
89
|
def call(state)
|
89
90
|
instance
|
90
91
|
.driver
|
91
|
-
.apply
|
92
|
-
.fmap do |output|
|
92
|
+
.apply do |output:|
|
93
93
|
state
|
94
94
|
.store(
|
95
95
|
:kitchen_terraform_output,
|
96
96
|
output
|
97
97
|
)
|
98
98
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
99
|
+
rescue ::Kitchen::Terraform::Error => error
|
100
|
+
raise(
|
101
|
+
::Kitchen::ActionFailed,
|
102
|
+
error.message
|
103
|
+
)
|
105
104
|
end
|
106
105
|
end
|
@@ -14,43 +14,45 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
require "dry/monads"
|
18
17
|
require "kitchen/terraform"
|
18
|
+
require "kitchen/terraform/error"
|
19
19
|
require "rubygems"
|
20
20
|
|
21
|
-
# Verifies that the output of the Terraform
|
21
|
+
# Verifies that the output of the Terraform version command indicates a supported version of Terraform.
|
22
|
+
#
|
23
|
+
# Supported:: Terraform version >= 0.10.2, < 0.12.0.
|
22
24
|
class ::Kitchen::Terraform::ClientVersionVerifier
|
23
|
-
|
24
|
-
|
25
|
-
# Verifies output from the Terraform Client version subcommand against the support version.
|
26
|
-
#
|
27
|
-
# Supported:: Terraform version ~> 0.10.2.
|
25
|
+
# Verifies output from the Terraform version command against the support version.
|
28
26
|
#
|
29
27
|
# @param version_output [::String] the Terraform Client version subcommand output.
|
30
|
-
# @
|
28
|
+
# @raise [::Kitchen::Terraform::Error] if the version is not supported.
|
29
|
+
# @return [::String] a confirmation that the version is supported.
|
31
30
|
def verify(version_output:)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
31
|
+
::Gem::Version
|
32
|
+
.new(
|
33
|
+
version_output
|
34
|
+
.slice(
|
35
|
+
/v(\d+\.\d+\.\d+)/,
|
36
|
+
1
|
37
|
+
)
|
38
|
+
)
|
39
|
+
.tap do |version|
|
40
|
+
requirement
|
41
|
+
.satisfied_by? version or
|
42
|
+
raise(
|
43
|
+
::Kitchen::Terraform::Error,
|
44
|
+
"Terraform v#{version} is not supported; install Terraform ~> v0.11.0"
|
45
|
+
)
|
46
|
+
|
47
|
+
return "Terraform v#{version} is supported"
|
46
48
|
end
|
47
|
-
end
|
48
49
|
end
|
49
50
|
|
50
51
|
private
|
51
52
|
|
52
53
|
attr_reader :requirement
|
53
54
|
|
55
|
+
# @api private
|
54
56
|
def initialize
|
55
57
|
@requirement =
|
56
58
|
::Gem::Requirement
|
@@ -0,0 +1,21 @@
|
|
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"
|
18
|
+
|
19
|
+
# The namespace for Terraform commands.
|
20
|
+
module ::Kitchen::Terraform::Command
|
21
|
+
end
|
@@ -0,0 +1,71 @@
|
|
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 "json"
|
18
|
+
require "kitchen/terraform/command"
|
19
|
+
require "kitchen/terraform/error"
|
20
|
+
require "kitchen/terraform/shell_out"
|
21
|
+
|
22
|
+
# Behaviour to run the `terraform output` command.
|
23
|
+
module ::Kitchen::Terraform::Command::Output
|
24
|
+
# Runs the command with JSON foramtting.
|
25
|
+
#
|
26
|
+
# @param duration [::Integer] the maximum duration in seconds to run the command.
|
27
|
+
# @param logger [::Kitchen::Logger] a Test Kitchen logger to capture the output from running the command.
|
28
|
+
# @yieldparam output [::String] the standard output of the command parsed as JSON.
|
29
|
+
def self.run(duration:, logger:, &block)
|
30
|
+
run_shell_out(
|
31
|
+
duration: duration,
|
32
|
+
logger: logger,
|
33
|
+
&block
|
34
|
+
)
|
35
|
+
rescue ::JSON::ParserError => error
|
36
|
+
handle_json_parser error: error
|
37
|
+
rescue ::Kitchen::Terraform::Error => error
|
38
|
+
handle_kitchen_terraform(
|
39
|
+
error: error,
|
40
|
+
&block
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
private_class_method
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
def self.handle_json_parser(error:)
|
48
|
+
raise(
|
49
|
+
::Kitchen::Terraform::Error,
|
50
|
+
"Parsing Terraform output as JSON failed: #{error.message}"
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
def self.handle_kitchen_terraform(error:)
|
56
|
+
/no\\ outputs\\ defined/.match ::Regexp.escape error.to_s or raise error
|
57
|
+
yield output: {}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @api private
|
61
|
+
def self.run_shell_out(duration:, logger:)
|
62
|
+
::Kitchen::Terraform::ShellOut
|
63
|
+
.run(
|
64
|
+
command: "output -json",
|
65
|
+
duration: duration,
|
66
|
+
logger: logger
|
67
|
+
) do |standard_output:|
|
68
|
+
yield output: ::JSON.parse(standard_output)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -62,7 +62,7 @@ module ::Kitchen::Terraform::ConfigAttribute::BackendConfigurations
|
|
62
62
|
def config_backend_configurations_flags
|
63
63
|
config_backend_configurations
|
64
64
|
.map do |key, value|
|
65
|
-
"-backend-config
|
65
|
+
"-backend-config=\"#{key}=#{value}\""
|
66
66
|
end
|
67
67
|
.join " "
|
68
68
|
end
|
@@ -19,30 +19,25 @@ require "kitchen/terraform/config_attribute_cacher"
|
|
19
19
|
require "kitchen/terraform/config_attribute_definer"
|
20
20
|
require "kitchen/terraform/config_schemas/groups"
|
21
21
|
|
22
|
-
# This attribute
|
23
|
-
#
|
22
|
+
# This attribute configures the execution of {https://www.inspec.io/docs/reference/profiles/ InSpec profiles} against
|
23
|
+
# different groups of resources in the Terraform state. Each group may be configured by using the proceeding attributes.
|
24
24
|
#
|
25
25
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760193 Sequence of mappings}
|
26
26
|
# Required:: False
|
27
|
-
# Example::
|
28
|
-
# _
|
29
|
-
# groups:
|
30
|
-
# -
|
31
|
-
# name: a_group
|
32
27
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# These keys must be declared in each of the mappings in the sequence.
|
36
|
-
#
|
37
|
-
# ==== name
|
28
|
+
# ===== name
|
38
29
|
#
|
39
30
|
# This key contains the name of the group to be used for logging purposes.
|
40
31
|
#
|
41
32
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760844 Scalar}
|
42
33
|
# Required:: True
|
43
|
-
# Example::
|
34
|
+
# Example::
|
35
|
+
# _
|
36
|
+
# groups:
|
37
|
+
# -
|
38
|
+
# name: a_group
|
44
39
|
#
|
45
|
-
#
|
40
|
+
# ===== attributes
|
46
41
|
#
|
47
42
|
# This key comprises associations of the names of
|
48
43
|
# {https://www.inspec.io/docs/reference/profiles/#profile-attributes InSpec profile attributes} with the names of
|
@@ -53,61 +48,93 @@ require "kitchen/terraform/config_schemas/groups"
|
|
53
48
|
# Required:: False
|
54
49
|
# Example::
|
55
50
|
# _
|
56
|
-
#
|
57
|
-
#
|
51
|
+
# groups:
|
52
|
+
# -
|
53
|
+
# name: a_group_with_overridden_attributes
|
54
|
+
# attributes:
|
55
|
+
# an_attribute: an_output
|
58
56
|
# Caveat:: As all Terraform outputs are associated with equivalently named InSpec profile attributes by default, this
|
59
57
|
# key is only necessary to provide alternative attribute names.
|
60
58
|
#
|
61
|
-
#
|
59
|
+
# ===== controls
|
62
60
|
#
|
63
61
|
# This key comprises the names of {https://www.inspec.io/docs/reference/dsl_inspec/ InSpec controls} to exclusively
|
64
|
-
# include from the InSpec profile of the Test Kitchen
|
62
|
+
# include from the InSpec profile of the associated Test Kitchen instance.
|
65
63
|
#
|
66
64
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760118 Sequince of scalars}
|
67
65
|
# Required:: False
|
68
66
|
# Example::
|
69
67
|
# _
|
70
|
-
#
|
71
|
-
# -
|
72
|
-
#
|
68
|
+
# groups:
|
69
|
+
# -
|
70
|
+
# name: a_group_with_a_first_subset_of_controls
|
71
|
+
# controls:
|
72
|
+
# - control_one
|
73
|
+
# - control_three
|
74
|
+
# -
|
75
|
+
# name: a_group_with_a_second_subset_of_controls
|
76
|
+
# controls:
|
77
|
+
# - control_two
|
78
|
+
# - control_four
|
73
79
|
#
|
74
|
-
#
|
80
|
+
# ===== hostnames
|
75
81
|
#
|
76
|
-
# This key contains the name of a Terraform output
|
82
|
+
# This key contains the name of a Terraform output which provides one or more hostnames to be targeted by the InSpec
|
83
|
+
# profile of the associated Test Kitchen instance.
|
77
84
|
#
|
78
85
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760844 Scalar}
|
79
86
|
# Required:: False
|
80
|
-
# Example::
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
87
|
+
# Example::
|
88
|
+
# _
|
89
|
+
# groups:
|
90
|
+
# -
|
91
|
+
# name: a_group_with_hostnames
|
92
|
+
# hostnames: an_output
|
93
|
+
# Caveat:: The output must be a string or an array of strings. If this key is omitted then +"localhost"+ will be the
|
94
|
+
# target of the profile. To connect to the hosts through a bastion host, a +ProxyCommand+ in the
|
95
|
+
# appropriate {https://linux.die.net/man/5/ssh_config SSH configuration file} must be configured on the system.
|
84
96
|
#
|
85
|
-
#
|
97
|
+
# ===== port
|
86
98
|
#
|
87
99
|
# This key contains the port to use when connecting with {https://en.wikipedia.org/wiki/Secure_Shell Secure Shell (SSH)}
|
88
100
|
# to the hosts of the group.
|
89
101
|
#
|
90
102
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2803828 Integer}
|
91
103
|
# Required:: False
|
92
|
-
# Example::
|
104
|
+
# Example::
|
105
|
+
# _
|
106
|
+
# groups:
|
107
|
+
# -
|
108
|
+
# name: a_group_with_a_port
|
109
|
+
# port: 1234
|
93
110
|
# Caveat:: If this key is omitted then the port of the Test Kitchen SSH transport will be used.
|
94
111
|
#
|
95
|
-
#
|
112
|
+
# ===== ssh_key
|
96
113
|
#
|
97
114
|
# This key contains the path to a private SSH key to use when connecting with SSH to the hosts of the group.
|
98
115
|
#
|
99
116
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760844 Scalar}
|
100
117
|
# Required:: False
|
101
|
-
# Example::
|
118
|
+
# Example::
|
119
|
+
# _
|
120
|
+
# groups:
|
121
|
+
# -
|
122
|
+
# name: a_group_with_an_ssh_key
|
123
|
+
# ssh_key: /path/to/an/ssh/key</
|
102
124
|
# Caveat:: If this key is omitted then the private SSH key of the Test Kitchen SSH Transport will be used.
|
103
125
|
#
|
104
|
-
#
|
126
|
+
# ===== username
|
105
127
|
#
|
106
128
|
# This key contains the username to use when connecting with SSH to the hosts of the group.
|
107
129
|
#
|
108
130
|
# Type:: {http://www.yaml.org/spec/1.2/spec.html#id2760844 Scalar}
|
109
131
|
# Required:: False
|
110
|
-
# Example::
|
132
|
+
# Example::
|
133
|
+
# _
|
134
|
+
# groups:
|
135
|
+
# -
|
136
|
+
# name: a_group_with_a_username
|
137
|
+
# username: tester
|
111
138
|
# Caveat:: If this key is omitted then the username of the Test Kitcen SSH Transport will be used.
|
112
139
|
#
|
113
140
|
# @abstract It must be included by a plugin class in order to be used.
|
@@ -0,0 +1,21 @@
|
|
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"
|
18
|
+
|
19
|
+
# This class represents errors that occur while Kitchen-Terraform is executing.
|
20
|
+
class ::Kitchen::Terraform::Error < ::StandardError
|
21
|
+
end
|
@@ -14,9 +14,8 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
require "dry/monads"
|
18
|
-
require "kitchen/terraform"
|
19
17
|
require "kitchen/terraform"
|
18
|
+
require "kitchen/terraform/error"
|
20
19
|
require "mixlib/shellout"
|
21
20
|
|
22
21
|
# Terraform commands are run by shelling out and using the
|
@@ -25,42 +24,62 @@ require "mixlib/shellout"
|
|
25
24
|
# TF_IN_AUTOMATION environment variable as specified by the
|
26
25
|
# {https://www.terraform.io/guides/running-terraform-in-automation.html#controlling-terraform-output-in-automation Running Terraform in Automation guide}.
|
27
26
|
module ::Kitchen::Terraform::ShellOut
|
28
|
-
extend ::Dry::Monads::Either::Mixin
|
29
|
-
extend ::Dry::Monads::Try::Mixin
|
30
|
-
|
31
27
|
# Runs a Terraform command.
|
32
28
|
#
|
33
29
|
# @param command [::String] the command to run.
|
34
30
|
# @param duration [::Integer] the maximum duration in seconds to run the command.
|
35
31
|
# @param logger [::Kitchen::Logger] a Test Kitchen logger to capture the output from running the command.
|
36
|
-
# @
|
32
|
+
# @raise [::Kitchen::Terraform::Error] if running the command fails.
|
33
|
+
# @return [::String] the standard output from running the command.
|
37
34
|
# @see https://rubygems.org/gems/mixlib-shellout mixlib-shellout
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
environment: {"TF_IN_AUTOMATION" => "true"},
|
44
|
-
live_stream: logger,
|
45
|
-
timeout: duration
|
46
|
-
)
|
47
|
-
end
|
48
|
-
.bind do |shell_out|
|
49
|
-
Try(
|
50
|
-
::Errno::EACCES,
|
51
|
-
::Errno::ENOENT,
|
52
|
-
::Mixlib::ShellOut::CommandTimeout,
|
53
|
-
::Mixlib::ShellOut::ShellCommandFailed
|
54
|
-
) do
|
55
|
-
logger.warn "Running command `#{shell_out.command}`"
|
56
|
-
shell_out.run_command
|
57
|
-
shell_out.error!
|
58
|
-
shell_out.stdout
|
59
|
-
end
|
60
|
-
end
|
61
|
-
.to_either
|
62
|
-
.or do |error|
|
63
|
-
Left "Running command resulted in failure: #{error}"
|
35
|
+
# @yieldparam standard_output [::String] the standard output from running the command.
|
36
|
+
def self.run(command:, duration: ::Mixlib::ShellOut::DEFAULT_READ_TIMEOUT, logger:, &block)
|
37
|
+
block ||=
|
38
|
+
lambda do |standard_output:|
|
39
|
+
standard_output
|
64
40
|
end
|
41
|
+
|
42
|
+
run_shell_out(
|
43
|
+
command: command,
|
44
|
+
duration: duration,
|
45
|
+
logger: logger,
|
46
|
+
&block
|
47
|
+
)
|
48
|
+
rescue ::Errno::EACCES,
|
49
|
+
::Errno::ENOENT,
|
50
|
+
::Mixlib::ShellOut::InvalidCommandOption,
|
51
|
+
::Mixlib::ShellOut::CommandTimeout,
|
52
|
+
::Mixlib::ShellOut::ShellCommandFailed => error
|
53
|
+
handle error: error
|
54
|
+
end
|
55
|
+
|
56
|
+
private_class_method
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def self.handle(error:)
|
60
|
+
raise(
|
61
|
+
::Kitchen::Terraform::Error,
|
62
|
+
"Running command resulted in failure: #{error.message}"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
def self.run_shell_out(command:, duration:, logger:)
|
68
|
+
yield(
|
69
|
+
standard_output:
|
70
|
+
::Mixlib::ShellOut
|
71
|
+
.new(
|
72
|
+
"terraform #{command}",
|
73
|
+
environment: {"TF_IN_AUTOMATION" => "true"},
|
74
|
+
live_stream: logger,
|
75
|
+
timeout: duration
|
76
|
+
)
|
77
|
+
.tap do |shell_out|
|
78
|
+
logger.warn "Running command `#{shell_out.command}`"
|
79
|
+
shell_out.run_command
|
80
|
+
shell_out.error!
|
81
|
+
end
|
82
|
+
.stdout
|
83
|
+
)
|
65
84
|
end
|
66
85
|
end
|