Skip to content

Commit 3328af0

Browse files
authored
Add Sample: Integration Testing (microsoft#43)
add samples for integration testing
1 parent 7d4ee2d commit 3328af0

14 files changed

+211
-0
lines changed

samples/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Azure Terraform Samples
2+
3+
This repository contains real-world examples that will walk you through different concepts and help you to implements all of them on your projects.
4+
5+
## Testing Best Practices
6+
7+
- [Integration Testing](integration-testing/README.md)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Terraform Integration Testing
2+
3+
This is an example about the minimum level of integration testing that we recommend to be implemented on every Terraform project.
4+
5+
## What about integration testing
6+
7+
Testing is an important part of a software development project, and this is also for infrastructure as code projects. When working with Terraform, there are a bunch of tools that can help you to set up continuous integration quickly. Making sure that every time you and your colleagues are pushing changes, this code is automatically validated and tested.
8+
9+
This example shows how you can use Azure Pipeline to quickly set up a CI pipeline on a Terraform module. This pipeline is responsible for:
10+
11+
- Running static code analysis using [checkov](https://github.com/bridgecrewio/checkov)
12+
- Running Terraform init
13+
- Running Terraform validate
14+
- Running Terraform plan
15+
16+
By running these steps, you will ensure that on every commit, the code that is pushed integrates with the existing code base and is valid from a syntax perspective as it can be executed by Terraform.
17+
18+
## Getting deep dive into this example
19+
20+
This example basically creates a resource group with a random name (see [main.tf](src/main.tf)):
21+
22+
```hcl
23+
resource "random_uuid" "uuid" {}
24+
25+
resource "azurerm_resource_group" "rg" {
26+
name = "rg-hello-tf-${random_uuid.uuid.result}"
27+
location = var.location
28+
}
29+
```
30+
31+
It also defines a [bash script](src/checkov.sh) responsible for running the static code analysis using Checkov tool.
32+
33+
Finally, it defines an [Azure YAML pipeline](src/azure-pipeline.yaml) responsible for executing the 4 steps described in the [above section](#what-about-basic-testing).
34+
35+
## How-to run this example
36+
37+
### Prerequisites
38+
39+
To run this example, you need to:
40+
41+
- Create a new Azure DevOps project. If you are not familiar with Azure DevOps, you can create an organization and your first project for free following [this documentation](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/create-project?view=azure-devops&tabs=preview-page).
42+
- Install the [Terraform Build & Release Tasks extension](https://marketplace.visualstudio.com/items?itemName=charleszipp.azure-pipelines-tasks-terraform) into your Azure DevOps organization
43+
- Create an [Azure Service Connection](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops) named `terraform-basic-testing-azure-connection` allowing Azure Pipelines to connect to your Azure subscriptions (required to execute the terraform plan step)
44+
- Fork this repository into your own GitHub organization
45+
46+
### Import the pipeline into Azure DevOps
47+
48+
Open your Azure DevOps project and go into the Azure Pipelines section. Click on the `Create Pipeline` button. On the `Where is your code?` select GitHub (YAML):
49+
50+
![Where is your code?](assets/new-pipeline-where-github-yaml.png)
51+
52+
> Note: At this step, you might have to authorize Azure DevOps to access your organization, if you've not done that already. If you are not familiar with building GitHub repositories using Azure Pipelines you can have a look to [this documenation page](https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/github?view=azure-devops&tabs=yaml).
53+
54+
In the repositories list, select the fork of this repository that you have created previously in your GitHub organization. In the `Configure your pipeline` step, choose to start from an existing YAML pipeline:
55+
56+
![Existing YAML pipeline](assets/new-pipeline-existing-yaml.png)
57+
58+
In the popup that opens, fill with the branch `master` and the path to the YAML pipeline `examples/basic-testing/src/azure-pipeline.yaml`:
59+
60+
![Select existing YAML pipeline](assets/select-existing-yaml-pipeline.png)
61+
62+
Click on the `Continue` button. This will load the Azure YAML pipeline from GitHub. On the next page, you can click the `Run` button to create and manually trigger the pipeline for the first time:
63+
64+
![Run Azure Pipeline](assets/run-pipeline.png)
65+
66+
### Run the pipeline
67+
68+
You can run the pipeline manually from the Azure DevOps UI or just commit new code to `example/basic-testing/src` folder of the repository. It will automatically trigger a new pipeline on the branch you are pushing the code:
69+
70+
![Pipeline running from GitHub](assets/pipeline-running-from-github.png)
71+
72+
And of course, you can access the details to ensure that everything ends up green in Azure DevOps:
73+
74+
![Azure DevOps Green Pipeline](assets/azure-devops-green-pipeline.png)
257 KB
Loading
54.7 KB
Loading
105 KB
Loading
75.3 KB
Loading
102 KB
Loading
33.3 KB
Loading
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Azure Pipeline that run basic continuous integration on a Terraform project
2+
3+
# This makes sure the pipeline is triggered every time code is pushed in the validation-testing example source, on all branches.
4+
trigger:
5+
branches:
6+
include:
7+
- '*'
8+
paths:
9+
include:
10+
- 'examples/validation-testing/src/*'
11+
12+
variables:
13+
# There must be an Azure Service Connection with that name defined in your Azure DevOps settings. See https://docs.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops
14+
serviceConnection: 'terraform-basic-testing-azure-connection'
15+
azureLocation: 'westeurope'
16+
# Terraform settings
17+
terraformWorkingDirectory: '$(System.DefaultWorkingDirectory)/examples/basic-testing/src'
18+
terraformVersion: '0.12.25'
19+
20+
stages:
21+
- stage: TerraformContinuousIntegration
22+
displayName: Terraform Module - CI
23+
jobs:
24+
- job: TerraformContinuousIntegrationJob
25+
displayName: TerraformContinuousIntegration - CI Job
26+
pool:
27+
vmImage: ubuntu-20.04
28+
steps:
29+
# Step 1: run the Checkov Static Code Analysis
30+
- bash: $(terraformWorkingDirectory)/checkov.sh $(terraformWorkingDirectory)
31+
displayName: Checkov Static Code Analysis
32+
# Step 2: install Terraform on the Azure Pipelines agent
33+
- task: charleszipp.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-installer.TerraformInstaller@0
34+
displayName: 'Install Terraform'
35+
inputs:
36+
terraformVersion: $(terraformVersion)
37+
# Step 3: run Terraform init to initialize the workspace
38+
- task: charleszipp.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-cli.TerraformCLI@0
39+
displayName: 'Run terraform init'
40+
inputs:
41+
command: init
42+
workingDirectory: $(terraformWorkingDirectory)
43+
# Step 4: run Terraform validate to validate HCL syntax
44+
- task: charleszipp.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-cli.TerraformCLI@0
45+
displayName: 'Run terraform validate'
46+
inputs:
47+
command: validate
48+
workingDirectory: $(terraformWorkingDirectory)
49+
# Step 5: run Terraform plan to validate HCL syntax
50+
- task: charleszipp.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-cli.TerraformCLI@0
51+
displayName: 'Run terraform plan'
52+
inputs:
53+
command: plan
54+
workingDirectory: $(terraformWorkingDirectory)
55+
environmentServiceName: $(serviceConnection)
56+
commandOptions: -var location=$(azureLocation)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
#title :run_checkov.sh
3+
#description :Runs the Checkov static analysis tool on all subdirectories of the target.
4+
#author :andreas.heuamier@microsoft.com
5+
#date :20200510
6+
#version :0.1
7+
#usage :./checkov.sh {WORKk_DIR}
8+
#bash_version :5.0.16(1)-release
9+
#
10+
set -eo pipefail
11+
12+
# The target directory for scanning.
13+
WORK_DIR=${1-$(pwd)}
14+
15+
#######################################
16+
# run_checkov() docker command
17+
# Arguments:
18+
# test_dir folder
19+
# Outputs:
20+
# Writes test command outputs to stdout
21+
# Exits on $? != 0
22+
#######################################
23+
run_checkov() {
24+
local test_dir=$1
25+
docker run -t -v "${test_dir}":/tf bridgecrew/checkov:release-1.0.235 -d /tf
26+
}
27+
28+
#######################################
29+
# find_folders_by() file pattern
30+
# Globals:
31+
# WORK_DIR -path
32+
# Arguments:
33+
# pattern - regex
34+
# Outputs:
35+
# Writes folders list to stdout
36+
#######################################
37+
find_folders_by() {
38+
local pattern=${1:-"main.tf"}
39+
find "${WORK_DIR}" -type f -name "${pattern}" -printf '%h\n' | sort -u
40+
}
41+
42+
#######################################
43+
# Runs the Checkov static analysis tool on all subdirectories
44+
#######################################
45+
run_main() {
46+
for folder in $(find_folders_by "main.tf"); do
47+
run_checkov "${folder}" &
48+
done
49+
wait
50+
}
51+
52+
#######################################
53+
# Be able to run this one either as standalone or import as lib
54+
#######################################
55+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
56+
run_main
57+
fi

0 commit comments

Comments
 (0)