CODE IN THIS REPOSITORY IS NOT READY TO BE USED PUBLICLY, BUT IT WILL BE GOOD AFTER SUMMER BREAK!
Terrapin is a Terraform module generator which supports creation of Terraform configuration files, automated tests, usage examples and documentation.
Terrapin process source files and generates complete module. At its simplest, a command-line call
./bin/generate_module.sh --module aws_bastion_s3_keys
will create complete module inside ./output/modules/aws_bastion_s3_keys
.
Terrapin is designed with a goal to generate canonical code for terraform-community-modules. Read my blog post about common traits in modules.
Terrapin supports all types of providers available in Terraform 0.9.
It is not going to take your job (at least not yet). Developers should still design infrastructure components and understand how Terraform works.
Using Terrapin developers focus on creating rather DRY template files, which is then used to generate the rest (tests, documentation and examples). All Terraform properties like variables, outputs, tfvars and defaults are generated from source templates, type of attributes is validated.
See code inside modules/aws_bastion_s3_keys
for reference.
Terrapin (wiki: portable building) is a type of prefabricated one-storey building for temporary use.
jinja2-cli
To run acceptance tests you will need to have Ruby 2.4+ with these gems: test-kitchen kitchen-terraform awspec
.
Source code of modules is inside modules
directory. For example, single module is inside modules/aws_bastion_s3_keys
and source templates are inside templates
directory. meta.yml
is not in currently in use, so you can skip it. templates
directory should contain at least one template file with extension .tf.tpl
.
Terraform templates are being produced from Jinja templates, where full power of Jinja and several custom macros are available. For more detailed examples on usage of Jinja macros check tests in tests/templates/basic
.
Jinja macros are inside templates/macros/macros.jinja2
. There are there custom macros which developers should use in Jinja templates:
Generates Terraform's resource configuration. Use call block to call resource
macros.
Example:
{% call resource("aws_security_group", "bastion") %}
...
{% endcall %}
Generates Terraform's data source configuration. Use call block to call data
macros.
Example:
{% call data("template_file", "user_data") %}
...
{% endcall %}
Generates Terraform configuration code for an argument named argument_name
of resource
or data
block where this macros is called from.
Macro arguments:
argument_name
- Name of the argument to render (required)argument_value
- Value of the argument (optional)description
- A human-friendly description for the variable (optional)default
- Default value for the variable (optional)set_default
- Whether to set default
value for th variable (optional, enabled by default)resource_type
- Resource type to use for this variable. Set this when calling this macros outside of resource
call block (eg, in tests) (optional)data_type
- Data source type to use for this variable. Set this when calling this macros outside of data
call block (eg, in tests) (optional)Example 1:
{% call resource("aws_security_group", "bastion") %}
{{ variable("vpc_id") }}
{% endcall %}
will render:
resource "aws_security_group" "bastion" {
vpc_id = "${var.vpc_id}"
}
Example 2 (set default value in name
parameter, name
is parametrized):
{% call resource("aws_security_group", "bastion") %}
{{ variable("name", default="bastion-vpc") }}
{% endcall %}
will render:
resource "aws_security_group" "bastion" {
name = "${var.name}"
}
// variables() macro will render this:
variable "name" {}
Example 3 (set argument value, name
can't be parametrized):
{% call resource("aws_security_group", "bastion") %}
{{ variable("name", "bastion-vpc") }}
{% endcall %}
will render:
resource "aws_security_group" "bastion" {
name = "bastion-vpc"
}
// variables() macro will not render anything
Notes:
argument_value
is not specified:
${var.argument_name}
.["${var.argument_name}"]
${var.argument_name}
"${var.argument_name}"
argument_name
will be appended to Terraform's variables
Generates Terraform configuration code for a parametrized variable named variable_name
which has type variable_type
.
Macro arguments:
variable_name
- Name of the variable to parametrize (required)variable_type
- Type of the variable (optional). Available values: boolean
, list
, map
or string
(default).description
- A human-friendly description for the variable (optional)default
- Default value for the variable (optional)set_default
- Whether to set default
value for th variable (optional, enabled by default)The differences between define_variable
and variable
macros are:
define_variable
only define variable_name
as a parameter, so that it appears in the list of Terraform's variables (see variables()
macros) and does not render any codedefine_variable
does not relate variable_name
to specific resource or data source type, therefore it requires to provide variable_type
for each variable (default is string).define_variable
allows variable to be parametrized and be used as a part of another variable. In the following example user_data_file
is a parametrized variable with default value (note escaped double quotes). user_data_file
is used as a value inside interpolation of template
value:
{% call data("template_file", "user_data") %}
{{ variable("template", "${file(\"${path.module}/${var.user_data_file}\")}") }}
{{ define_variable("user_data_file", default="\"user_data.sh\"") }}
{% endcall %}
It renders as:
data "template_file" "user_data" {
template = "${file("${path.module}/${var.user_data_file}")}"
}
// variables() macro will render this:
variable "user_data_file" {
default = "user_data.sh"
}
Generates Terraform's variables configuration.
This macros in explicitly invoked only in tests, but in real templates it is appended by helper script (such as ./bin/generate_module.sh
) and developers should not call it into templates.
Generates Terraform's outputs configuration.
This macros in explicitly invoked only in tests, but in real templates it is appended by helper script (such as ./bin/generate_module.sh
) and developers should not call it into templates.
Terrapin currently has a bit more dependencies than it can have. The complete list of dependencies is inside .circleci/images/antonbabenko/terrapin/Dockerfile
.
Create directory modules/YOUR_MODULE/templates/
and put your source template file (main.tf.tpl
) there.
Run ./bin/generate_module.sh --module YOUR_MODULE
and check content of output/modules/YOUR_MODULE
.
Send pull-request to master branch of https://github.com/antonbabenko/terrapin.
main.tf.tpl
) per module.See the LICENSE file for license rights and limitations (MIT).