Infrastructure-as-code

The configuration of the infrastructure (often cloud-based infrastructure) of the IT system nowadays is often defined using machine-readable code (so-called infrastructure-as-code). This results in a more efficient provisioning of environments and reduces the human error and replication of faults, which ultimately leads to fewer anomalies caused by testing errors.  

When using a proper infrastructure-as-code (see example below) solution you will effectively determine the quality of the IT system including the infrastructure. The test set should be executed in an environment which has similar behavior and characteristics as the live system. It is important to have behavior such as permissions, access rights and integration with 3rd party interfaces in place.  

Infrastructure-as-code (IaC) is the process of managing and provisioning computer environments through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools (based on [Wittig 2016]).

Infrastructure-as-code (IaC) is an approach whereby an infrastructure configuration is scripted or described by files stored in version control, and changes are pushed out to the data center in a controlled manner. This parallels the discipline of source control and builds promotion used in software development, hence ‘as code’. 

A test environment is a composition of parts, such as hardware and software, connections, environment data, tools, and operational processes in which a test is carried out. 

In DevOps, people do not need to provision entire environments as they can use service virtualization tools to virtualize parts of the environment that are either unavailable for testing, are still in development, or are third-party services. With automation, complete, ephemeral environments can be created on demand and decommissioned when testing is complete, reducing both the time as well as the cost associated with maintaining environments. Cloud technology or containerization can help with this. And the adoption of virtual environments is a logical step for automating the delivery pipeline.  

infrastruction definition

Example of infrastructure definition as code. 

A popular open-source tool for infrastructure automation is HashiCorp - Terraform. It uses a DSL (Domain Specific Language) to script the desired infrastructure. This approach provides consistent and repeatable environment changes, reducing manual effort, especially in troubleshooting environmental differences. 

Applying IaC will eliminate several problems. E.g.: 

  • Labor intensive; building and configuring a complete infrastructure for an IT system traditionally is a time-consuming activity
  • Error prone; manual building of the infrastructure for an IT system, following a checklist or not, is an error-prone process
  • Hard to rebuild infrastructure exactly for other environments, like another test or acceptance environment
  • Difference between design and reality; all above mentioned possible problems result in a difference between the designed and approved infrastructure architecture and the implemented infrastructure.

Using IaC, many problems can be converted into advantages: 

  • Modularization; the DRY principle (Don’t Repeat Yourself) applies also for IaC similar as applications code. Split the complete infrastructure into small reusable pieces of code.
  • Maintainability and versioning
  • Testability; See infrastructure verification
  • Automation
  • Repeatability; Similar infrastructures can be deployed over and over again
  • Security, compliance and policies
  • Collaboration and code review

The extra advantage of tools like Terraform is that it is agnostic for the target cloud platform. A single tool and domain specific language can be used for a variety of cloud providers. 

Example of a Hashicorp - Terraform code snippet: Creation of AWS server instance and AWS database instance. 

// Creation of an Amazon Web Services (AWS) server instance and an AWS database instance.
// This example doesn’t use variables.
// Declare AWS instance
resource "aws_instance" "web" {
  ami = "${data.aws_ami.ubuntu.id}"
>   instance_type = "t2.micro"
  tags = {
    Name = "testland-webserver"
  }
}
// Declare data block which is used during creation of AWS instance
data "aws_ami" "ubuntu" {&
  most_recent = true
  filter {
    name = "name"
    values = ["ubuntu/images/ubuntu-trusty-14.04-amd64-server-*"] 

  }
  owners = ["0123456789"]

 

// Declare AWS database

resource "aws_db_instance" "default" {
  allocated_storage = "20"
  storage_type = "gp2"
  engine = "postgres"
  engine_version = "12.3"
  instance_class = "t2.micro"
  name = "postgres"
  username = "postgres"
  password = "postgres"
  final_snapshot_identifier = "postgres"

 

For more information please also read the building block “Infrastructure verification”. 

Additionally

When performing integration tests the team may not be able to connect to all relevant systems. Service virtualization is a good option to replace systems that are not available. For more information see "Test automation". Apart from service virtualization there are other ways to simulate the integration with other (sub-)systems, for example by using self-developed stubs, drivers or mocks.