kitchen-terraform 0.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +1 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/kitchen/driver/terraform.rb +57 -0
  5. data/lib/kitchen/provisioner/terraform.rb +58 -0
  6. data/lib/kitchen/verifier/terraform.rb +109 -0
  7. data/lib/terraform/apply_command.rb +32 -0
  8. data/lib/terraform/client.rb +102 -0
  9. data/lib/terraform/client_holder.rb +26 -0
  10. data/lib/terraform/command.rb +58 -0
  11. data/lib/terraform/command_options.rb +45 -0
  12. data/lib/terraform/error.rb +20 -0
  13. data/lib/terraform/get_command.rb +32 -0
  14. data/lib/terraform/inspec_runner.rb +44 -0
  15. data/lib/terraform/invalid_version.rb +34 -0
  16. data/lib/terraform/output_command.rb +38 -0
  17. data/lib/terraform/output_not_found.rb +23 -0
  18. data/lib/terraform/plan_command.rb +35 -0
  19. data/lib/terraform/validate_command.rb +32 -0
  20. data/lib/terraform/version.rb +19 -0
  21. data/lib/terraform/version_command.rb +32 -0
  22. data/spec/lib/kitchen/driver/terraform_spec.rb +126 -0
  23. data/spec/lib/kitchen/provisioner/terraform_spec.rb +106 -0
  24. data/spec/lib/kitchen/verifier/terraform_spec.rb +302 -0
  25. data/spec/lib/terraform/apply_command_spec.rb +32 -0
  26. data/spec/lib/terraform/client_spec.rb +211 -0
  27. data/spec/lib/terraform/command_options_spec.rb +34 -0
  28. data/spec/lib/terraform/get_command_spec.rb +30 -0
  29. data/spec/lib/terraform/inspec_runner_spec.rb +67 -0
  30. data/spec/lib/terraform/output_command_spec.rb +58 -0
  31. data/spec/lib/terraform/plan_command_spec.rb +46 -0
  32. data/spec/lib/terraform/validate_command_spec.rb +30 -0
  33. data/spec/lib/terraform/version_command_spec.rb +30 -0
  34. data/spec/spec_helper.rb +27 -0
  35. data/spec/support/coverage.rb +21 -0
  36. data/spec/support/terraform/client_holder_context.rb +26 -0
  37. data/spec/support/terraform/client_holder_examples.rb +36 -0
  38. data/spec/support/terraform/command_examples.rb +80 -0
  39. data/spec/support/terraform/versions_are_set_examples.rb +35 -0
  40. metadata +329 -0
  41. 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