Lesson 106 Structure
In the last Chapter we covered tools, this chapter focussed on structure.
Terraform is a declarative data driven language.
- As a rule design for replication and clarity and not for logic constructs.
- Design for a lower cognitive load.
How should I layout Terraform project
When I first started writing Terraform I wrote a lot of wrapper scripts now I aim to write none.
-
no wrapper scripts Exception- Well I sometime create a makefile or equivalent.
-
Call Terraform on a given path. You may have to repeat yourself but it makes up for it in for clarity and portability.
-
For application related infrastructure, keep the tf with the code it relates to.
-
Account level/environments code is best kept separate, this would be VPC, routing, security. With Cloud native services, The separation between Infrastructure from application is getting less defined (see lesson 201).
-
Preference is for Clarity, repeat for clarity.
Files
Naming lowercase with _ separators.
Standard files variables.tf,outputs.tf, locals.tf
I follow a 1 resource per file with files named after resources, although dumping in main.tf is common
- easier to navigate
- easier to compare
- easier to debug
Testing
As alluded previously to, I have yet to fins a satisfactory tool/solution for unit testing
- Checkov.
- Terraform init, plan, fmt, validate.
- Only test whats you can reasonably be expected to fix.
Some use AWS-spec. I do not.
Modules
I have a standard process and skeleton for starting, building, documenting and versioning modules.
This is the MVP of module creation:
Make a copy of the Lambda code from lesson 4.
Create a folder called example, and move the provider to it. Then add module.lambda.tf
module "lambda" {
source="../"
}
in aws_lambda_function.hello_world.tf
resource "aws_lambda_function" "hello_world" {
filename = "${path.module}/lambda.zip"
function_name = var.name
handler = "lambda.lambda_handler"
role = data.aws_iam_role.basic.arn
runtime = "python3.7"
source_code_hash = data.archive_file.hello-world.output_base64sha256
}
And add variables.tf
variable "name" {
description="The name of the lambda"
type=string
}
Your module now requires the value for var.name, add that to your module reference in example, put your own value for the name:
module "lambda" {
source= "../"
name = "James made me do it"
}
Open the example folder in your console, and Terraform init and apply.
That's the basics.
- Create build process for modules.
- Build to TF module guidelines.
- Build for the Registry.
- Don't put all your modules in a monolith repo, amongst other things this makes versioning hard.
- private repos, are forgotten not reused, never get seen or tested.
Refactor
Using the lessons from earlier refactor this chapter.
Exercises
- Add a reference to a version of a module.
Takeaways
- modules are like micro-services, keep them separate.