From ddf6f468d5ff7c76a98ec4eff84d48a4b8bbefd6 Mon Sep 17 00:00:00 2001 From: Nitin Mishra Date: Fri, 23 Dec 2022 16:10:27 +0530 Subject: [PATCH] add new tests for IaC codebase --- .../Automated-test-with-Terratest/README.md | 23 +++++++++++++ .../examples/instance.tf | 12 +++++++ .../examples/output.tf | 4 +++ .../examples/provider.tf | 6 ++++ .../examples/securitygroup.tf | 9 +++++ .../examples/terraform.tfvars | 3 ++ .../examples/vars.tf | 17 ++++++++++ .../examples/versions.tf | 3 ++ .../test/terraform_test.go | 34 +++++++++++++++++++ 2022/Days/IaC/Terratest/examples/instance.tf | 12 +++++++ 2022/Days/IaC/Terratest/examples/output.tf | 4 +++ 2022/Days/IaC/Terratest/examples/provider.tf | 5 +++ .../IaC/Terratest/examples/securitygroup.tf | 9 +++++ .../IaC/Terratest/examples/terraform.tfvars | 3 ++ 2022/Days/IaC/Terratest/examples/vars.tf | 16 +++++++++ 2022/Days/IaC/Terratest/examples/versions.tf | 3 ++ .../Days/IaC/Terratest/test/terraform_test.go | 34 +++++++++++++++++++ 2022/Days/day62.md | 25 +++++++++++++- 18 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/README.md create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/instance.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/output.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/provider.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/securitygroup.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/terraform.tfvars create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/vars.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/examples/versions.tf create mode 100644 2022/Days/IaC/Automated-test-with-Terratest/test/terraform_test.go create mode 100644 2022/Days/IaC/Terratest/examples/instance.tf create mode 100644 2022/Days/IaC/Terratest/examples/output.tf create mode 100644 2022/Days/IaC/Terratest/examples/provider.tf create mode 100644 2022/Days/IaC/Terratest/examples/securitygroup.tf create mode 100644 2022/Days/IaC/Terratest/examples/terraform.tfvars create mode 100644 2022/Days/IaC/Terratest/examples/vars.tf create mode 100644 2022/Days/IaC/Terratest/examples/versions.tf create mode 100644 2022/Days/IaC/Terratest/test/terraform_test.go diff --git a/2022/Days/IaC/Automated-test-with-Terratest/README.md b/2022/Days/IaC/Automated-test-with-Terratest/README.md new file mode 100644 index 0000000..be86e19 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/README.md @@ -0,0 +1,23 @@ +# Terratest +Terratest is a Go library developed at Gruntwork, that makes it easier to write automated tests for our infrastructure code. It provides a variety of helper functions and patterns for common infrastructure testing tasks but here we will be discussing about Testing Terraform code. + +# To Run this application +* git clone https://github.com/imnitin28/terra-form-test-techhub.git
+* cd test
+* go mod init ""
+ **MODULE_NAME would be github.com//**
+* go mod init github.com/
+* go run + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +go mod init "" would create go.mod file into test folder.
+* The go.mod file is the root of dependency management in GoLang. +* All the modules which are needed or to be used in the project are maintained here in go.mod file. +* It creates entry for all the packages we are going to use/import in our project. +* It reduces effort for getting each dependencies manually. + +On running **go test** for the first time you would get go.sum file created. +* go.sum file is created when **go test** or **go build** is executed for the first time. +* It installs all the packages with specific version(latest) +* we do not need to edit or modify this file. diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/instance.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/instance.tf new file mode 100644 index 0000000..5a9db2d --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/instance.tf @@ -0,0 +1,12 @@ +resource "aws_instance" "example" { + ami = var.AMIS[var.AWS_REGION] + instance_type = "t2.micro" + vpc_security_group_ids = [aws_security_group.instance.id] + + # When the instance boots, start a web server on port 8080 that responds with "Hello, World!". + user_data = < index.html +nohup busybox httpd -f -p 8080 & +EOF +} \ No newline at end of file diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/output.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/output.tf new file mode 100644 index 0000000..752bb05 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/output.tf @@ -0,0 +1,4 @@ +# Output the instance's public IP address. +output "public_ip" { + value = aws_instance.example.public_ip +} \ No newline at end of file diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/provider.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/provider.tf new file mode 100644 index 0000000..696b517 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/provider.tf @@ -0,0 +1,6 @@ +provider "aws" { + access_key = var.AWS_ACCESS_KEY + secret_key = var.AWS_SECRET_KEY + region = var.AWS_REGION +} + diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/securitygroup.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/securitygroup.tf new file mode 100644 index 0000000..d562dee --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/securitygroup.tf @@ -0,0 +1,9 @@ +# Allow the instance to receive requests on port 8080. +resource "aws_security_group" "instance" { + ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} \ No newline at end of file diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/terraform.tfvars b/2022/Days/IaC/Automated-test-with-Terratest/examples/terraform.tfvars new file mode 100644 index 0000000..dcc3f3b --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/terraform.tfvars @@ -0,0 +1,3 @@ +AWS_ACCESS_KEY = "XXXX" +AWS_SECRET_KEY = "XXXXXXXX" +AWS_REGION="ap-south-1" diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/vars.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/vars.tf new file mode 100644 index 0000000..9316302 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/vars.tf @@ -0,0 +1,17 @@ +variable "AWS_ACCESS_KEY" { +} + +variable "AWS_SECRET_KEY" { +} + +variable "AWS_REGION" { + default = "ap-south-1" +} + +variable "AMIS" { + type = map(string) + default = { + ap-south-1 = "ami-0860c9429baba6ad2" + } +} + diff --git a/2022/Days/IaC/Automated-test-with-Terratest/examples/versions.tf b/2022/Days/IaC/Automated-test-with-Terratest/examples/versions.tf new file mode 100644 index 0000000..0ac1e24 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/examples/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.12.26" +} \ No newline at end of file diff --git a/2022/Days/IaC/Automated-test-with-Terratest/test/terraform_test.go b/2022/Days/IaC/Automated-test-with-Terratest/test/terraform_test.go new file mode 100644 index 0000000..93dc842 --- /dev/null +++ b/2022/Days/IaC/Automated-test-with-Terratest/test/terraform_test.go @@ -0,0 +1,34 @@ +package test + +import ( + "fmt" + "testing" + "time" + + http_helper "github.com/gruntwork-io/terratest/modules/http-helper" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestTerraformAwsHelloWorldExample(t *testing.T) { + t.Parallel() + + /*Construct the terraform options with default retryable errors to handle the most common retryable errors in terraform testing. */ + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + /* The path to where our Terraform code is located */ + TerraformDir: "../examples", + }) + + /* At the end of the test, run `terraform destroy` to clean up any resources that were created.*/ + defer terraform.Destroy(t, terraformOptions) + + /* Run `terraform init` and `terraform apply`. Fail the test if there are any errors. */ + terraform.InitAndApply(t, terraformOptions) + + /* Run `terraform output` to get the IP of the instance */ + publicIp := terraform.Output(t, terraformOptions, "public_ip") + + /* Make an HTTP request to the instance and make sure we get back a 200 OK with the body "Hello, World!" */ + url := fmt.Sprintf("http://%s:8080", publicIp) + http_helper.HttpGetWithRetry(t, url, nil, 200, "Hello, World!", 30, 5*time.Second) +} diff --git a/2022/Days/IaC/Terratest/examples/instance.tf b/2022/Days/IaC/Terratest/examples/instance.tf new file mode 100644 index 0000000..5a9db2d --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/instance.tf @@ -0,0 +1,12 @@ +resource "aws_instance" "example" { + ami = var.AMIS[var.AWS_REGION] + instance_type = "t2.micro" + vpc_security_group_ids = [aws_security_group.instance.id] + + # When the instance boots, start a web server on port 8080 that responds with "Hello, World!". + user_data = < index.html +nohup busybox httpd -f -p 8080 & +EOF +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/output.tf b/2022/Days/IaC/Terratest/examples/output.tf new file mode 100644 index 0000000..752bb05 --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/output.tf @@ -0,0 +1,4 @@ +# Output the instance's public IP address. +output "public_ip" { + value = aws_instance.example.public_ip +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/provider.tf b/2022/Days/IaC/Terratest/examples/provider.tf new file mode 100644 index 0000000..20ca06a --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/provider.tf @@ -0,0 +1,5 @@ +provider "aws" { + access_key = var.AWS_ACCESS_KEY + secret_key = var.AWS_SECRET_KEY + region = var.AWS_REGION +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/securitygroup.tf b/2022/Days/IaC/Terratest/examples/securitygroup.tf new file mode 100644 index 0000000..d562dee --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/securitygroup.tf @@ -0,0 +1,9 @@ +# Allow the instance to receive requests on port 8080. +resource "aws_security_group" "instance" { + ingress { + from_port = 8080 + to_port = 8080 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/terraform.tfvars b/2022/Days/IaC/Terratest/examples/terraform.tfvars new file mode 100644 index 0000000..f819709 --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/terraform.tfvars @@ -0,0 +1,3 @@ +AWS_ACCESS_KEY = "XXXX" +AWS_SECRET_KEY = "XXXXXXXX" +AWS_REGION="ap-south-1" \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/vars.tf b/2022/Days/IaC/Terratest/examples/vars.tf new file mode 100644 index 0000000..40091fa --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/vars.tf @@ -0,0 +1,16 @@ +variable "AWS_ACCESS_KEY" { +} + +variable "AWS_SECRET_KEY" { +} + +variable "AWS_REGION" { + default = "ap-south-1" +} + +variable "AMIS" { + type = map(string) + default = { + ap-south-1 = "ami-0860c9429baba6ad2" + } +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/examples/versions.tf b/2022/Days/IaC/Terratest/examples/versions.tf new file mode 100644 index 0000000..0ac1e24 --- /dev/null +++ b/2022/Days/IaC/Terratest/examples/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.12.26" +} \ No newline at end of file diff --git a/2022/Days/IaC/Terratest/test/terraform_test.go b/2022/Days/IaC/Terratest/test/terraform_test.go new file mode 100644 index 0000000..93dc842 --- /dev/null +++ b/2022/Days/IaC/Terratest/test/terraform_test.go @@ -0,0 +1,34 @@ +package test + +import ( + "fmt" + "testing" + "time" + + http_helper "github.com/gruntwork-io/terratest/modules/http-helper" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestTerraformAwsHelloWorldExample(t *testing.T) { + t.Parallel() + + /*Construct the terraform options with default retryable errors to handle the most common retryable errors in terraform testing. */ + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + /* The path to where our Terraform code is located */ + TerraformDir: "../examples", + }) + + /* At the end of the test, run `terraform destroy` to clean up any resources that were created.*/ + defer terraform.Destroy(t, terraformOptions) + + /* Run `terraform init` and `terraform apply`. Fail the test if there are any errors. */ + terraform.InitAndApply(t, terraformOptions) + + /* Run `terraform output` to get the IP of the instance */ + publicIp := terraform.Output(t, terraformOptions, "public_ip") + + /* Make an HTTP request to the instance and make sure we get back a 200 OK with the body "Hello, World!" */ + url := fmt.Sprintf("http://%s:8080", publicIp) + http_helper.HttpGetWithRetry(t, url, nil, 200, "Hello, World!", 30, 5*time.Second) +} diff --git a/2022/Days/day62.md b/2022/Days/day62.md index 593de42..e468ce2 100644 --- a/2022/Days/day62.md +++ b/2022/Days/day62.md @@ -56,9 +56,32 @@ Managed Cloud offering - [Terraform Sentinel](https://www.terraform.io/cloud-docs/sentinel) - embedded policy-as-code framework integrated with the HashiCorp Enterprise products. It enables fine-grained, logic-based policy decisions, and can be extended to use information from external sources. -Automated testing +### Automated testing - [Terratest](https://terratest.gruntwork.io/) - Terratest is a Go library that provides patterns and helper functions for testing infrastructure +- Terratest makes it easier to write automated tests for our infrastructure code. It provides a variety of helper functions and patterns for common infrastructure testing. + +- To Run this application + * git clone #repo_url#
+ * cd test
+ * go mod init ""
+ **MODULE_NAME would be github.com//**
+ * go mod init github.com/
+ * go run + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +go mod init "" would create go.mod file into test folder.
+* The go.mod file is the root of dependency management in GoLang. +* All the modules which are needed or to be used in the project are maintained here in go.mod file. +* It creates entry for all the packages we are going to use/import in our project. +* It reduces effort for getting each dependencies manually. + +On running **go test** for the first time you would get go.sum file created.
+* go.sum file is created when **go test** or **go build** is executed for the first time. +* It installs all the packages with specific version(latest) +* we do not need to edit or modify this file. + Worth a mention