Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terraform Tests #4

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .github/workflows/ci-pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ jobs:
- name: Install Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.0
terraform_version: 1.9.3

- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Terraform Init
run: terraform init -backend=false
Expand All @@ -34,6 +39,15 @@ jobs:
run: terraform validate
working-directory: infrastructure

- name: Terraform Init (Tests)
run: terraform init -backend=false
working-directory: tests

- name: Terraform Test
run: terraform test
working-directory: tests
#working-directory: infrastructure

static-code-analysis:
name: Static Code Analysis
runs-on: ubuntu-latest
Expand All @@ -45,7 +59,7 @@ jobs:
- name: Install Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.0
terraform_version: 1.9.3

- name: Run Terraform Format
run: terraform fmt -check
Expand Down
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ The following diagram illustrates the high level architecture

The repository consists of the following directories:

* `./.github`

Contains the GitHub workflows in `yaml` format.

[See the YAML schema documentation for more details.](https://learn.microsoft.com/en-us/azure/devops/pipelines/yaml-schema/?view=azure-pipelines)

* `./.pipelines`

Contains the Azure Pipelines in `yaml` format.
Expand Down Expand Up @@ -167,6 +173,46 @@ Take the following steps to get started in configuring and verify the infrastruc

The repo contains an `example` module which can be utilised to further extend the sample infrastructure with some resources and backup instances. To use this module for dev/test purposes, include the module in `main.tf` and run `terraform apply` again.

### Running the Tests

The test suite consists of a number Terraform HCL tests.

[See this link for more information.](https://developer.hashicorp.com/terraform/language/tests)

Take the following steps to run the test suite:

1. Login to Azure

Use the Azure CLI to login to Azure by running the following command:

```pwsh
az login
```

> NOTE: You can skip this step if you've already logged in (e.g. by following the steps above in the [Getting Started](#getting-started) guide).

2. Initialise Terraform

Change the working directory to `./tests`.

Terraform can now be initialised by running the following command:

````pwsh
terraform init -backend=false
````

> NOTE: There's no need to initialise a backend for the purposes of running the tests).

3. Run the Tests

Run the tests with the following command:

````pwsh
terraform test
````

> NOTE: There's no need to initialise a backend for the purposes of running the tests).

### Contributing

If you want to contribute to the project, raise a PR on GitHub.
Expand Down
16 changes: 16 additions & 0 deletions infrastructure/backup_policy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module "blob_storage_policy" {
source = "./modules/backup_policy/blob_storage"
policy_name = "bkpol-${var.vault_name}-blobstorage"
vault_id = azurerm_data_protection_backup_vault.backup_vault.id
retention_period = "P7D" # 7 days
# NOTE - this blob policy has been configured for operational backup
# only, which continuously backs up data and does not need a schedule
}

module "managed_disk_policy" {
source = "./modules/backup_policy/managed_disk"
policy_name = "bkpol-${var.vault_name}-manageddisk"
vault_id = azurerm_data_protection_backup_vault.backup_vault.id
retention_period = "P7D" # 7 days
backup_intervals = ["R/2024-01-01T00:00:00+00:00/P1D"] # Once per day at 00:00
}
11 changes: 11 additions & 0 deletions infrastructure/backup_vault.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
resource "azurerm_data_protection_backup_vault" "backup_vault" {
name = "bvault-${var.vault_name}"
resource_group_name = azurerm_resource_group.resource_group.name
location = var.vault_location
datastore_type = "VaultStore"
redundancy = var.vault_redundancy
soft_delete = "Off"
identity {
type = "SystemAssigned"
}
}
41 changes: 0 additions & 41 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,4 @@ terraform {

provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "resource_group" {
location = var.vault_location
name = "rg-nhsbackup-${var.vault_name}"
}

# Create the vault
###########################################################################

resource "azurerm_data_protection_backup_vault" "backup_vault" {
name = "bvault-${var.vault_name}"
resource_group_name = azurerm_resource_group.resource_group.name
location = var.vault_location
datastore_type = "VaultStore"
redundancy = var.vault_redundancy
soft_delete = "Off"
identity {
type = "SystemAssigned"
}
}


# Create some backup policies
###########################################################################

module "blob_storage_policy" {
source = "./modules/backup_policy/blob_storage"
policy_name = "bkpol-${var.vault_name}-blobstorage"
vault_id = azurerm_data_protection_backup_vault.backup_vault.id
retention_period = "P7D" # 7 days
# NOTE - this blob policy has been configured for operational backup
# only, which continuously backs up data and does not need a schedule
}

module "managed_disk_policy" {
source = "./modules/backup_policy/managed_disk"
policy_name = "bkpol-${var.vault_name}-manageddisk"
vault_id = azurerm_data_protection_backup_vault.backup_vault.id
retention_period = "P7D" # 7 days
backup_intervals = ["R/2024-01-01T00:00:00+00:00/P1D"] # Once per day at 00:00
}
12 changes: 12 additions & 0 deletions infrastructure/modules/backup_policy/blob_storage/output.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
output "id" {
value = azurerm_data_protection_backup_policy_blob_storage.backup_policy.id
}

output "name" {
value = azurerm_data_protection_backup_policy_blob_storage.backup_policy.name
}

output "vault_id" {
value = azurerm_data_protection_backup_policy_blob_storage.backup_policy.vault_id
}

output "retention_period" {
value = azurerm_data_protection_backup_policy_blob_storage.backup_policy.operational_default_retention_duration
}
16 changes: 16 additions & 0 deletions infrastructure/modules/backup_policy/managed_disk/output.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
output "id" {
value = azurerm_data_protection_backup_policy_disk.backup_policy.id
}

output "name" {
value = azurerm_data_protection_backup_policy_disk.backup_policy.name
}

output "vault_id" {
value = azurerm_data_protection_backup_policy_disk.backup_policy.vault_id
}

output "retention_period" {
value = azurerm_data_protection_backup_policy_disk.backup_policy.default_retention_duration
}

output "backup_intervals" {
value = azurerm_data_protection_backup_policy_disk.backup_policy.backup_repeating_time_intervals
}
4 changes: 4 additions & 0 deletions infrastructure/resource_group.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "azurerm_resource_group" "resource_group" {
location = var.vault_location
name = "rg-nhsbackup-${var.vault_name}"
}
77 changes: 77 additions & 0 deletions tests/backup_policy.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
run "create_blob_storage_policy" {
command = apply

module {
source = "../infrastructure"
}

variables {
vault_name = "testvault"
}

# Check that the id is as expected
assert {
condition = length(module.blob_storage_policy.id) > 0
error_message = "Blob storage policy id not as expected."
}

# Check that the name is as expected
assert {
condition = module.blob_storage_policy.name == "bkpol-${var.vault_name}-blobstorage"
error_message = "Blob storage policy name not as expected."
}

# Check that the vault id is as expected
assert {
condition = module.blob_storage_policy.vault_id == azurerm_data_protection_backup_vault.backup_vault.id
error_message = "Blob storage policy vault id not as expected."
}

# Check that the retention period is as expected
assert {
condition = module.blob_storage_policy.retention_period == "P7D"
error_message = "Blob storage policy retention period not as expected."
}
}

run "create_managed_disk_policy" {
command = apply

module {
source = "../infrastructure"
}

variables {
vault_name = "testvault"
}

# Check that the id is as expected
assert {
condition = length(module.managed_disk_policy.id) > 0
error_message = "Managed disk policy id not as expected."
}

# Check that the name is as expected
assert {
condition = module.managed_disk_policy.name == "bkpol-${var.vault_name}-manageddisk"
error_message = "Managed disk policy name not as expected."
}

# Check that the vault id is as expected
assert {
condition = module.managed_disk_policy.vault_id == azurerm_data_protection_backup_vault.backup_vault.id
error_message = "Managed disk policy vault id not as expected."
}

# Check that the retention period is as expected
assert {
condition = module.managed_disk_policy.retention_period == "P7D"
error_message = "Managed disk policy retention period not as expected."
}

# Check that the backup intervals is as expected
assert {
condition = can(module.managed_disk_policy.backup_intervals) && length(module.managed_disk_policy.backup_intervals) == 1 && module.managed_disk_policy.backup_intervals[0] == "R/2024-01-01T00:00:00+00:00/P1D"
error_message = "Managed disk policy backup intervals not as expected."
}
}
55 changes: 55 additions & 0 deletions tests/backup_vault.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
run "create_backup_vault" {
command = apply

module {
source = "../infrastructure"
}

variables {
vault_name = "testvault"
vault_location = "uksouth"
vault_redundancy = "LocallyRedundant"
}

# Check that the name is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.name == "bvault-${var.vault_name}"
error_message = "Backup vault name not as expected."
}

# Check that the resource group is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.resource_group_name == azurerm_resource_group.resource_group.name
error_message = "Resource group not as expected."
}

# Check that the location is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.location == var.vault_location
error_message = "Backup vault location not as expected."
}

# Check that the datastore type is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.datastore_type == "VaultStore"
error_message = "Backup vault datastore type not as expected."
}

# Check that the redundancy is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.redundancy == var.vault_redundancy
error_message = "Backup vault redundancy not as expected."
}

# Check that soft delete is as expected
assert {
condition = azurerm_data_protection_backup_vault.backup_vault.soft_delete == "Off"
error_message = "Backup vault soft delete not as expected."
}

# Check that identity is as expected
assert {
condition = length(azurerm_data_protection_backup_vault.backup_vault.identity[0].principal_id) > 0
error_message = "Backup vault identity not as expected."
}
}
12 changes: 12 additions & 0 deletions tests/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.114.0"
}
}
}

provider "azurerm" {
features {}
}
24 changes: 24 additions & 0 deletions tests/resource_group.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
run "create_resource_group" {
command = plan

module {
source = "../infrastructure"
}

variables {
vault_name = "testvault"
vault_location = "uksouth"
}

# Check that the name is as expected
assert {
condition = azurerm_resource_group.resource_group.name == "rg-nhsbackup-${var.vault_name}"
error_message = "Resource group name not as expected."
}

# Check that the location is as expected
assert {
condition = azurerm_resource_group.resource_group.location == var.vault_location
error_message = "Resource group location not as expected."
}
}
Loading