Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Add Terraform Transport (#500)
Browse files Browse the repository at this point in the history
* Add transport plugin

* Define Connection

* Rufo format

* Add private to init_options docs

* Extend Exec transport

* Remove erroneous serial actions configuration

* Remove redundant method references

* Add transport to driver

* Override run_command instead of execute

* Add null logger for tests

* Use transport connections for CLI

* Use test logger

* Apply rufo

* Document transport, verifier modules

* Add options accessor for Ruby 2.6

* Disable TooManyStatements detector

* Deprecate driver.client

* Refactor doctor design

* Move command_timeout to transport

* Move root_module_directory to transport

* Clear warnings

* Update deprecated config usage

* Update CHANGELOG

* Update documentation

* Fix doctor-transport attributes

* Add deprecated-driver-attributes suite

* Fix Ruby 2.6 private method access

* Restore code coverage of deprecated driver config

---------

Co-authored-by: Aaron Lane <2400330-aaron-lane@users.noreply.gitlab.com>
  • Loading branch information
aaron-lane and Aaron Lane authored Mar 9, 2023
1 parent 26811dd commit baa176c
Show file tree
Hide file tree
Showing 44 changed files with 905 additions and 1,214 deletions.
3 changes: 3 additions & 0 deletions .reek.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
detectors:
TooManyStatements:
enabled: false
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@ and this project adheres to

### Added

- A Terraform transport plugin
- Support for Inspec < 6.0
- Support for `kitchen doctor` command: initially validates driver.client and verifier.systems
- Support for the `kitchen doctor` command, which checks for deprecated
or invalid configuration attributes

### Changed

- Deprecated some driver configuration attributes which are assumed by
the transport:
- `client`
- `command_timeout`
- `root_module_directory`
- Dropped support for Inspec < 4.25.1

## [6.1.0] - 2022-01-22
Expand Down
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,23 @@ A familiarity with [Test Kitchen][test-kitchen] workflows and commands is requir

### Configuration

Kitchen-Terraform provides three Test Kitchen plugins which must be
Kitchen-Terraform provides four Test Kitchen plugins which must be
configured in a
[Test Kitchen configuration file][kitchen-configuration-file] in
order to successfully test Terraform configuration.

The [Terraform driver][terraform-driver] manages the state of the
Terraform root module.
The [Terraform driver][terraform-driver] is the bridge between Test
Kitchen and Terraform. It manages the [state][terraform-state] of the
Terraform root module under test by shelling out and running Terraform commands.

The [Terraform provisioner][terraform-provisioner] uses the Terraform
driver to apply changes to the Terraform state.
The [Terraform provisioner][terraform-provisioner] applies changes to
the Terraform state based on the configuration of the root module.

The [Terraform verifier][terraform-verifier] uses InSpec to verify the
Terraform state.
The [Terraform transport][terraform-transport] is responsible for the
integration with the Terraform CLI.

The [Terraform verifier][terraform-verifier] utilizes InSpec to verify
the behaviour and state of resources in the Terraform state.

More information can be found in the
[Ruby gem documentation][ruby-gem-documentation].
Expand Down Expand Up @@ -260,7 +264,7 @@ Kitchen-Terraform is distributed under the [Apache License][license].
[gem-version-shield]: https://img.shields.io/gem/v/kitchen-terraform.svg
[gitter-shield]: https://img.shields.io/gitter/room/kitchen-terraform/Lobby.svg
[gitter]: https://gitter.im/kitchen-terraform/Lobby
[inspec]: https://www.inspec.io/
[inspec]: https://community.chef.io/tools/chef-inspec
[int-kitchen-config]: https://github.com/newcontext-oss/kitchen-terraform/blob/master/kitchen.yml
[kitchen-configuration-file]: https://docs.chef.io/config_yml_kitchen.html
[kitchen-terraform-gem]: https://rubygems.org/gems/kitchen-terraform
Expand All @@ -281,10 +285,12 @@ Kitchen-Terraform is distributed under the [Apache License][license].
[rubygems-installing-gems]: http://guides.rubygems.org/rubygems-basics/#rubygems-installing-gems
[technical-debt-shield]: https://img.shields.io/codeclimate/tech-debt/newcontext-oss/kitchen-terraform.svg
[technical-debt]: https://codeclimate.com/github/newcontext-oss/kitchen-terraform/
[terraform-cli]: https://www.terraform.io/docs/commands/index.html
[terraform-cli]: https://developer.hashicorp.com/terraform/cli/commands
[terraform-driver]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Driver/Terraform
[terraform-install]: https://www.terraform.io/intro/getting-started/install.html
[terraform-provisioner]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Provisioner/Terraform
[terraform-state]: https://developer.hashicorp.com/terraform/language/state
[terraform-transport]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Transport/Terraform
[terraform-verifier]: http://www.rubydoc.info/github/newcontext-oss/kitchen-terraform/Kitchen/Verifier/Terraform
[terraform]: https://www.terraform.io/
[test-directory]: https://github.com/newcontext-oss/kitchen-terraform/tree/master/test
Expand Down
40 changes: 34 additions & 6 deletions kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@ driver:
name: terraform
provisioner:
name: terraform
transport:
name: terraform
verifier:
name: terraform
fail_fast: false
platforms:
- name: macos
driver:
transport:
client: terragrunt
- name: ubuntu
- name: windows
suites:
- name: attributes
driver:
root_module_directory: test/terraform/attributes
variables:
passthrough: value
transport:
root_module_directory: test/terraform/attributes
verifier:
systems:
- name: default
Expand Down Expand Up @@ -55,7 +58,7 @@ suites:
excludes:
- macos
- windows
driver:
transport:
root_module_directory: test/terraform/backend-ssh
verifier:
systems:
Expand Down Expand Up @@ -85,15 +88,37 @@ suites:
shell_command: /bin/sh
shell_options: -x
user: root
- name: deprecated-driver-attributes
includes:
- macos
driver:
client: terragrunt
root_module_directory: test/terraform/attributes
variables:
passthrough: value
transport:
name: ssh
verifier:
systems:
- name: default
backend: local
controls:
- default
profile_locations:
- test/integration/attributes
- name: doctor-driver
driver:
client: /nonexistent/pathname
- name: doctor-transport
transport:
client: /nonexistent/pathname
- name: doctor-verifier
verifier:
systems: []
- name: plug-ins
driver:
plugin_directory: test/terraform/PlugIns/PlugInDirectory
transport:
root_module_directory: test/terraform/PlugIns
verifier:
systems:
Expand All @@ -103,14 +128,15 @@ suites:
- test/integration/plug-ins
- name: variables
driver:
root_module_directory: test/terraform/variables
variable_files:
- test/terraform/variables/variable_files/Variable File.tfvars
variables:
string: 'A String'
map: '{ key = \"A Value\" }'
list_of_strings: '[ \"Element One\", \"Element Two\" ]'
list_of_maps: '[ { key = \"A List Of Maps Value\" } ]'
transport:
root_module_directory: test/terraform/variables
verifier:
systems:
- name: variable_files
Expand All @@ -127,9 +153,10 @@ suites:
- test/integration/variables
- name: workspace-one
driver:
root_module_directory: test/terraform/workspace
variables:
workspace: one
transport:
root_module_directory: test/terraform/workspace
verifier:
systems:
- name: one
Expand All @@ -138,9 +165,10 @@ suites:
- test/integration/workspace-one
- name: workspace-two
driver:
root_module_directory: test/terraform/workspace
variables:
workspace: two
transport:
root_module_directory: test/terraform/workspace
verifier:
systems:
- name: two
Expand Down
96 changes: 66 additions & 30 deletions lib/kitchen/driver/terraform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
require "kitchen/terraform/configurable"
require "kitchen/terraform/driver/create"
require "kitchen/terraform/driver/destroy"
require "kitchen/terraform/driver/doctor"
require "kitchen/terraform/version_verifier"
require "kitchen/transport/terraform"
require "rubygems"
require "shellwords"

Expand All @@ -45,9 +45,9 @@ module Kitchen
# @see http://www.rubydoc.info/gems/test-kitchen/Kitchen/Driver
module Driver

# The driver is the bridge between Test Kitchen and Terraform. It manages the
# {https://www.terraform.io/docs/state/index.html state} of the Terraform root module by shelling out and running
# Terraform commands.
# The Terraform driver is the bridge between Test Kitchen and Terraform. It manages the
# {https://developer.hashicorp.com/terraform/language/state state} of the Terraform root module under test by
# shelling out and running Terraform commands.
#
# === Commands
#
Expand Down Expand Up @@ -77,6 +77,8 @@ module Driver
#
# ==== client
#
# driver.client is deprecated; use transport.client instead.
#
# {include:Kitchen::Terraform::ConfigAttribute::Client}
#
# ==== color
Expand All @@ -85,6 +87,8 @@ module Driver
#
# ==== command_timeout
#
# driver.command_timeout is deprecated; use transport.command_timeout instead.
#
# {include:Kitchen::Terraform::ConfigAttribute::CommandTimeout}
#
# ==== lock
Expand All @@ -105,6 +109,8 @@ module Driver
#
# ==== root_module_directory
#
# driver.root_module_directory is deprecated; use transport.root_module_directory instead.
#
# {include:Kitchen::Terraform::ConfigAttribute::RootModuleDirectory}
#
# ==== variable_files
Expand Down Expand Up @@ -146,10 +152,15 @@ class Terraform < ::Kitchen::Driver::Base
include ::Kitchen::Terraform::ConfigAttribute::BackendConfigurations

include ::Kitchen::Terraform::ConfigAttribute::Client
deprecate_config_for :client, "driver.client is deprecated; use transport.client instead"

include ::Kitchen::Terraform::ConfigAttribute::Color

include ::Kitchen::Terraform::ConfigAttribute::CommandTimeout
deprecate_config_for(
:command_timeout,
"driver.command_timeout is deprecated; use transport.command_timeout instead"
)

include ::Kitchen::Terraform::ConfigAttribute::Lock

Expand All @@ -160,6 +171,10 @@ class Terraform < ::Kitchen::Driver::Base
include ::Kitchen::Terraform::ConfigAttribute::PluginDirectory

include ::Kitchen::Terraform::ConfigAttribute::RootModuleDirectory
deprecate_config_for(
:root_module_directory,
"driver.root_module_directory is deprecated; use transport.root_module_directory instead"
)

include ::Kitchen::Terraform::ConfigAttribute::VariableFiles

Expand All @@ -169,25 +184,39 @@ class Terraform < ::Kitchen::Driver::Base

include ::Kitchen::Terraform::Configurable

attr_reader :transport

# Creates a Test Kitchen instance by initializing the working directory and creating a test workspace.
#
# @param _state [Hash] the mutable instance and driver state.
# @param state [Hash] the mutable instance and driver state.
# @raise [Kitchen::ActionFailed] if the result of the action is a failure.
# @return [void]
def create(_state)
create_strategy.call
def create(state)
::Kitchen::Terraform::Driver::Create.new(
config: config,
connection: transport.connection(state),
logger: logger,
version_requirement: version_requirement,
workspace_name: workspace_name,
).call
rescue => error
action_failed.call message: error.message
end

# Destroys a Test Kitchen instance by initializing the working directory, selecting the test workspace,
# deleting the state, selecting the default workspace, and deleting the test workspace.
#
# @param _state [Hash] the mutable instance and driver state.
# @param state [Hash] the mutable instance and driver state.
# @raise [Kitchen::ActionFailed] if the result of the action is a failure.
# @return [void]
def destroy(_state)
destroy_strategy.call
def destroy(state)
::Kitchen::Terraform::Driver::Destroy.new(
config: config,
connection: transport.connection(state.merge(environment: { "TF_WARN_OUTPUT_ERRORS" => "true" })),
logger: logger,
version_requirement: version_requirement,
workspace_name: workspace_name,
).call
rescue => error
action_failed.call message: error.message
end
Expand All @@ -197,35 +226,41 @@ def destroy(_state)
# @param state [Hash] the mutable Kitchen instance state.
# @return [Boolean] +true+ if any errors are found; +false+ if no errors are found.
def doctor(state)
driver_errors = ::Kitchen::Terraform::Driver::Doctor.new(
instance_name: instance.name,
logger: logger
).call config: config
errors = false

deprecated_config.each_pair do |attribute, message|
errors = true
logger.warn "driver.#{attribute} is deprecated: #{message}"
end

methods.each do |method|
next if !method.match? /doctor_config_.*/

config_error = send method
errors = errors || config_error
end

transport_errors = transport.doctor state
verifier_errors = instance.verifier.doctor state

driver_errors or verifier_errors
errors || transport_errors || verifier_errors
end

# #finalize_config! invokes the super implementation and then initializes the strategies.
#
# @param instance [Kitchen::Instance] an associated instance.
# @raise [Kitchen::ClientError] if the instance is nil.
# @return [self]
# @see Kitchen::Configurable#finalize_config!
def finalize_config!(instance)
super instance
self.create_strategy = ::Kitchen::Terraform::Driver::Create.new(
config: config,
logger: logger,
version_requirement: version_requirement,
workspace_name: workspace_name,
)
self.destroy_strategy = ::Kitchen::Terraform::Driver::Destroy.new(
config: config,
logger: logger,
version_requirement: version_requirement,
workspace_name: workspace_name,
)
super

transport = instance.transport

self.transport = if ::Kitchen::Transport::Terraform == transport.class
transport
else
::Kitchen::Transport::Terraform.new(config).finalize_config! instance
end

self
end
Expand All @@ -241,7 +276,8 @@ def initialize(config = {})

private

attr_accessor :action_failed, :create_strategy, :destroy_strategy
attr_accessor :action_failed
attr_writer :transport
end
end
end
Loading

0 comments on commit baa176c

Please sign in to comment.