Infrastructure as code is not programming, it’s only configuration.
— as a software developer
With the big cloud migration wave, there are a lot of cloud provision and configuration effort. There is a modern name called “ Infrastructure as code “. But after AWS released in the market over 1 decade, it is still in earlier stage from a software engineer point view.
The biggest market winner is https://www.terraform.io/, which it can deliver infrastructure easily. But it was same year in 2014, AWS released boto3 API, https://pypi.org/project/boto3/0.0.1/ which can also provision all AWS service in python code easily, link here
import boto3
client = boto3.resource('s3')
response = client.create_bucket(
Bucket='examplebucket',
CreateBucketConfiguration={
'LocationConstraint': 'eu-west-1',
},
)
print(response)
How is the definition of simplicity from Terraform point view? I have different options. Is boto3 complicated?
The main disadvantage for Terraform is the DSL language can’t test easily with Unit Test, Mock Service, Integration Test, E2E test like other modern language Python, Java. Many Infra Engineers or Architects are always challenging me, WHY need test? —– It’s like a joke.
However, there are some innovative solution is coming,
- AWS CDK https://aws.amazon.com/cdk/
- Plumi https://www.pulumi.com/
- Terraform https://www.terraform.io/cdktf
Which is providing modern programming productivity to make infrastructure as real code with quality.
import pulumi
from pulumi_aws import s3
# Create an AWS resource (S3 Bucket)
bucket = s3.Bucket('my-bucket')
# Export the name of the bucket
pulumi.export('bucket_name', bucket.id)
As today, there are maybe many existing legacies Terraform code or module in your organization which you can’t drop directly. I made a hand-on dirty to find a testable solution to maintain TF code. And today SonarQube support TF code check for AWS.
1. Overview of Test Cost

2. Unit Test in Terraform
It is not really unit test, it is more grammar check and plan explanation.
terraform fmt -check
tflint
terraform validate
terraform plan
3. Integration Test Terraform
In terraform, you can apply to deploy your code at Integration Test Directly.
terraform apply
terraform destory [don't forget release code]
But you can also use advanced IT test framework such as Terratest4 or kitchen-terraform5. It’s a provision PostgreSQL test example.
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: tfFilePath,
Vars: map[string]interface{}{
"postfix": uniquePostfix,
"db_user": expectedUser,
"db_password": expectedPassword,
},
NoColor: false,
})
subscriptionID := "xxx"
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
expectedServername := "postgresqlserver-" + uniquePostfix // see fixture
actualServername := terraform.Output(t, terraformOptions, "servername")
rgName := terraform.Output(t, terraformOptions, "rgname")
expectedSkuName := terraform.Output(t, terraformOptions, "sku_name")
actualServer := azure.GetPostgreSQLServer(t, rgName, actualServername, subscriptionID)
actualServerAddress := *actualServer.ServerProperties.FullyQualifiedDomainName
actualServerUser := *actualServer.ServerProperties.AdministratorLogin
// Expectation
assert.NotNil(t, actualServer)
assert.Equal(t, expectedUser, actualServerUser)
assert.Equal(t, expectedServername, actualServername)
assert.Equal(t, expectedSkuName, *actualServer.Sku.Name)
In go libraries, you can use SQL to make end2end test like this,
func ConnectDB(t *testing.T, userName string, expectedPassword string, databaseAddress string, actualServername string) {
var connectionString string = fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=require", databaseAddress, userName+"@"+actualServername, expectedPassword, "postgres")
print(connectionString)
db, err := sql.Open("postgres", connectionString)
assert.Nil(t, err, "open db failed")
err = db.Ping()
assert.Nil(t, err, "connect db failed")
fmt.Println("Successfully created connection to database")
var currentTime string
err = db.QueryRow("select now()").Scan(¤tTime)
assert.Nil(t, err, "query failed ")
assert.NotEmpty(t, currentTime, "Get Query Time "+currentTime)
github code is here https://github.com/wuqunfei/tfmodule-azure-resource-postgresql/blob/main/test/mod_test.go#L56
4. Policy Test in Terraform
IT Compliance and Security become into code in these years when you provision your infrastructure. Azure has an example blog https://learn.microsoft.com/en-us/azure/developer/terraform/best-practices-compliance-testing
terraform show -json main.tfplan > main.tfplan.json
docker run --rm -v $PWD:/target -it eerkunt/terraform-compliance -f features -p main.tfplan.json
# https://github.com/terraform-compliance/cli a lightweight, security focused, BDD test framework against terraform.

5. Terraform Code Quality Check
Since last year, SonarQube supports Terraform Grammar and Security Check. It helps us reduce a lot manually setup and check.

For example, this code has Omitting “public_network_access_enabled” allows network access from the Internet. Make sure it is safe here.
# public_network_access_enabled = true
# default is true, need to set false
public_network_access_enabled = false
Which developer can’t find it easily because public network access as default.
6. Making Terraform code callable

1. Shell spaghetti easily: Using some shell and scripts or github ci/cd or jenkins, the provision can work automation quickly and easily.
2. Integrating with automation tools : we can also use Ansible TF-module and define a play book to run automatically. Ansible TF model link Ansible Towner can explore their API easily to automation tools.
3. Crossplane Open API definition
It is a new design architecture from Crossplane which had considered each component can be callable by Open API definition.
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
Original code is here https://github.com/crossplane/crossplane/blob/master/docs/getting-started/create-configuration.md
Summary
To write infrastructure code goes straightforward, but the foundation of high-quality software mindset which is still missing in many cloud engineering daily job. In this blog, I summarized the existing marketing options, it may help someone like to improve their automation and quality in their infrastructure daily work.

Leave a comment