Tech Notes #2: Terraform Test Framework & random Github Copilot Tips
Welcome to the second edition of my new series called Tech Notes (Working Name). The idea is to share what I am currently learning in tech to perhaps inspire you to want to look into the same topics!
It will be anything and everything. It is not always topics that I master so I am not an authority on what I am writing about I am simply sharing my insights and learning process. It can be something small or not, who knows.
I hope I can inspire you to do the same!
Terraform Testing Framework
There are built in commands that you can use to "test" that your Terraform configuration is valid. I am thinking of course of terraform validate for example. However this just ensures that your code is syntactically correct, not much else.
It does not validate that your code logic actually does what you want or that your varible validation blocks actually enforce what they should enforce.
Enter .tftest.hcl files. It seems pretty pragmatic to use one defaults/unit test file and one full integration test file. Inside of a run block with Terraform tests you can define if the block should use command = plan or command = apply - you use plan for validation and unit testing. You use apply for full integration tests that will actually deploy resources.
run "name_of_test_step" {
command = plan
}
Variables
Inside of a test file you can provide a variable block such as a "top level" variable block that will be inherited by all run blocks. Or you can provide them inside the run block as well to override and test different scenarios.
run "name_of_test_step" {
command = plan
variables {
variable_name = "variable_value"
}
}
Assert if something is true or expect failures
Inside a run block you use assert to test if something is true and you use expect_failures if you want to input something invalid and make sure that Terraform throws an error as expected. This is useful if you have a validation = {} block inside your variable.
[...]
variables {
environment = "dev"
location_short = "sc"
week_of_year = 100
}
assert {
condition = azapi_resource.vm.name == "vm-dev-sc-test"
error_message = "The VM name should equal vm-dev-sc-test"
}
expect_failures = [ var.week_of_year ]
[...]
In the above we use string interpolation in the actual terraform config to set the name = name = "vm-${var.environment}-${var.location_short}-test" so the benefit of the test if to ensure that the string interpolation works.
In expect_failures we say that the variable week_of_year only accepts a number between 1-52 so the given value here of 100 should throw an error, and that is what we are making sure happens.
Mocking the provider
mock_provider "azapi" {} tells Terraform to mock or simulate calls to the AzAPI provider. We are not making real calls and therefor we don't need real values and there is no need to authenticate and no network access is required, perfect for our simple tests here!
Random Github Copilot Tips
Use # to reference files and folders
In github copilot chat you can use # to get the list of files you can reference without having to click the "Attach" button, works for folders as well. If you are using Github Copilot CLI you can do the same with the @ sign.
Use /fleet mode
/fleet inside of Copilot CLI allows you to run parallel agents that can execute tasks simultaneously
Add [skip-ci] to skip CICD (Not Copilot but I thought it was good)
In Github you can add [skip-ci] to your commit message and any CI/CD jobs that would run following a commit will be skipped.
This is useful if you for example have OPA checking your blast radius inside Terraform pipelines. You may know that a change will exceed a certain threshold, say 100, and this is the intended change that should happen. Append [skip-ci] to the merge commit and then run the pipeline again manually assigning a higher value, saving time!
Conclusion
Thank you for reading! I hope I inspired you to learn something new and share as well!
