kitchen-terraform 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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