kitchen-terraform 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +0 -0
- data/lib/kitchen/driver/terraform.rb +57 -0
- data/lib/kitchen/provisioner/terraform.rb +58 -0
- data/lib/kitchen/verifier/terraform.rb +109 -0
- data/lib/terraform/apply_command.rb +32 -0
- data/lib/terraform/client.rb +102 -0
- data/lib/terraform/client_holder.rb +26 -0
- data/lib/terraform/command.rb +58 -0
- data/lib/terraform/command_options.rb +45 -0
- data/lib/terraform/error.rb +20 -0
- data/lib/terraform/get_command.rb +32 -0
- data/lib/terraform/inspec_runner.rb +44 -0
- data/lib/terraform/invalid_version.rb +34 -0
- data/lib/terraform/output_command.rb +38 -0
- data/lib/terraform/output_not_found.rb +23 -0
- data/lib/terraform/plan_command.rb +35 -0
- data/lib/terraform/validate_command.rb +32 -0
- data/lib/terraform/version.rb +19 -0
- data/lib/terraform/version_command.rb +32 -0
- data/spec/lib/kitchen/driver/terraform_spec.rb +126 -0
- data/spec/lib/kitchen/provisioner/terraform_spec.rb +106 -0
- data/spec/lib/kitchen/verifier/terraform_spec.rb +302 -0
- data/spec/lib/terraform/apply_command_spec.rb +32 -0
- data/spec/lib/terraform/client_spec.rb +211 -0
- data/spec/lib/terraform/command_options_spec.rb +34 -0
- data/spec/lib/terraform/get_command_spec.rb +30 -0
- data/spec/lib/terraform/inspec_runner_spec.rb +67 -0
- data/spec/lib/terraform/output_command_spec.rb +58 -0
- data/spec/lib/terraform/plan_command_spec.rb +46 -0
- data/spec/lib/terraform/validate_command_spec.rb +30 -0
- data/spec/lib/terraform/version_command_spec.rb +30 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/coverage.rb +21 -0
- data/spec/support/terraform/client_holder_context.rb +26 -0
- data/spec/support/terraform/client_holder_examples.rb +36 -0
- data/spec/support/terraform/command_examples.rb +80 -0
- data/spec/support/terraform/versions_are_set_examples.rb +35 -0
- metadata +329 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,45 @@
|
|
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
|
+
# Manages options for Terraform commands
|
19
|
+
class CommandOptions
|
20
|
+
def to_s
|
21
|
+
key_flags.each_with_object String.new('') do |(flag, values), string|
|
22
|
+
values.each { |value| string.concat "#{flag}=#{value} " }
|
23
|
+
end.chomp ' '
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_accessor :options
|
29
|
+
|
30
|
+
def key_flags
|
31
|
+
options
|
32
|
+
.map { |key, value| [key.to_s.tr('_', '-').prepend('-'), value] }.to_h
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(**options)
|
36
|
+
self.options = options
|
37
|
+
normalize_values
|
38
|
+
yield self if block_given?
|
39
|
+
end
|
40
|
+
|
41
|
+
def normalize_values
|
42
|
+
options.each_pair { |key, value| options.store key, Array(value) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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
|
+
class Error < StandardError
|
19
|
+
end
|
20
|
+
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_relative 'command'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Command to get modules
|
21
|
+
class GetCommand
|
22
|
+
include Command
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize_attributes(dir:)
|
27
|
+
self.name = 'get'
|
28
|
+
self.options = { update: true }
|
29
|
+
self.target = dir
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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 'inspec'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Inspec::Runner with convenience methods for use by
|
21
|
+
# Kitchen::Verifier::Terraform
|
22
|
+
class InspecRunner < Inspec::Runner
|
23
|
+
attr_reader :conf
|
24
|
+
|
25
|
+
def add(targets:)
|
26
|
+
targets.each { |target| add_target target, conf }
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_attribute(name:, value:)
|
30
|
+
conf.fetch('attributes').store name.to_s, value
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify_run(verifier:)
|
34
|
+
verifier.evaluate exit_code: run
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def initialize(conf = {})
|
40
|
+
super
|
41
|
+
yield self if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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_relative 'error'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Error of an invalid Terraform version
|
21
|
+
class InvalidVersion < Error
|
22
|
+
def message
|
23
|
+
"Terraform version must match #{supported_version}"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_accessor :supported_version
|
29
|
+
|
30
|
+
def initialize(supported_version)
|
31
|
+
self.supported_version = supported_version
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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_relative 'command'
|
18
|
+
require_relative 'output_not_found'
|
19
|
+
|
20
|
+
module Terraform
|
21
|
+
# Command to extract values of output variables
|
22
|
+
class OutputCommand
|
23
|
+
include Command
|
24
|
+
|
25
|
+
def handle(error:)
|
26
|
+
raise OutputNotFound, error.message, error.backtrace if
|
27
|
+
error.message =~ /no(?:thing to)? output/
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def initialize_attributes(state:, name:)
|
33
|
+
self.name = 'output'
|
34
|
+
self.options = { state: state }
|
35
|
+
self.target = name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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_relative 'error'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Error of an output not found
|
21
|
+
class OutputNotFound < Error
|
22
|
+
end
|
23
|
+
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_relative 'command'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Command to plan an execution
|
21
|
+
class PlanCommand
|
22
|
+
include Command
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize_attributes(destroy:, out:, state:, var:, var_file:, dir:)
|
27
|
+
self.name = 'plan'
|
28
|
+
self.options = {
|
29
|
+
destroy: destroy, input: false, out: out, state: state, var: var,
|
30
|
+
var_file: var_file
|
31
|
+
}
|
32
|
+
self.target = dir
|
33
|
+
end
|
34
|
+
end
|
35
|
+
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_relative 'command'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Command to valdidate configuration files
|
21
|
+
class ValidateCommand
|
22
|
+
include Command
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize_attributes(dir:)
|
27
|
+
self.name = 'validate'
|
28
|
+
self.options = {}
|
29
|
+
self.target = dir
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
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
|
+
VERSION = '0.1.0'
|
19
|
+
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_relative 'command'
|
18
|
+
|
19
|
+
module Terraform
|
20
|
+
# Command to obtain the version
|
21
|
+
class VersionCommand
|
22
|
+
include Command
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize_attributes(**_)
|
27
|
+
self.name = 'version'
|
28
|
+
self.options = {}
|
29
|
+
self.target = ''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,126 @@
|
|
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/driver/terraform'
|
18
|
+
require 'terraform/error'
|
19
|
+
require 'support/terraform/client_holder_context'
|
20
|
+
require 'support/terraform/client_holder_examples'
|
21
|
+
require 'support/terraform/versions_are_set_examples'
|
22
|
+
|
23
|
+
RSpec.describe Kitchen::Driver::Terraform do
|
24
|
+
let(:described_instance) { described_class.new }
|
25
|
+
|
26
|
+
it_behaves_like Terraform::ClientHolder
|
27
|
+
|
28
|
+
it_behaves_like 'versions are set'
|
29
|
+
|
30
|
+
describe '.serial_actions' do
|
31
|
+
subject(:serial_actions) { described_class.serial_actions }
|
32
|
+
|
33
|
+
it('is empty') { is_expected.to be_empty }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#create(_state = nil)' do
|
37
|
+
include_context '#client'
|
38
|
+
|
39
|
+
before do
|
40
|
+
allow(client).to receive(:fetch_version).with(no_args).and_yield output
|
41
|
+
end
|
42
|
+
|
43
|
+
subject { proc { described_instance.create } }
|
44
|
+
|
45
|
+
context 'when the Terraform version is supported' do
|
46
|
+
let(:output) { 'v0.6.1' }
|
47
|
+
|
48
|
+
it('does not raise an error') { is_expected.to_not raise_error }
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when the Terraform version is not supported' do
|
52
|
+
let(:output) { 'v0.5.2' }
|
53
|
+
|
54
|
+
it 'does raise an error' do
|
55
|
+
is_expected.to raise_error Kitchen::ActionFailed
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when the client command fails' do
|
60
|
+
before do
|
61
|
+
allow(client).to receive(:fetch_version).with(no_args)
|
62
|
+
.and_raise Terraform::Error
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does raise an error' do
|
66
|
+
is_expected.to raise_error Kitchen::ActionFailed
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#destroy(_state = nil)' do
|
72
|
+
include_context '#client'
|
73
|
+
|
74
|
+
let(:call_method) { described_instance.destroy }
|
75
|
+
|
76
|
+
context 'when the Terraform state can be destroyed' do
|
77
|
+
before do
|
78
|
+
allow(client).to receive(:validate_configuration_files).with no_args
|
79
|
+
|
80
|
+
allow(client).to receive(:download_modules).with no_args
|
81
|
+
|
82
|
+
allow(client).to receive(:plan_destructive_execution).with no_args
|
83
|
+
|
84
|
+
allow(client).to receive(:apply_execution_plan).with no_args
|
85
|
+
end
|
86
|
+
|
87
|
+
after { call_method }
|
88
|
+
|
89
|
+
subject { client }
|
90
|
+
|
91
|
+
it 'validates the configuration files' do
|
92
|
+
is_expected.to receive(:validate_configuration_files).with no_args
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'gets the modules' do
|
96
|
+
is_expected.to receive(:download_modules).with no_args
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'plans the destructive execution' do
|
100
|
+
is_expected.to receive(:plan_destructive_execution).with no_args
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'applies the execution plan' do
|
104
|
+
is_expected.to receive(:apply_execution_plan).with no_args
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when a client command fails' do
|
109
|
+
before do
|
110
|
+
allow(client).to receive(:validate_configuration_files).and_raise
|
111
|
+
end
|
112
|
+
|
113
|
+
subject { proc { call_method } }
|
114
|
+
|
115
|
+
it 'raises an error' do
|
116
|
+
is_expected.to raise_error Kitchen::ActionFailed
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#supported_version' do
|
122
|
+
subject { described_instance.supported_version }
|
123
|
+
|
124
|
+
it('equals v0.6') { is_expected.to eq 'v0.6' }
|
125
|
+
end
|
126
|
+
end
|