kitchen-terraform 5.1.1 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +37 -173
  5. data/lib/kitchen/driver/terraform.rb +196 -514
  6. data/lib/kitchen/provisioner/terraform.rb +88 -86
  7. data/lib/kitchen/terraform.rb +5 -6
  8. data/lib/kitchen/terraform/breaking.rb +7 -5
  9. data/lib/kitchen/terraform/command.rb +7 -5
  10. data/lib/kitchen/terraform/command/apply.rb +87 -0
  11. data/lib/kitchen/terraform/command/destroy.rb +88 -0
  12. data/lib/kitchen/terraform/command/get.rb +32 -0
  13. data/lib/kitchen/terraform/command/init.rb +102 -0
  14. data/lib/kitchen/terraform/command/output.rb +11 -50
  15. data/lib/kitchen/terraform/command/validate.rb +63 -0
  16. data/lib/kitchen/terraform/command/version.rb +5 -42
  17. data/lib/kitchen/terraform/command/workspace_delete.rb +41 -0
  18. data/lib/kitchen/terraform/command/workspace_new.rb +43 -0
  19. data/lib/kitchen/terraform/command/workspace_select.rb +43 -0
  20. data/lib/kitchen/terraform/command_executor.rb +60 -0
  21. data/lib/kitchen/terraform/command_flag.rb +23 -0
  22. data/lib/kitchen/terraform/command_flag/backend_config.rb +43 -0
  23. data/lib/kitchen/terraform/command_flag/color.rb +45 -0
  24. data/lib/kitchen/terraform/command_flag/lock_timeout.rb +42 -0
  25. data/lib/kitchen/terraform/command_flag/plugin_dir.rb +47 -0
  26. data/lib/kitchen/terraform/command_flag/upgrade.rb +45 -0
  27. data/lib/kitchen/terraform/command_flag/var.rb +43 -0
  28. data/lib/kitchen/terraform/command_flag/var_file.rb +45 -0
  29. data/lib/kitchen/terraform/config_attribute.rb +58 -55
  30. data/lib/kitchen/terraform/config_attribute/backend_configurations.rb +1 -1
  31. data/lib/kitchen/terraform/config_attribute/client.rb +10 -3
  32. data/lib/kitchen/terraform/config_attribute/color.rb +1 -1
  33. data/lib/kitchen/terraform/config_attribute/command_timeout.rb +1 -1
  34. data/lib/kitchen/terraform/config_attribute/fail_fast.rb +1 -1
  35. data/lib/kitchen/terraform/config_attribute/lock.rb +1 -1
  36. data/lib/kitchen/terraform/config_attribute/lock_timeout.rb +1 -1
  37. data/lib/kitchen/terraform/config_attribute/parallelism.rb +1 -1
  38. data/lib/kitchen/terraform/config_attribute/plugin_directory.rb +3 -3
  39. data/lib/kitchen/terraform/config_attribute/root_module_directory.rb +4 -4
  40. data/lib/kitchen/terraform/config_attribute/systems.rb +1 -1
  41. data/lib/kitchen/terraform/config_attribute/variable_files.rb +4 -4
  42. data/lib/kitchen/terraform/config_attribute/variables.rb +1 -1
  43. data/lib/kitchen/terraform/config_attribute/verify_version.rb +2 -2
  44. data/lib/kitchen/terraform/config_attribute_cacher.rb +27 -25
  45. data/lib/kitchen/terraform/config_attribute_definer.rb +37 -43
  46. data/lib/kitchen/terraform/config_attribute_type.rb +7 -5
  47. data/lib/kitchen/terraform/config_attribute_type/hash_of_symbols_and_strings.rb +32 -27
  48. data/lib/kitchen/terraform/config_attribute_type/integer.rb +4 -4
  49. data/lib/kitchen/terraform/config_predicates.rb +7 -5
  50. data/lib/kitchen/terraform/config_predicates/hash_of_symbols_and_strings.rb +6 -6
  51. data/lib/kitchen/terraform/config_schemas.rb +7 -5
  52. data/lib/kitchen/terraform/config_schemas/array_of_strings.rb +20 -13
  53. data/lib/kitchen/terraform/config_schemas/boolean.rb +16 -9
  54. data/lib/kitchen/terraform/config_schemas/optional_string.rb +20 -13
  55. data/lib/kitchen/terraform/config_schemas/string.rb +13 -7
  56. data/lib/kitchen/terraform/config_schemas/system.rb +38 -16
  57. data/lib/kitchen/terraform/config_schemas/systems.rb +5 -2
  58. data/lib/kitchen/terraform/configurable.rb +41 -21
  59. data/lib/kitchen/terraform/debug_logger.rb +1 -1
  60. data/lib/kitchen/terraform/deprecating.rb +7 -5
  61. data/lib/kitchen/terraform/driver.rb +23 -0
  62. data/lib/kitchen/terraform/driver/create.rb +120 -0
  63. data/lib/kitchen/terraform/driver/destroy.rb +169 -0
  64. data/lib/kitchen/terraform/error.rb +7 -5
  65. data/lib/kitchen/terraform/file_path_config_attribute_definer.rb +30 -27
  66. data/lib/kitchen/terraform/inspec.rb +3 -57
  67. data/lib/kitchen/terraform/inspec/fail_fast_with_hosts.rb +59 -0
  68. data/lib/kitchen/terraform/inspec/fail_slow_with_hosts.rb +69 -0
  69. data/lib/kitchen/terraform/inspec/without_hosts.rb +52 -0
  70. data/lib/kitchen/terraform/inspec_factory.rb +68 -0
  71. data/lib/kitchen/terraform/inspec_options_factory.rb +86 -0
  72. data/lib/kitchen/terraform/inspec_runner.rb +88 -0
  73. data/lib/kitchen/terraform/outputs_manager.rb +64 -0
  74. data/lib/kitchen/terraform/outputs_parser.rb +39 -0
  75. data/lib/kitchen/terraform/outputs_reader.rb +63 -0
  76. data/lib/kitchen/terraform/provisioner.rb +23 -0
  77. data/lib/kitchen/terraform/provisioner/converge.rb +206 -0
  78. data/lib/kitchen/terraform/raise.rb +23 -0
  79. data/lib/kitchen/terraform/raise/action_failed.rb +49 -0
  80. data/lib/kitchen/terraform/raise/client_error.rb +49 -0
  81. data/lib/kitchen/terraform/shell_out.rb +90 -59
  82. data/lib/kitchen/terraform/system.rb +63 -93
  83. data/lib/kitchen/terraform/system_attrs_inputs_resolver.rb +49 -0
  84. data/lib/kitchen/terraform/system_attrs_outputs_resolver.rb +80 -0
  85. data/lib/kitchen/terraform/system_bastion_host_resolver.rb +72 -0
  86. data/lib/kitchen/terraform/system_hosts_resolver.rb +39 -17
  87. data/lib/kitchen/terraform/system_inspec_map.rb +49 -0
  88. data/lib/kitchen/terraform/systems_verifier.rb +23 -0
  89. data/lib/kitchen/terraform/systems_verifier/fail_fast.rb +52 -0
  90. data/lib/kitchen/terraform/systems_verifier/fail_slow.rb +62 -0
  91. data/lib/kitchen/terraform/systems_verifier_factory.rb +50 -0
  92. data/lib/kitchen/terraform/unsupported_client_version_error.rb +26 -0
  93. data/lib/kitchen/terraform/variables_manager.rb +64 -0
  94. data/lib/kitchen/terraform/verify_version.rb +63 -20
  95. data/lib/kitchen/terraform/verify_version_rescue_strategy.rb +23 -0
  96. data/lib/kitchen/terraform/verify_version_rescue_strategy/permissive.rb +50 -0
  97. data/lib/kitchen/terraform/verify_version_rescue_strategy/strict.rb +47 -0
  98. data/lib/kitchen/terraform/verify_version_rescue_strategy_factory.rb +51 -0
  99. data/lib/kitchen/terraform/version.rb +59 -58
  100. data/lib/kitchen/terraform/version_verifier.rb +50 -0
  101. data/lib/kitchen/terraform/version_verifier_strategy.rb +25 -0
  102. data/lib/kitchen/terraform/version_verifier_strategy/supported.rb +33 -0
  103. data/lib/kitchen/terraform/version_verifier_strategy/unsupported.rb +34 -0
  104. data/lib/kitchen/terraform/version_verifier_strategy_factory.rb +50 -0
  105. data/lib/kitchen/verifier/terraform.rb +71 -62
  106. metadata +143 -80
  107. metadata.gz.sig +0 -0
  108. data/lib/kitchen/terraform/inspec_options_mapper.rb +0 -73
  109. data/lib/kitchen/terraform/inspec_with_hosts.rb +0 -50
  110. data/lib/kitchen/terraform/inspec_without_hosts.rb +0 -45
  111. data/lib/kitchen/terraform/system_attrs_resolver.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87c376e5a70ddafbed0a060b327f76d89447a975131983a7f4593c0987d4fdac
