Improving Our Terraform Module Quality by Enforcing Codestyle, aka getting rid of "any" type constraints
Our cloud team has been rapidly building Terraform modules, but many lack proper type constraints. This not only hampers our ability to enhance validations but also prevents us from utilizing automatic documentation features in Terraform, or other third-party tools such as Terraform Docs.
Currently, we often use type = any in our variable definitions:
variable "complex_user_interface_here" {
type = any
}
Using any is discouraged by Terraform, as it offers no real benefits. Please see this link: The "any" constraint.
Most of our variables are static, leading to unnecessary manual documentation and validation efforts. To improve this, we propose the following:
To achieve this, we need to find a way that we can validate the developers/engineers code before it is released to production. At Prudential Services Asia Global Technology Engineering, we are already adopting Rego (Using Conftest as a testing tool), in our self-service workflows to identify and react on infrastructure changes. Thus, it is a no-brainer to widely implement this idea to our development practice and improve the quality of our work.
We created a simple rule to deny any variables defined as any:
package terraform_codestyle
# METADATA
# title: TERRAFORM-DENY-ANY-TYPES-VARIABLES
deny[msg] {
some var
type := input.variable[var].type
contains(type, "any")
msg := sprintf(
"%s: Variables cannot be of type any: %s",
[rego.metadata.rule().title, type]
)
}
Our test workflow now checks for the use of type(any):
$ conftest test modules -p policies --all-namespaces -o github
::group::Testing 'modules/new_module/variables.tf' against 1 policies in namespace 'terraform_codestyle'
::error file=modules/new_module/variables.tf::TERRAFORM-DENY-ANY-TYPES-VARIABLES: Variables cannot be of type any: ${list(any)}
::endgroup::
::group::Testing 'modules/old_modules/buckets/variables.tf' against 1 policies in namespace 'terraform_codestyle'
::error file=modules/old_modules/buckets/variables.tf::TERRAFORM-DENY-ANY-TYPES-VARIABLES: Variables cannot be of type any: ${list(any)}
::endgroup::
::group::Testing 'modules/old_modules/storage_accounts/variables.tf' against 1 policies in namespace 'terraform_codestyle'
::error file=modules/old_modules/storage_accounts/variables.tf::TERRAFORM-DENY-ANY-TYPES-VARIABLES: Variables cannot be of type any: ${list(any)}
::endgroup::
3 tests, 0 passed, 0 warnings, 3 failures, 0 exceptions
Unfortunately, this new change to our workflow is breaking old modules! Imagine having hundreds of existing modules that was built in this way, it would be impossible to refactor the type constraints and ensure it is adapted to pass the new codestyle.
Thankfully, for existing modules, we tell Conftest to ignore specific paths, ensuring we don't disrupt current implementations:
$ conftest test modules -p policies --all-namespaces -o github --ignore "modules/old_modules/"
::group::Testing 'modules/new_module/variables.tf' against 1 policies in namespace 'terraform_codestyle'
::error file=modules/new_module/variables.tf::TERRAFORM-DENY-ANY-TYPES-VARIABLES: Variables cannot be of type any: ${list(any)}
::endgroup::
1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions
By enforcing proper type constraints, we’re on track to enhance the quality and accuracy of our modules.
Next, I will be covering more on how this simple enforcement, will propel two trivial but important aspects of Terraform:
Takaful & Insurance Bancatakaful//Partnership //Employee Benefit
4 个月Sensational
Solutions Architect @ AWS | Public Sector
4 个月good stuff
SRE | pokgak.com | AWS Community Builder
4 个月This is cool! Nice to know other companies using OPA too.