The following guide is for developers working on the blueprint solution - not for developers that are consuming the blueprint.
The following are pre-requisites to working with the solution:
- An Azure subscription for development purposes
- An Azure identity which has been assigned the following roles at the subscription level:
- Contributor (required to create resources)
- Role Based Access Control Administrator (to assign roles to the backup vault managed identity) with a condition that limits the roles which can be assigned to:
- Disk Backup Reader
- Disk Snapshot Contributor
- PostgreSQL Flexible Server Long Term Retention Backup Role
- Storage Account Backup Contributor
- Reader
- Azure CLI installed
- Terraform installed
- Go installed (to run the end-to-end tests)
Ensure all installed components have been added to the %PATH%
- e.g. az
, terraform
and go
.
Take the following steps to get started in configuring and verifying the infrastructure for your development environment:
-
Setup environment variables
Set the following environment variables in order to connect to Azure in the following steps:
$env:ARM_TENANT_ID="<your-tenant-id>" $env:ARM_SUBSCRIPTION_ID="<your-subscription-id>" $env:ARM_CLIENT_ID="<your-client-id>" $env:ARM_CLIENT_SECRET="<your-client-secret>"
-
Create Backend
A backend (e.g. storage account) is required in order to store the tfstate and work with Terraform.
Run the following powershell script to create the backend with default settings:
./scripts/create-tf-backend.ps1
. This script will create a resource group calledrg-nhsbackup
containing a storage account calledsatfstate<random-id>
.Make a note of the name of the storage account in the script output - it's generated with a random suffix, and you'll need it in the following steps to initialise the terraform.
-
Initialise Terraform
Change the working directory to
./infrastructure
.Terraform can now be initialised by running the following command:
terraform init -backend=true -backend-config="resource_group_name=rg-nhsbackup" -backend-config="storage_account_name=<storage-account-name>" -backend-config="container_name=tfstate" -backend-config="key=terraform.tfstate"
-
Prepare Terraform Variables
You need to specify the mandatory terraform variables as a minimum, and may want to specify a number of the optional variables.
You can specify the variables via the command line when executing
terraform apply
, or by preparing a tfvars file and specifying the path to that file.Here are examples of each approach:
terraform apply -var resource_group_name=<resource-group-name> -var backup_vault_name=<backup-vault-name> var tags={"tagOne" = "tagOneValue"} -var blob_storage_backups={"backup1" = { "backup_name" = "myblob", "retention_period" = "P7D", "backup_intervals" = ["R/2024-01-01T00:00:00+00:00/P1D"], "storage_account_id" = "id" }}
terraform apply -var-file="<your-var-file>.tfvars
-
Apply Terraform
Apply the Terraform code to create the infrastructure.
The
-auto-approve
flag is used to automatically approve the plan, you can remove this flag to review the plan before applying.terraform apply -auto-approve
Now review the deployed infrastructure in the Azure portal. You will find the resources deployed to a resource group called
rg-nhsbackup-myvault
(unless you specified a different vault name in the tfvars).Should you want to, you can remove the infrastructure with the following command:
terraform destroy -auto-approve
The test suite consists of a number Terraform HCL integration tests that use a mock azurerm provider.
See this link for more information.
TIP! Consider adopting the classic red-green-refactor approach using the integration test framework when adding or modifying the terraform code.
Take the following steps to run the test suite:
-
Initialise Terraform
Change the working directory to
./tests/integration-tests
.Terraform can now be initialised by running the following command:
terraform init -backend=false
NOTE: There's no need to initialise a backend for the purposes of running the tests.
-
Run the tests
Run the tests with the following command:
terraform test
The end to end tests are written in go, and use the terratest library and the Azure SDK for Go.
The tests depend on a connection to Azure so it can create an environment that the tests can be executed against - the environment is torn down once the test run has completed.
See the following resources for docs and examples of terratest and the Azure SDK:
- Terratest docs
- Terratest repository
- Terratest test examples
- Azure SDK
- Azure SDK Data Protection Module
To run the tests, take the following steps:
-
Install go packages
You only need to do this once when setting up your environment.
Change the working directory to
./tests/end-to-end-tests
.Run the following command:
go mod tidy
-
Setup environment variables
The end-to-end test suite needs to login to Azure in order to execute the tests and therefore the following environment variables must be set.
$env:ARM_TENANT_ID="<your-tenant-id>" $env:ARM_SUBSCRIPTION_ID="<your-subscription-id>" $env:ARM_CLIENT_ID="<your-client-id>" $env:ARM_CLIENT_SECRET="<your-client-secret>" $env:TF_STATE_RESOURCE_GROUP="rg-nhsbackup" $env:TF_STATE_STORAGE_ACCOUNT="<storage-account-name>" $env:TF_STATE_STORAGE_CONTAINER="tfstate"
For the storage account name, the TF state backend should have been created during the getting started guide, at which point the storage account will have been created and the name generated.
-
Run the tests
Run the tests with the following command:
go test -v -timeout 10m
To debug the tests in vscode, add the following configuration to launch settings and run the configuration:
{
"configurations": [
{
"name": "Go Test",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}/tests/end-to-end-tests",
"env": {
"ARM_TENANT_ID": "<your-tenant-id>",
"ARM_SUBSCRIPTION_ID": "<your-subscription-id>",
"ARM_CLIENT_ID": "<your-client-id>",
"ARM_CLIENT_SECRET": "<your-client-secret>",
"TF_STATE_RESOURCE_GROUP": "rg-nhsbackup",
"TF_STATE_STORAGE_ACCOUNT": "<storage-account-name>",
"TF_STATE_STORAGE_CONTAINER": "tfstate"
}
}
]
}
For the storage account name, the TF state backend should have been created during the getting started guide, at which point the storage account will have been created and the name generated.
The CI pipeline workflow uses the Semantic Release GitHub action to create semantic version number (e.g. 1.0.0 / major.minor.patch), add a tag to the repository, and publish a release to GitHub. See the ./releaserc
file at the repo root to view the configuration that has been applied.
Semantic Release relies on commit message conventions, therefore any merge into main
should squash merged with a commit message that adheres to the semantic release formatting rules.
When a PR is merged into main
, if no commit messages are found that meet the convention then the patch number is incremented by default.
Here are some example commit messages which will result in a version increment:
Commit Message | Type | Example |
---|---|---|
fix: Fixed a bug. | Patch | 1.1.10 -> 1.1.11 |
feat: Added a feature. | Minor | 1.1.10 -> 1.2.0 |
feat: Changed a feature. BREAKING CHANGE: This change breaks things. |
Major | 1.1.10 -> 2.0.0 |