4
- data.tar.gz: a41d6d0fc75aaec9de8cddc2adc236fe3e29b43da7765f7916a1bb5e1e9dd798
3
+ metadata.gz: 3948ec5fe29f577c8d765a5953787519fce5b3a44f98a31f8bda3d4f1bbec8c2
4
+ data.tar.gz: 92dd2c104727c488295117dee79560de00b182cb8a153efc9ef336eb389a3289
5
5
  SHA512:
6
- metadata.gz: f4ff76d4c4a2357a0651b29524b371358b9f5f15bf9d0db494c6f4141061b97e22e0ea8da8ca7783f9514810089589d820d38edc0252f79309828205ca4cf3a7
7
- data.tar.gz: 8a5301f8d490038734cda34b3a637d24596ed42ec310692581075f4befb3533ff637e417256316a010f512e59a1cb914bd6132d977171ad22008e9becce0a2c5
6
+ metadata.gz: 58238380acb2afaaa699efc7e1c84a3132ec89e6aeed4deafd1aee6a557b1ff4235ff882f7469caee9012ca44561090debd913fab3ae0ae14793717b61e43780
7
+ data.tar.gz: 870c8f8ef8cffd6a41eb1af6b6e7d70ae211910d1f0bf6ab2ba41213ebffa2ec0d956213c607607ef66abf0b8cefc179f2a79fc075a53a4b649ff32180728e04
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ![Kitchen-Terraform Logo][kitchen-terraform-logo] Kitchen-Terraform
2
2
 
3
- > Kitchen-Terraform enables verification of Terraform state.
3
+ > Kitchen-Terraform enables verification of infrastructure systems provisioned with Terraform.
4
4
 
5
5
  [![Gem version][gem-version-shield]][kitchen-terraform-gem]
6
6
  [![Gem downloads version][gem-downloads-version-shield]][kitchen-terraform-gem]
@@ -15,10 +15,10 @@
15
15
 
16
16
  [![Gitter chat][gitter-shield]][gitter]
17
17
 
18
- Kitchen-Terraform provides a set of [Test Kitchen][test-kitchen] plugins
19
- which enable a system to use Test Kitchen to converge a
20
- [Terraform][terraform] configuration and verify the resulting Terraform
21
- state with [InSpec][inspec] controls.
18
+ Kitchen-Terraform provides a set of [Kitchen][kitchen] plugins
19
+ which enable the use of Kitchen to converge a [Terraform][terraform]
20
+ configuration and verify the resulting infrastructure systems with
21
+ [InSpec][inspec] controls.
22
22
 
23
23
  As Kitchen-Terraform integrates several distinctive technologies in a
24
24
  nontrivial manner, reviewing the documentation of each of the
@@ -36,7 +36,7 @@ Installation instructions can be found in the
36
36
  [Terraform: Install Terraform][terraform-install] article.
37
37
 
38
38
  Kitchen-Terraform supports versions of Terraform in the interval of
39
- `>= 0.11.4, < 0.13.0`.
39
+ `>= 0.11.4, < 0.15.0`.
40
40
 
41
41
  [tfenv] can be used to manage versions of Terraform on the system.
42
42
 
@@ -50,7 +50,7 @@ Installation instructions can be found in the
50
50
 
51
51
  Kitchen-Terraform aims to support all versions of Ruby that are in
