CNI is heavily reliant on terraform modules and we create the module for the other teams to use. In order to assure that the modules will do what it needs to without applying the code ourselves we created the tftest framework. This is specially important to check that the module will not destroy existing infrastructure.
To implement tests on both module and the implementation of module. If we have properties that are tested using args.
To implement test on just the module if we dont have any properties to test on the implementation.
'name'
- (string) Module to be exported from thetests.js
'description'
- (string) Description of the tests which will be shown on jasmine stdout with (√) or (x).'changeWindow'
- (object: to, from) This is used for destroy and create. For a window of time the tests will be skipped. Implementation Reference changeWindow'count'
- (integer) The number of times to run the tests should be same with the terraform code. This should match the var.count parameter in module if it exists'args'
- (object) Argument to be created in thetests.js
this will be used in the tests function'tests'
- (array of functions) Tests to be run against the module this should have expectations
- Create a new module
- Create tests.js under the new module's folder. We create the
tests.js
here to test what is in the module like a unit test. To use this test we need to add a file calledmodules.js
under the folder of the module implementation.
# cd /module/truthy
# cat tests.js
# sample
module.exports = [{
'name': 'aws_instance.dummy',
'count': 1,
'args': {},
'tests': [
function (obj, args) {
if ('dummy_condition' in obj.new.hasOwnProperty) {
expect(obj.new.dummy_condition).toEqual(true);
}
}
]
}
];
- Create the implementation of the module
- Create
tests.js
andmodule.js
on the implementation folder. We createtests.js
in the implementation to test the values of the properties. For example in this case we want truthy to have the value of true.
# cd /implementation/truthy
# cat modules.js
module.exports = [
{ name: 'aws_instance', prefix: 'dummy' }
];
# cat tests.js
const dummy_properties = {
"truthy": "true"
}
module.exports = [{
'name': 'dummy.aws_instance.dummy',
'description': 'Ensure true is equal to true',
'count': 1,
'args': {},
'tests': [
function (obj, args) {
if ('truthy' in obj.new.hasOwnProperty) {
expect(obj.new.truthy).toEqual(true);
}
}
]
}
];
- Get the plan of the implementation. In the implementation directory run
terraform init
andterraform plan -out=plan.out
- Install the tftest using
npm install -g @condenast/tftest
- In the implementation directory run
tftest test -p plan.out
- To debug the terraform plan json run
tftest show -p plan.out
- ec2-example
- ec2-example-withChangeWindow
- ec2-example-withIncorrectNumberOfTests
- ec2-example-using-has_changes
- vpc-example
- vpc-iam-example
- rds-cnid-terraform-modules
- rds-implementation-cnid-infrastructure
Since we are using javascript in testing the terraform module we can use any
arbitrary javascript function under 'tests'
function in the module.exports
condition
in order to write tests. By default we use jasmine
expectations.
obj
and args
are passed in the jasmine function.
obj
will contain terraform plan object which will have obj.new
and obj.old
- Use a javascript linter for tests
- Keep the code as independent as possible without using
node_modules
- Write tests for each resource
- tftest now looks for
tests.js
in the current working directory to discover modules that are being used, and their "prefix" - tftest will now examine
.terraform/modules/modules.json
to detect any modules that contain atests.js
file. - tftest executes the tests against the plan file, if any tests fail the return code is non-zero.
npm install @condenast/tftest -g
git clone [email protected]:conde-nast-international/tftest.git
cd tftest
npm install
$ tftest -h
Usage: tftest [options] [command]
Options:
-V, --version output the version number
-h, --help output usage information
Commands:
test [options] test
show [options] show
show-resources [options] show-resources
gettfjson gettfjson
This program uses debug to be able to debug use environment variable DEBUG
Example:
$ ENV DEBUG=tftest,generic bin/tftest show -p spec/lib/fixtures/simple-create.plan
It's possible to combine multiple files names using ,
.
Value should be name of file that you want to debug.
Available values for DEBUG
:
- tftest
- filesystem
- generic
- plan
- runner