Samples: end-to-end testing (#47)

Add a new sample for end-to-end testing in Terraform projects.
This commit is contained in:
Julien Corioland
2020-06-18 14:48:42 +02:00
committed by GitHub
parent 74170d8203
commit 24455a9336
11 changed files with 400 additions and 1 deletions

View File

@ -0,0 +1,140 @@
resource "random_integer" "rand" {
min = 1000
max = 9999
}
resource "azurerm_resource_group" "rg" {
name = "rg-terratest-sample-${random_integer.rand.result}"
location = var.location
}
resource "azurerm_virtual_network" "vnet" {
name = "vnet-terratest-sample"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "subnet" {
name = "default"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.2.0/24"]
}
## Linux VM 1
resource "azurerm_public_ip" "pip" {
name = "pip-vm-linux-1"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
allocation_method = "Dynamic"
idle_timeout_in_minutes = 30
}
resource "azurerm_network_interface" "nic1" {
name = "nic-vm-linux-1"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.pip.id
}
}
resource "azurerm_network_security_group" "nsg" {
name = "nsg-terraform-sample"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface_security_group_association" "nic1-nsg" {
network_interface_id = azurerm_network_interface.nic1.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_linux_virtual_machine" "vm1" {
name = "vm-linux-1"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_B2s"
admin_username = "azureuser"
network_interface_ids = [
azurerm_network_interface.nic1.id,
]
admin_ssh_key {
username = "azureuser"
public_key = file("~/.ssh/id_rsa.pub")
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
## Linux VM 2
resource "azurerm_network_interface" "nic2" {
name = "nic-vm-linux-2"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_linux_virtual_machine" "vm2" {
name = "vm-linux-2"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_B2s"
admin_username = "azureuser"
network_interface_ids = [
azurerm_network_interface.nic2.id,
]
admin_ssh_key {
username = "azureuser"
public_key = file(var.ssh_public_key_file)
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}

View File

@ -0,0 +1,11 @@
output "resource_group_name" {
value = azurerm_resource_group.rg.name
}
output "vm_linux_1_public_ip_address" {
value = azurerm_public_ip.pip.ip_address
}
output "vm_linux_2_private_ip_address" {
value = azurerm_network_interface.nic2.ip_configuration[0].private_ip_address
}

View File

@ -0,0 +1,3 @@
provider "azurerm" {
features {}
}

View File

@ -0,0 +1,101 @@
package test
import (
"fmt"
"io/ioutil"
"os"
"testing"
"time"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"golang.org/x/crypto/ssh"
)
func TestEndToEndDeploymentScenario(t *testing.T) {
t.Parallel()
fixtureFolder := "../"
sshKeyPath := os.Getenv("TEST_SSH_KEY_PATH")
if sshKeyPath == "" {
t.Fatalf("TEST_SSH_KEY_PATH environment variable cannot be empty.")
}
// User Terratest to deploy the infrastructure
test_structure.RunTestStage(t, "setup", func() {
terraformOptions := &terraform.Options{
// Indicate the directory that contains the Terraform configuration to deploy
TerraformDir: fixtureFolder,
}
// Save options for later test stages
test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)
// Triggers the terraform init and terraform apply command
terraform.InitAndApply(t, terraformOptions)
})
test_structure.RunTestStage(t, "validate", func() {
// run validation checks here
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
vmLinux1PublicIPAddress := terraform.Output(t, terraformOptions, "vm_linux_1_public_ip_address")
vmLinux2PrivateIPAddress := terraform.Output(t, terraformOptions, "vm_linux_2_private_ip_address")
// it takes some time for Azure to assign the public IP address so it's not available in Terraform output after the first apply
attemptsCount := 0
for vmLinux1PublicIPAddress == "" && attemptsCount < 5 {
// add wait time to let Azure assign the public IP address and apply the configuration again, to refresh state.
time.Sleep(30 * time.Second)
terraform.Apply(t, terraformOptions)
vmLinux1PublicIPAddress = terraform.Output(t, terraformOptions, "vm_linux_1_public_ip_address")
attemptsCount++
}
if vmLinux1PublicIPAddress == "" {
t.Fatal("Cannot retrieve the public IP address value for the linux vm 1.")
}
key, err := ioutil.ReadFile(sshKeyPath)
if err != nil {
t.Fatalf("Unable to read private key: %v", err)
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
t.Fatalf("Unable to parse private key: %v", err)
}
sshConfig := &ssh.ClientConfig{
User: "azureuser",
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
sshConnection, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", vmLinux1PublicIPAddress), sshConfig)
if err != nil {
t.Fatalf("Cannot establish SSH connection to vm-linux-1 public IP address: %v", err)
}
defer sshConnection.Close()
sshSession, err := sshConnection.NewSession()
if err != nil {
t.Fatalf("Cannot create SSH session to vm-linux-1 public IP address: %v", err)
}
defer sshSession.Close()
err = sshSession.Run(fmt.Sprintf("ping -c 1 %s", vmLinux2PrivateIPAddress))
if err != nil {
t.Fatalf("Cannot ping vm-linux-2 from vm-linux-2: %v", err)
}
})
// When the test is completed, teardown the infrastructure by calling terraform destroy
test_structure.RunTestStage(t, "teardown", func() {
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
terraform.Destroy(t, terraformOptions)
})
}

View File

@ -0,0 +1,8 @@
module test
go 1.13
require (
github.com/gruntwork-io/terratest v0.28.5
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
)

View File

@ -0,0 +1,11 @@
variable location {
type = string
description = "The Azure location where the resources will be created."
default = "westeurope"
}
variable ssh_public_key_file {
type = string
description = "The file path of the public SSH key to use for the virtual machine."
default = "~/.ssh/id_rsa.pub"
}