This project shows an example file/dir structure you can use with Terramate to keep your Terraform code DRY.
Be sure to read through the Terramate documentation to understand the features of Terramate used here.
The example is organized as two environments, each environment will have:
- Its own Google Cloud Project.
- Service account to be used when deploying Cloud Run services.
- Two Cloud Run applications.
The Cloud Run applications are simple echo servers that will be reachable through public URLs provided by Cloud Run.
Note: This code is solely for demonstration purposes. This is not production-ready code, so use it at your own risk.
- Terraform
~> 1.8
- Terramate
~> 0.11.1
- Configure your Google Cloud credentials using one of the supported authentication mechanisms
- Google Cloud Provider account
- At least one Google Cloud project
- The Google Cloud project has a proper billing account configured
This is the overall structure of the project:
├── modules
│ ├── cloud-run
│ └── service-account
└── stacks
├── prod
│ ├── cloud-runs
│ │ ├── app1
│ │ ├── app2
│ └── service-accounts
│ └── cloud-run
└── staging
├── cloud-runs
│ ├── app1
│ ├── app2
└── service-accounts
└── cloud-run
modules/cloud-run
: Local module, useful to showcase change detection and DRY code generation.modules/service-account
: Local Terramate config that keeps code generation DRY between environments.stacks/prod
: All stacks belonging to the prod environment.stacks/staging
: All stacks belonging to the staging environment.stacks/<env>/service-accounts/cloud-run
: Stack that creates service accounts used to execute the cloud run services.stacks/<env>/cloud-runs/{app1,app2}
: Stacks that create Cloud Run services.
As you navigate the project you will find multiple Terramate configuration files. Each file will have documentation guiding you through its purpose and usage.
To check if your Terramate installation is working and get an overview of the available stacks just run:
terramate list
To check how each stack is defined in detail you can use terramate run
:
terramate run -- cat stack.tm.hcl
This will run on each stack directory the command cat stack.tm.hcl
.
The output will be the definition of all stacks.
Later we are going to use the same mechanism to create and destroy all stacks.
Before we try to deploy any stacks, beware that this will require you to have Google Cloud credentials and deploying infrastructure will incur costs (check the pre-requisites section for more details).
On stacks/config.tm.hcl
you will find the terraform_google_provider_project
global which configures the project where infrastructure will be created.
It is important to change that to a Google Cloud project where you have appropriate permissions.
Once the configuration is changed we need to update the generated code by running:
At this point, since our project has uncommitted changes Terramate will prevent us
from running any commands. Create a branch (or use the flag --disable-check-git-uncommitted
to disable the git checks):
git checkout -b <your branch name>
And commit all the changed files.
Now we initialize all our stacks:
terramate run -- terraform init
Check how their plans look like:
terramate run -- terraform plan
And apply them:
terramate run -- terraform apply
For each Cloud Run service deployed, there will be an output with the URL to the deployed service, like this:
url = "https://terramate-app1-<env>-<hash>-lz.a.run.app"
You can check the outputs with:
terramate run -- terraform output
Open the URL on the browser to check the running service.
To avoid unnecessary charges to your account let's destroy all stacks:
terramate run --reverse -- terraform destroy
The --reverse
flag runs all stacks in reversed order, which is desirable
when destroying resources.