52
52
  ["normal" or "security" maintenance][ruby-branches], which is currently
53
- the interval of `>= 2.4, < 2.7`.
53
+ the interval of `>= 2.4, < 2.8`.
54
54
 
55
55
  [rbenv] can be used to manage versions of Ruby on the system.
56
56
 
@@ -75,10 +75,7 @@ the semantic versioning of the Ruby gem.
75
75
 
76
76
  ```ruby
77
77
  source "https://rubygems.org/" do
78
- gem(
79
- "kitchen-terraform",
80
- "~> 4.0"
81
- )
78
+ gem "kitchen-terraform", "~> 5.6"
82
79
  end
83
80
  ```
84
81
 
@@ -105,7 +102,7 @@ example.
105
102
  > Installing Kitchen-Terraform with RubyGems
106
103
 
107
104
  ```sh
108
- gem install kitchen-terraform --version 4.0.0
105
+ gem install kitchen-terraform --version 5.6.0
109
106
  ```
110
107
 
111
108
  This approach is not recommended as it requires more effort to install
@@ -131,7 +128,7 @@ Ed25519-type SSH keys.
131
128
 
132
129
  Kitchen-Terraform provides three Test Kitchen plugins which must be
133
130
  configured in a
134
- [Test Kitchen configuration file][test-kitchen-configuration-file] in
131
+ [Kitchen configuration file][kitchen-configuration-file] in
135
132
  order to successfully test Terraform configuration.
136
133
 
137
134
  The [Terraform driver][terraform-driver] manages the state of the
@@ -146,166 +143,27 @@ Terraform state.
146
143
  More information can be found in the
147
144
  [Ruby gem documentation][ruby-gem-documentation].
148
145
 
149
- ### Example
146
+ ### Caveats
150
147
 
151
- This example demonstrates how to test a simple Terraform configuration
152
- which utilizes the [Docker provider][docker-provider].
148
+ Versions of Terraform in the 0.11 series may cause `kitchen test` to
149
+ fail if the initial destroy targets an empty Terraform state. A
150
+ workaround for this problem is to use
151
+ `kitchen verify && kitchen destroy` instead of `kitchen test`. More
152
+ details about the problem are available in
153
+ [issue #271](issue-271).
153
154
 
154
- The test system is assumed to be running Ubuntu 17.04.
155
+ ### Tutorials and Examples
155
156
 
156
- Terraform, Ruby, and Bundler are assumed to have been installed on the
157
- test system as described in the [Installation](#installation) section.
158
-
159
- The [Docker Community Edition][docker-community-edition] is assumed to
160
- have been installed on the test system.
161
-
162
- The working directory on the test system is assumed to contain a
163
- hierarchy of files comprising the following blocks.
164
-
165
- > Directory hierarchy
166
-
167
- ```
168
- .
169
- ├── .kitchen.yml
170
- ├── Gemfile
171
- ├── main.tf
172
- ├── outputs.tf
173
- └── test
174
- └── integration
175
- └── example
176
- ├── controls
177
- │   ├── operating_system.rb
178
- └── inspec.yml
179
- ```
180
-
181
- > Gemfile
182
-
183
- ```ruby
184
- source "https://rubygems.org/"
185
-
186
- gem 'kitchen-terraform'
187
- ```
188
-
189
- > ./.kitchen.yml (Test Kitchen configuration)
190
-
191
- ```yaml
192
- driver:
193
- name: terraform
194
-
195
- provisioner:
196
- name: terraform
197
-
198
- verifier:
199
- name: terraform
200
- systems:
201
- - name: container
202
- backend: ssh
203
- hosts_output: container_hostname
204
- password: root
205
- port: 2222
206
- user: root
207
-
208
- platforms:
209
- - name: ubuntu
210
-
211
- suites:
212
- - name: example
213
- ```
214
-
215
- > ./main.tf
216
-
217
- ```hcl
218
- provider "docker" {
219
- host = "unix://localhost/var/run/docker.sock"
220
- }
221
-
222
- data "docker_registry_image" "ubuntu" {
223
- name = "rastasheep/ubuntu-sshd:latest"
224
- }
225
-
226
- resource "docker_image" "ubuntu" {
227
- name = "${data.docker_registry_image.ubuntu.name}"
228
- pull_triggers = ["${data.docker_registry_image.ubuntu.sha256_digest}"]
229
- }
230
-
231
- resource "docker_container" "ubuntu" {
232
- image = "${docker_image.ubuntu.name}"
233
- must_run = true
234
- name = "ubuntu_container"
235
-
236
- ports {
237
- external = 2222
238
- internal = 22
239
- }
240
- }
241
- ```
242
-
243
- > ./outputs.tf
244
-
245
- ```hcl
246
- output "container_hostname" {
247
- description = "The hostname of the container."
248
- value = "127.0.0.1"
249
- }
250
- ```
251
-
252
- > ./test/integration/example/inspec.yml
253
-
254
- ```yaml
255
- name: example
256
- ```
257
-
258
- > ./test/integration/example/controls/operating_system.rb
259
-
260
- ```ruby
261
- # frozen_string_literal: true
262
-
263
- control "operating_system" do
264
- describe "the operating system" do
265
- subject do
266
- command("cat /etc/os-release").stdout
267
- end
268
-
269
- it "is Ubuntu" do
270
- is_expected.to match /Ubuntu/
271
- end
272
- end
273
- end
274
- ```
275
-
276
- Running the following command would initialize the working directory for
277
- Terraform, create a Docker container by applying the configuration file,
278
- and verify that the container is running Ubuntu.
279
-
280
- > Verifying with Kitchen-Terraform
281
-
282
- ```sh
283
- $ bundle install
284
- $ bundle exec kitchen test
285
- -----> Starting Kitchen...
286
- ...
287
- $$$$$$ Running command `terraform init...`
288
- ...
289
- $$$$$$ Running command `terraform apply...`
290
- ...
291
- docker_container.ubuntu: Creation complete after 1s...
292
-
293
- Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
294
- ...
295
- Finished converging <example-ubuntu>...
296
- ...
297
- -----> Verifying <example-ubuntu>...
298
- Verifying host 'localhost' of system 'container'
299
- ...
300
- ✔ operating_system: the operating system is Ubuntu
301
- ...
302
- Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
303
- ...
304
- ```
305
-
306
- More information can be found on the
157
+ Several tutorials are available on the
307
158
  [Kitchen-Terraform Tutorials][kitchen-terraform-tutorials] page.
308
159
 
160
+ The integration tests for Kitchen-Terraform can also be viewed as
161
+ examples of how it works. The
162
+ [integration test Kitchen configuration file][int-kitchen-config]
163
+ and the [integration test directory][test-directory] provide several
164
+ functional examples which exercise various features of
165
+ Kitchen-Terraform.
166
+
309
167
  ## Contributing
310
168
 
311
169
  Kitchen-Terraform thrives on community contributions.
@@ -323,7 +181,8 @@ Information about changes to Kitchen-Terraform can be found in the
323
181
 
324
182
  ## Maintainers
325
183
 
326
- Kitchen-Terraform is maintained by New Context.
184
+ Kitchen-Terraform is maintained by [community contributors][contributors]
185
+ and New Context.
327
186
 
328
187
  <img
329
188
  alt="New Context logo"
@@ -376,17 +235,22 @@ Kitchen-Terraform is distributed under the [Apache License][license].
376
235
  [code-coverage-shield]: https://img.shields.io/codeclimate/coverage/newcontext-oss/kitchen-terraform.svg
377
236
  [code-coverage]: https://codeclimate.com/github/newcontext-oss/kitchen-terraform/
378
237
  [contributing-document]: https://github.com/newcontext-oss/kitchen-terraform/blob/master/CONTRIBUTING.md
238
+ [contributors]: https://github.com/newcontext-oss/kitchen-terraform/graphs/contributors
379
239
  [docker]: https://www.docker.com/
380
240
  [docker-community-edition]: https://store.docker.com/editions/community/docker-ce-server-ubuntu
381
241
  [docker-provider]: https://www.terraform.io/docs/providers/docker/index.html
382
242
  [gem-downloads-total-shield]: https://img.shields.io/gem/dt/kitchen-terraform.svg
383
243
  [gem-downloads-version-shield]: https://img.shields.io/gem/dtv/kitchen-terraform.svg
384
244
  [gem-version-shield]: https://img.shields.io/gem/v/kitchen-terraform.svg
385
- [hakiri-shield]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/master.svg
386
- [hakiri]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/
387
245
  [gitter-shield]: https://img.shields.io/gitter/room/kitchen-terraform/Lobby.svg
388
246
  [gitter]: https://gitter.im/kitchen-terraform/Lobby
247
+ [hakiri-shield]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/master.svg
248
+ [hakiri]: https://hakiri.io/github/newcontext-oss/kitchen-terraform/
389
249
  [inspec]: https://www.inspec.io/
250
+ [int-kitchen-config]: https://github.com/newcontext-oss/kitchen-terraform/blob/master/kitchen.yml
251
+ [issue-271]: https://github.com/newcontext-oss/kitchen-terraform/issues/271
252
+ [kitchen]: http://kitchen.ci/index.html
253
+ [kitchen-configuration-file]: https://docs.chef.io/config_yml_kitchen.html
390
254
  [kitchen-terraform-gem]: https://rubygems.org/gems/kitchen-terraform
391
255
  [kitchen-terraform-logo]: https://raw.githubusercontent.com/newcontext-oss/kitchen-terraform/master/assets/logo.png
392
256
  [kitchen-terraform-tutorials]: https://newcontext-oss.github.io/kitchen-terraform/tutorials/
@@ -413,8 +277,8 @@ Kitchen-Terraform is distributed under the [Apache License][license].
413
277
  [terraform-provisioner]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Provisioner/Terraform
414
278
  [terraform-verifier]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Verifier/Terraform
415
279
  [terraform]: https://www.terraform.io/
416
- [test-kitchen-configuration-file]: https://docs.chef.io/config_yml_kitchen.html
417
- [test-kitchen]: http://kitchen.ci/index.html
280
+ [test-directory]: https://github.com/newcontext-oss/kitchen-terraform/tree/master/test
418
281
  [tfenv]: https://github.com/kamatama41/tfenv
419
282
  [travis-build-status-shield]: https://img.shields.io/travis/com/newcontext-oss/kitchen-terraform.svg
420
283
  [travis-build-status]: https://travis-ci.com/newcontext-oss/kitchen-terraform
284
+
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2016 New Context Services, Inc.
3
+ # Copyright 2016-2019 New Context, Inc.
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -15,14 +15,13 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "kitchen"
18
- require "kitchen/terraform/command/output"
19
- require "kitchen/terraform/command/version"
18
+ require "kitchen/terraform/raise/action_failed"
20
19
  require "kitchen/terraform/config_attribute/backend_configurations"
21
20
  require "kitchen/terraform/config_attribute/client"
22
21
  require "kitchen/terraform/config_attribute/color"
23
22
  require "kitchen/terraform/config_attribute/command_timeout"
24
- require "kitchen/terraform/config_attribute/lock"
25
23
  require "kitchen/terraform/config_attribute/lock_timeout"
24
+ require "kitchen/terraform/config_attribute/lock"
26
25
  require "kitchen/terraform/config_attribute/parallelism"
27
26
  require "kitchen/terraform/config_attribute/plugin_directory"
28
27
  require "kitchen/terraform/config_attribute/root_module_directory"
@@ -30,521 +29,204 @@ require "kitchen/terraform/config_attribute/variable_files"
30
29
  require "kitchen/terraform/config_attribute/variables"
31
30
  require "kitchen/terraform/config_attribute/verify_version"
32
31
  require "kitchen/terraform/configurable"
33
- require "kitchen/terraform/debug_logger"
34
- require "kitchen/terraform/shell_out"
35
- require "kitchen/terraform/verify_version"
32
+ require "kitchen/terraform/driver/create"
33
+ require "kitchen/terraform/driver/destroy"
34
+ require "kitchen/terraform/version_verifier"
35
+ require "rubygems"
36
36
  require "shellwords"
37
37
 
38
38
  # This namespace is defined by Kitchen.
39
39
  #
40
- # @see http://www.rubydoc.info/gems/test-kitchen/Kitchen/Driver
41
- module ::Kitchen::Driver
42
- end
43
-
44
- # The driver is the bridge between Test Kitchen and Terraform. It manages the
45
- # {https://www.terraform.io/docs/state/index.html state} of the Terraform root module by shelling out and running
46
- # Terraform commands.
47
- #
48
- # === Commands
49
- #
50
- # The following command-line commands are provided by the driver.
51
- #
52
- # ==== kitchen create
53
- #
54
- # A Test Kitchen instance is created through the following steps.
55
- #
56
- # ===== Initializing the Terraform Working Directory
57
- #
58
- # terraform init \
59
- # -input=false \
60
- # -lock=<lock> \
61
- # -lock-timeout=<lock_timeout>s \
62
- # [-no-color] \
63
- # -upgrade \
64
- # -force-copy \
65
- # -backend=true \
66
- # [-backend-config=<backend_configurations.first> ...] \
67
- # -get=true \
68
- # -get-plugins=true \
69
- # [-plugin-dir=<plugin_directory>] \
70
- # -verify-plugins=true \
71
- # <root_module_directory>
72
- #
73
- # ===== Creating a Test Terraform Workspace
74
- #
75
- # terraform workspace <new|select> kitchen-terraform-<instance>
76
- #
77
- # ==== kitchen destroy
78
- #
79
- # A Test Kitchen instance is destroyed through the following steps.
80
- #
81
- # ===== Initializing the Terraform Working Directory
82
- #
83
- # terraform init \
84
- # -input=false \
85
- # -lock=<lock> \
86
- # -lock-timeout=<lock_timeout>s \
87
- # [-no-color] \
88
- # -force-copy \
89
- # -backend=true \
90
- # [-backend-config=<backend_configurations.first>...] \
91
- # -get=true \
92
- # -get-plugins=true \
93
- # [-plugin-dir=<plugin_directory>] \
94
- # -verify-plugins=true \
95
- # <root_module_directory>
96
- #
97
- # ===== Selecting the Test Terraform Workspace
98
- #
99
- # terraform workspace <select|new> kitchen-terraform-<instance>
100
- #
101
- # ===== Destroying the Terraform State
102
- #
103
- # terraform destroy \
104
- # -auto-approve \
105
- # -lock=<lock> \
106
- # -lock-timeout=<lock_timeout>s \
107
- # -input=false \
108
- # [-no-color] \
109
- # -parallelism=<parallelism> \
110
- # -refresh=true \
111
- # [-var=<variables.first>...] \
112
- # [-var-file=<variable_files.first>...] \
113
- # <root_module_directory>
114
- #
115
- # ===== Selecting the Default Terraform Workspace
116
- #
117
- # terraform workspace select default
118
- #
119
- # ===== Deleting the Test Terraform Workspace
120
- #
121
- # terraform workspace delete kitchen-terraform-<instance>
122
- #
123
- # === Shelling Out
124
- #
125
- # {include:Kitchen::Terraform::ShellOut}
126
- #
127
- # === Configuration Attributes
128
- #
129
- # The configuration attributes of the driver control the behaviour of the Terraform commands that are run. Within the
130
- # {http://kitchen.ci/docs/getting-started/kitchen-yml Test Kitchen configuration file}, these attributes must be
131
- # declared in the +driver+ mapping along with the plugin name.
132
- #
133
- # driver:
134
- # name: terraform
135
- # a_configuration_attribute: some value
136
- #
137
- # ==== backend_configurations
138
- #
139
- # {include:Kitchen::Terraform::ConfigAttribute::BackendConfigurations}
140
- #
141
- # ==== client
142
- #
143
- # {include:Kitchen::Terraform::ConfigAttribute::Client}
144
- #
145
- # ==== color
146
- #
147
- # {include:Kitchen::Terraform::ConfigAttribute::Color}
148
- #
149
- # ==== command_timeout
150
- #
151
- # {include:Kitchen::Terraform::ConfigAttribute::CommandTimeout}
152
- #
153
- # ==== lock
154
- #
155
- # {include:Kitchen::Terraform::ConfigAttribute::Lock}
156
- #
157
- # ==== lock_timeout
158
- #
159
- # {include:Kitchen::Terraform::ConfigAttribute::LockTimeout}
160
- #
161
- # ==== parallelism
162
- #
163
- # {include:Kitchen::Terraform::ConfigAttribute::Parallelism}
164
- #
165
- # ==== plugin_directory
166
- #
167
- # {include:Kitchen::Terraform::ConfigAttribute::PluginDirectory}
168
- #
169
- # ==== root_module_directory
170
- #
171
- # {include:Kitchen::Terraform::ConfigAttribute::RootModuleDirectory}
172
- #
173
- # ==== variable_files
174
- #
175
- # {include:Kitchen::Terraform::ConfigAttribute::VariableFiles}
176
- #
177
- # ==== variables
178
- #
179
- # {include:Kitchen::Terraform::ConfigAttribute::Variables}
180
- #
181
- # ==== verify_version
182
- #
183
- # {include:Kitchen::Terraform::ConfigAttribute::VerifyVersion}
184
- #
185
- # @example Describe the create command
186
- # kitchen help create
187
- # @example Create a Test Kitchen instance
188
- # kitchen create default-ubuntu
189
- # @example Describe the destroy command
190
- # kitchen help destroy
191
- # @example Destroy a Test Kitchen instance
192
- # kitchen destroy default-ubuntu
193
- # @version 2
194
- class ::Kitchen::Driver::Terraform < ::Kitchen::Driver::Base
195
- kitchen_driver_api_version 2
196
-
197
- no_parallel_for(
198
- :create,
199
- :converge,
200
- :setup,
201
- :destroy
202
- )
203
-
204
- include ::Kitchen::Terraform::ConfigAttribute::BackendConfigurations
205
-
206
- include ::Kitchen::Terraform::ConfigAttribute::Client
207
-
208
- include ::Kitchen::Terraform::ConfigAttribute::Color
209
-
210
- include ::Kitchen::Terraform::ConfigAttribute::CommandTimeout
211
-
212
- include ::Kitchen::Terraform::ConfigAttribute::Lock
213
-
214
- include ::Kitchen::Terraform::ConfigAttribute::LockTimeout
215
-
216
- include ::Kitchen::Terraform::ConfigAttribute::Parallelism
217
-
218
- include ::Kitchen::Terraform::ConfigAttribute::PluginDirectory
219
-
220
- include ::Kitchen::Terraform::ConfigAttribute::RootModuleDirectory
221
-
222
- include ::Kitchen::Terraform::ConfigAttribute::VariableFiles
223
-
224
- include ::Kitchen::Terraform::ConfigAttribute::Variables
225
-
226
- include ::Kitchen::Terraform::ConfigAttribute::VerifyVersion
227
-
228
- include ::Kitchen::Terraform::Configurable
229
-
230
- # Applies changes to the state by selecting the test workspace, updating the dependency modules, validating the root
231
- # module, and applying the state changes.
232
- #
233
- # @raise [::Kitchen::ActionFailed] if the result of the action is a failure.
234
- # @return [void]
235
- def apply(&block)
236
- verify_version
237
- run_workspace_select_instance
238
- apply_run
239
- rescue ::Kitchen::Terraform::Error => error
240
- raise ::Kitchen::ActionFailed, error.message
241
- end
242
-
243
- # Creates a Test Kitchen instance by initializing the working directory and creating a test workspace.
244
- #
245
- # @param _state [::Hash] the mutable instance and driver state.
246
- # @raise [::Kitchen::ActionFailed] if the result of the action is a failure.
247
- # @return [void]
248
- def create(_state)
249
- verify_version
250
- create_run_init
251
- run_workspace_select_instance
252
- rescue ::Kitchen::Terraform::Error => error
253
- raise ::Kitchen::ActionFailed, error.message
254
- end
255
-
256
- # Destroys a Test Kitchen instance by initializing the working directory, selecting the test workspace,
257
- # deleting the state, selecting the default workspace, and deleting the test workspace.
258
- #
259
- # @param _state [::Hash] the mutable instance and driver state.
260
- # @raise [::Kitchen::ActionFailed] if the result of the action is a failure.
261
- # @return [void]
262
- def destroy(_state)
263
- verify_version
264
- destroy_run_init
265
- run_workspace_select_instance
266
- destroy_run_destroy
267
- destroy_run_workspace_select_default
268
- destroy_run_workspace_delete_instance
269
- rescue ::Kitchen::Terraform::Error => error
270
- raise ::Kitchen::ActionFailed, error.message
271
- end
272
-
273
- # Retrieves the Terraform input variables for a Kitchen instance provided by the configuration.
274
- #
275
- # @return [self]
276
- # @yieldparam inputs [::Hash] the input variables.
277
- def retrieve_inputs
278
- yield inputs: config_variables
279
-
280
- self
281
- end
282
-
283
- # Retrieves the Terraform state outputs for a Kitchen instance by selecting the test workspace and fetching the
284
- # outputs.
40
+ # @see http://www.rubydoc.info/gems/test-kitchen/Kitchen
41
+ module Kitchen
42
+ # This namespace is defined by Kitchen.
285
43
  #
286
- # @raise [::Kitchen::ActionFailed] if the result of the action is a failure.
287
- # @return [self]
288
- # @yieldparam outputs [::Hash] the state output.
289
- def retrieve_outputs(&block)
290
- run_workspace_select_instance
291
- ::Kitchen::Terraform::Command::Output.run(
292
- client: config_client,
293
- options: { cwd: config_root_module_directory, live_stream: debug_logger, timeout: config_command_timeout },
294
- &block
295
- )
296
-
297
- self
298
- rescue ::Kitchen::Terraform::Error => error
299
- raise ::Kitchen::ActionFailed, error.message
300
- end
301
-
302
- private
303
-
304
- attr_accessor :debug_logger
305
-
306
- def apply_run
307
- apply_run_get
308
- apply_run_validate
309
- apply_run_apply
310
- end
311
-
312
- # @api private
313
- def apply_run_apply
314
- ::Kitchen::Terraform::ShellOut.run(
315
- client: config_client,
316
- command: "apply " \
317
- "#{lock_flag} " \
318
- "#{lock_timeout_flag} " \
319
- "-input=false " \
320
- "-auto-approve=true " \
321
- "#{color_flag} " \
322
- "#{parallelism_flag} " \
323
- "-refresh=true " \
324
- "#{variables_flags} " \
325
- "#{variable_files_flags}",
326
- options: {
327
- cwd: config_root_module_directory,
328
- live_stream: logger,
329
- timeout: config_command_timeout,
330
- },
331
- )
332
- end
333
-
334
- # @api private
335
- def apply_run_get
336
- ::Kitchen::Terraform::ShellOut.run(
337
- client: config_client,
338
- command: "get -update",
339
- options: {
340
- cwd: config_root_module_directory,
341
- live_stream: logger,
342
- timeout: config_command_timeout,
343
- },
344
- )
345
- end
346
-
347
- # @api private
348
- def apply_run_validate
349
- ::Kitchen::Terraform::ShellOut.run(
350
- client: config_client,
351
- command: "validate " \
352
- "#{color_flag} " \
353
- "#{variables_flags} " \
354
- "#{variable_files_flags}",
355
- options: {
356
- cwd: config_root_module_directory,
357
- live_stream: logger,
358
- timeout: config_command_timeout,
359
- },
360
- )
361
- end
362
-
363
- # @api private
364
- def backend_configurations_flags
365
- config_backend_configurations.map do |key, value|
366
- "-backend-config=\"#{key}=#{value}\""
367
- end.join " "
368
- end
369
-
370
- # api private
371
- def color_flag
372
- config_color and "" or "-no-color"
373
- end
374
-
375
- # @api private
376
- def create_run_init
377
- ::Kitchen::Terraform::ShellOut.run(
378
- client: config_client,
379
- command: "init " \
380
- "-input=false " \
381
- "#{lock_flag} " \
382
- "#{lock_timeout_flag} " \
383
- "#{color_flag} " \
384
- "-upgrade " \
385
- "-force-copy " \
386
- "-backend=true " \
387
- "#{backend_configurations_flags} " \
388
- "-get=true " \
389
- "-get-plugins=true " \
390
- "#{plugin_directory_flag}" \
391
- "-verify-plugins=true",
392
- options: {
393
- cwd: config_root_module_directory,
394
- live_stream: logger,
395
- timeout: config_command_timeout,
396
- },
397
- )
398
- end
399
-
400
- # @api private
401
- def destroy_run_destroy
402
- ::Kitchen::Terraform::ShellOut.run(
403
- client: config_client,
404
- command: "destroy " \
405
- "-auto-approve " \
406
- "#{lock_flag} " \
407
- "#{lock_timeout_flag} " \
408
- "-input=false " \
409
- "#{color_flag} " \
410
- "#{parallelism_flag} " \
411
- "-refresh=true " \
412
- "#{variables_flags} " \
413
- "#{variable_files_flags}",
414
- options: {
415
- cwd: config_root_module_directory,
416
- environment: { "TF_WARN_OUTPUT_ERRORS" => "true" },
417
- live_stream: logger,
418
- timeout: config_command_timeout,
419
- },
420
- )
421
- end
422
-
423
- # @api private
424
- def destroy_run_init
425
- ::Kitchen::Terraform::ShellOut.run(
426
- client: config_client,
427
- command: "init " \
428
- "-input=false " \
429
- "#{lock_flag} " \
430
- "#{lock_timeout_flag} " \
431
- "#{color_flag} " \
432
- "-force-copy " \
433
- "-backend=true " \
434
- "#{backend_configurations_flags} " \
435
- "-get=true " \
436
- "-get-plugins=true " \
437
- "#{plugin_directory_flag}" \
438
- "-verify-plugins=true",
439
- options: {
440
- cwd: config_root_module_directory,
441
- live_stream: logger,
442
- timeout: config_command_timeout,
443
- },
444
- )
445
- end
446
-
447
- # @api private
448
- def destroy_run_workspace_delete_instance
449
- ::Kitchen::Terraform::ShellOut.run(
450
- client: config_client,
451
- command: "workspace delete #{workspace_name}",
452
- options: {
453
- cwd: config_root_module_directory,
454
- live_stream: logger,
455
- timeout: config_command_timeout,
456
- },
457
- )
458
- end
459
-
460
- # @api private
461
- def destroy_run_workspace_select_default
462
- ::Kitchen::Terraform::ShellOut.run(
463
- client: config_client,
464
- command: "workspace select default",
465
- options: {
466
- cwd: config_root_module_directory,
467
- live_stream: logger,
468
- timeout: config_command_timeout,
469
- },
470
- )
471
- end
472
-
473
- def initialize(config = {})
474
- super
475
- self.debug_logger = ::Kitchen::Terraform::DebugLogger.new logger
476
- end
477
-
478
- # @api private
479
- def lock_flag
480
- "-lock=#{config_lock}"
481
- end
482
-
483
- # @api private
484
- def lock_timeout_flag
485
- "-lock-timeout=#{config_lock_timeout}s"
486
- end
487
-
488
- # @api private
489
- def parallelism_flag
490
- "-parallelism=#{config_parallelism}"
491
- end
492
-
493
- # @api private
494
- def plugin_directory_flag
495
- if config_plugin_directory
496
- "-plugin-dir=\"#{::Shellwords.shelljoin ::Shellwords.shellsplit config_plugin_directory}\" "
497
- else
498
- ""
499
- end
500
- end
501
-
502
- # @api private
503
- def run_workspace_select_instance
504
- ::Kitchen::Terraform::ShellOut.run(
505
- client: config_client,
506
- command: "workspace select #{workspace_name}",
507
- options: {
508
- cwd: config_root_module_directory,
509
- live_stream: logger,
510
- timeout: config_command_timeout,
511
- },
512
- )
513
- rescue ::Kitchen::Terraform::Error
514
- ::Kitchen::Terraform::ShellOut.run(
515
- client: config_client,
516
- command: "workspace new #{workspace_name}",
517
- options: {
518
- cwd: config_root_module_directory,
519
- live_stream: logger,
520
- timeout: config_command_timeout,
521
- },
522
- )
523
- end
524
-
525
- # @api private
526
- def variable_files_flags
527
- config_variable_files.map do |path|
528
- "-var-file=\"#{::Shellwords.shelljoin ::Shellwords.shellsplit path}\""
529
- end.join " "
530
- end
531
-
532
- # @api private
533
- def variables_flags
534
- config_variables.map do |key, value|
535
- "-var=\"#{key}=#{value}\""
536
- end.join " "
537
- end
538
-
539
- def verify_version
540
- if config_verify_version
541
- ::Kitchen::Terraform::VerifyVersion.call
542
- else
543
- logger.warn "Verification of support for the available version of Terraform is disabled"
44
+ # @see http://www.rubydoc.info/gems/test-kitchen/Kitchen/Driver
45
+ module Driver
46
+
47
+ # The driver is the bridge between Test Kitchen and Terraform. It manages the
48
+ # {https://www.terraform.io/docs/state/index.html state} of the Terraform root module by shelling out and running
49
+ # Terraform commands.
50
+ #
51
+ # === Commands
52
+ #
53
+ # The following command-line commands are provided by the driver.
54
+ #
55
+ # ==== kitchen create
56
+ #
57
+ # {include:Kitchen::Terraform::Driver::Create}
58
+ #
59
+ # ==== kitchen destroy
60
+ #
61
+ # {include:Kitchen::Terraform::Driver::Destroy}
62
+ #
63
+ # === Configuration Attributes
64
+ #
65
+ # The configuration attributes of the driver control the behaviour of the Terraform commands that are run. Within the
66
+ # {http://kitchen.ci/docs/getting-started/kitchen-yml Test Kitchen configuration file}, these attributes must be
67
+ # declared in the +driver+ mapping along with the plugin name.
68
+ #
69
+ # driver:
70
+ # name: terraform
71
+ # a_configuration_attribute: some value
72
+ #
73
+ # ==== backend_configurations
74
+ #
75
+ # {include:Kitchen::Terraform::ConfigAttribute::BackendConfigurations}
76
+ #
77
+ # ==== client
78
+ #
79
+ # {include:Kitchen::Terraform::ConfigAttribute::Client}
80
+ #
81
+ # ==== color
82
+ #
83
+ # {include:Kitchen::Terraform::ConfigAttribute::Color}
84
+ #
85
+ # ==== command_timeout
86
+ #
87
+ # {include:Kitchen::Terraform::ConfigAttribute::CommandTimeout}
88
+ #
89
+ # ==== lock
90
+ #
91
+ # {include:Kitchen::Terraform::ConfigAttribute::Lock}
92
+ #
93
+ # ==== lock_timeout
94
+ #
95
+ # {include:Kitchen::Terraform::ConfigAttribute::LockTimeout}
96
+ #
97
+ # ==== parallelism
98
+ #
99
+ # {include:Kitchen::Terraform::ConfigAttribute::Parallelism}
100
+ #
101
+ # ==== plugin_directory
102
+ #
103
+ # {include:Kitchen::Terraform::ConfigAttribute::PluginDirectory}
104
+ #
105
+ # ==== root_module_directory
106
+ #
107
+ # {include:Kitchen::Terraform::ConfigAttribute::RootModuleDirectory}
108
+ #
109
+ # ==== variable_files
110
+ #
111
+ # {include:Kitchen::Terraform::ConfigAttribute::VariableFiles}
112
+ #
113
+ # ==== variables
114
+ #
115
+ # {include:Kitchen::Terraform::ConfigAttribute::Variables}
116
+ #
117
+ # ==== verify_version
118
+ #
119
+ # {include:Kitchen::Terraform::ConfigAttribute::VerifyVersion}
120
+ #
121
+ # === Ruby Interface
122
+ #
123
+ # This class implements the interface of Kitchen::Configurable which requires the following Reek suppressions:
124
+ # :reek:MissingSafeMethod { exclude: [ finalize_config! ] }
125
+ #
126
+ # @example Describe the create command
127
+ # kitchen help create
128
+ # @example Create a Test Kitchen instance
129
+ # kitchen create default-ubuntu
130
+ # @example Describe the destroy command
131
+ # kitchen help destroy
132
+ # @example Destroy a Test Kitchen instance
133
+ # kitchen destroy default-ubuntu
134
+ # @version 2
135
+ class Terraform < ::Kitchen::Driver::Base
136
+ kitchen_driver_api_version 2
137
+
138
+ no_parallel_for(
139
+ :create,
140
+ :converge,
141
+ :setup,
142
+ :destroy
143
+ )
144
+
145
+ include ::Kitchen::Terraform::ConfigAttribute::BackendConfigurations
146
+
147
+ include ::Kitchen::Terraform::ConfigAttribute::Client
148
+
149
+ include ::Kitchen::Terraform::ConfigAttribute::Color
150
+
151
+ include ::Kitchen::Terraform::ConfigAttribute::CommandTimeout
152
+
153
+ include ::Kitchen::Terraform::ConfigAttribute::Lock
154
+
155
+ include ::Kitchen::Terraform::ConfigAttribute::LockTimeout
156
+
157
+ include ::Kitchen::Terraform::ConfigAttribute::Parallelism
158
+
159
+ include ::Kitchen::Terraform::ConfigAttribute::PluginDirectory
160
+
161
+ include ::Kitchen::Terraform::ConfigAttribute::RootModuleDirectory
162
+
163
+ include ::Kitchen::Terraform::ConfigAttribute::VariableFiles
164
+
165
+ include ::Kitchen::Terraform::ConfigAttribute::Variables
166
+
167
+ include ::Kitchen::Terraform::ConfigAttribute::VerifyVersion
168
+
169
+ include ::Kitchen::Terraform::Configurable
170
+
171
+ # Creates a Test Kitchen instance by initializing the working directory and creating a test workspace.
172
+ #
173
+ # @param _state [Hash] the mutable instance and driver state.
174
+ # @raise [Kitchen::ActionFailed] if the result of the action is a failure.
175
+ # @return [void]
176
+ def create(_state)
177
+ create_strategy.call
178
+ rescue => error
179
+ action_failed.call message: error.message
180
+ end
181
+
182
+ # Destroys a Test Kitchen instance by initializing the working directory, selecting the test workspace,
183
+ # deleting the state, selecting the default workspace, and deleting the test workspace.
184
+ #
185
+ # @param _state [Hash] the mutable instance and driver state.
186
+ # @raise [Kitchen::ActionFailed] if the result of the action is a failure.
187
+ # @return [void]
188
+ def destroy(_state)
189
+ destroy_strategy.call
190
+ rescue => error
191
+ action_failed.call message: error.message
192
+ end
193
+
194
+ # #finalize_config! invokes the super implementation and then initializes the strategies.
195
+ #
196
+ # @param instance [Kitchen::Instance] an associated instance.
197
+ # @raise [Kitchen::ClientError] if the instance is nil.
198
+ # @return [self]
199
+ # @see Kitchen::Configurable#finalize_config!
200
+ def finalize_config!(instance)
201
+ super instance
202
+ self.create_strategy = ::Kitchen::Terraform::Driver::Create.new(
203
+ config: config,
204
+ logger: logger,
205
+ version_requirement: version_requirement,
206
+ workspace_name: workspace_name,
207
+ )
208
+ self.destroy_strategy = ::Kitchen::Terraform::Driver::Destroy.new(
209
+ config: config,
210
+ logger: logger,
211
+ version_requirement: version_requirement,
212
+ workspace_name: workspace_name,
213
+ )
214
+
215
+ self
216
+ end
217
+
218
+ # #initialize prepares a new instance of the class.
219
+ #
220
+ # @param config [Hash] the driver configuration.
221
+ # @return [Kitchen::Driver::Terraform]
222
+ def initialize(config = {})
223
+ super config
224
+ self.action_failed = ::Kitchen::Terraform::Raise::ActionFailed.new logger: logger
225
+ end
226
+
227
+ private
228
+
229
+ attr_accessor :action_failed, :create_strategy, :destroy_strategy
544
230
  end
545
231
  end
546
-
547
- def workspace_name
548
- @workspace_name ||= "kitchen-terraform-#{::Shellwords.escape instance.name}"
549
- end
550
232
  end