Skip to content
This repository has been archived by the owner on Feb 14, 2024. It is now read-only.

test: Integration tests for other modules #276

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions tests/alb/main_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package main

import (
"log"
"testing"

"github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/helpers"
"github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"log"
"testing"
)

func TestALBOutputAndConectivitiyWithFullTFVars(t *testing.T) {
Expand Down Expand Up @@ -51,7 +52,7 @@ func TestALBOutputAndConectivitiyWithFullTFVars(t *testing.T) {
// check communication with app
{
Operation: "CheckFunctionWithValue",
Check: helpers.CheckHttpGetWebUiLoginPage,
Check: helpers.CheckHttpGetWebApp,
TestedValue: "http://" + albName + "/",
},
}
Expand Down
13 changes: 7 additions & 6 deletions tests/internal/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,31 @@ import (
"time"
)

func CheckHttpGetWebUiLoginPage(t *testing.T, outputValue string) bool {
func CheckHttpGetWebApp(t *testing.T, outputValue string) bool {
// Do not verify insecure connection
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

// Define how many retries and how often to do in order to check if Panorama web UI is healthy
// Define how many retries and how often to do in order to check if application is healthy
sleepBetweenRetry := 15 * time.Second
numberOfRetries := 60
urlHealthy := false

// Check in the loop if Panorama web UI is healthy
// Check in the loop if application is healthy
for i := 1; i <= numberOfRetries && !urlHealthy; i++ {
// HTTP GET
time.Sleep(sleepBetweenRetry)
//TODO: Check if client can replace :15

//TODO: Check if client can replace :22
//client := http.Client{
// Timeout: 15 * time.Second,
//}
resp, err := http.Get(outputValue)

// Display errors, if there were any, or HTTPS status code, if no errors
if err != nil {
t.Logf("Waiting for App (%d/%d)... error HTTP GET: %v\n", i, numberOfRetries, err)
t.Logf("Waiting for application (%d/%d)... error HTTP GET: %v\n", i, numberOfRetries, err)
} else {
t.Logf("APP HTTP GET status code: %v", resp.StatusCode)
t.Logf("Application HTTP GET status code: %v", resp.StatusCode)
urlHealthy = resp.StatusCode == 200
}
}
Expand Down
45 changes: 26 additions & 19 deletions tests/internal/testskeleton/testskeleton.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ func AssertOutputs(t *testing.T, terraformOptions *terraform.Options, assertList
case "Equal":
outputValue := terraform.Output(t, terraformOptions, assertExpression.OutputName)
assert.Equal(t, assertExpression.ExpectedValue, outputValue, assertExpression.Message)
case "NotFound":
_, err := terraform.OutputE(t, terraformOptions, assertExpression.OutputName)
assert.ErrorContains(t, err,
fmt.Sprintf("Output \"%v\" not found", assertExpression.OutputName),
assertExpression.Message)
case "ListLengthEqual":
outputValue := terraform.OutputList(t, terraformOptions, assertExpression.OutputName)
assert.Equal(t, assertExpression.ExpectedValue, len(outputValue), assertExpression.Message)
Expand Down Expand Up @@ -127,30 +132,15 @@ func PlanInfraCheckErrors(t *testing.T, terraformOptions *terraform.Options,
assert.Error(t, err)
AssertErrors(t, err, assertList)
} else {
// Fail test, because error was expected
t.Error(noErrorsMessage)
// Fail test, if errors were expected
if len(assertList) > 0 {
t.Error(noErrorsMessage)
}
}

return terraformOptions
}

func InitAndApplyOnlyWithoutDelete(t *testing.T, terraformOptions *terraform.Options) *terraform.Options {
// If no Terraform options were provided, use default one
if terraformOptions == nil {
terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: ".",
Logger: logger.Default,
Lock: true,
Upgrade: true,
})
}

// Terraform initalization and apply with auto-approve
terraform.InitAndApply(t, terraformOptions)

return terraformOptions
}

// Function is comparing every provided error in expressions lists
// and checks value using expression defined in the list
func AssertErrors(t *testing.T, err error, assertList []AssertExpression) {
Expand All @@ -169,3 +159,20 @@ func AssertErrors(t *testing.T, err error, assertList []AssertExpression) {
}
}
}

func InitAndApplyOnlyWithoutDelete(t *testing.T, terraformOptions *terraform.Options) *terraform.Options {
// If no Terraform options were provided, use default one
if terraformOptions == nil {
terraformOptions = terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: ".",
Logger: logger.Default,
Lock: true,
Upgrade: true,
})
}

// Terraform initalization and apply with auto-approve
terraform.InitAndApply(t, terraformOptions)

return terraformOptions
}
7 changes: 4 additions & 3 deletions tests/panorama/main_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package bootstrap
package panorama

import (
"testing"

"github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/helpers"
"github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"testing"
)

func TestOutputForModulePanoramaWithFullVariables(t *testing.T) {
Expand All @@ -32,7 +33,7 @@ func TestOutputForModulePanoramaWithFullVariables(t *testing.T) {
// check access to login page in web UI for Panorama
{
Operation: "CheckFunctionWithOutput",
Check: helpers.CheckHttpGetWebUiLoginPage,
Check: helpers.CheckHttpGetWebApp,
OutputName: "panorama_url",
Message: "After bootstrapping, which takes few minutes, web UI for Panorama should be accessible",
},
Expand Down
2 changes: 1 addition & 1 deletion tests/transit_gateway/main_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package bootstrap
package transit_gateway

import (
"testing"
Expand Down
77 changes: 77 additions & 0 deletions tests/transit_gateway_attachment/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
locals {
# List of VPC routes
security_vpc_routes = concat(
[for cidr in var.security_vpc_app_routes :
{
subnet_key = "mgmt"
next_hop_set = module.security_transit_gateway_attachment[0].next_hop_set
to_cidr = cidr
} if length(var.transit_gateway_route_tables) > 0
],
)
}

# Random ID used in names of the resoruces created for tests
resource "random_string" "random_sufix" {
length = 16
special = false
}

# Test security VPC
module "security_vpc" {
source = "../../modules/vpc"

name = "${var.name_prefix}${random_string.random_sufix.id}"
cidr_block = var.security_vpc_cidr
security_groups = var.security_vpc_security_groups
create_internet_gateway = true
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
}

# Subnets configured in test security VPC
module "security_subnet_sets" {
for_each = toset(distinct([for _, v in var.security_vpc_subnets : v.set]))
source = "../../modules/subnet_set"

name = "${var.name_prefix}${random_string.random_sufix.id}_${each.key}"
vpc_id = module.security_vpc.id
has_secondary_cidrs = module.security_vpc.has_secondary_cidrs
cidrs = { for k, v in var.security_vpc_subnets : k => v if v.set == each.key }
}

# Routes configured in test security VPC
module "security_vpc_routes" {
for_each = { for route in local.security_vpc_routes : "${route.subnet_key}_${route.to_cidr}" => route }
source = "../../modules/vpc_route"

route_table_ids = module.security_subnet_sets[each.value.subnet_key].unique_route_table_ids
to_cidr = try(each.value.to_cidr, null)
destination_type = try(each.value.destination_type, "ipv4")
managed_prefix_list_id = try(each.value.managed_prefix_list_id, null)
next_hop_set = each.value.next_hop_set
}

# Transit gateway (without attachments)
module "transit_gateway" {
source = "../../modules/transit_gateway"

name = var.transit_gateway_name != null ? "${var.name_prefix}${random_string.random_sufix.id}_${var.transit_gateway_name}" : null
asn = var.transit_gateway_asn
route_tables = var.transit_gateway_route_tables
}

# Transit gateway attachment for security VPC
module "security_transit_gateway_attachment" {
source = "../../modules/transit_gateway_attachment"
count = length(var.transit_gateway_route_tables) > 0 ? 1 : 0

name = "${var.name_prefix}${random_string.random_sufix.id}_${var.security_vpc_tgw_attachment_name}"
vpc_id = module.security_subnet_sets["tgw_attach"].vpc_id
subnets = module.security_subnet_sets["tgw_attach"].subnets
transit_gateway_route_table = module.transit_gateway.route_tables["from_security_vpc"]
propagate_routes_to = {
to1 = module.transit_gateway.route_tables["from_spoke_vpc"].id
}
}
76 changes: 76 additions & 0 deletions tests/transit_gateway_attachment/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package transit_gateway_attachment

import (
"testing"

"github.com/PaloAltoNetworks/terraform-aws-vmseries-modules/tests/internal/testskeleton"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
)

func TestOutputForModuleTransitGatewayAttachmentFullVariables(t *testing.T) {
// define options for Terraform
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: ".",
VarFiles: []string{"terraform_full.tfvars"},
Vars: map[string]interface{}{
"name_prefix": "terratest_module_tgw_attach_",
},
Logger: logger.Default,
Lock: true,
Upgrade: true,
SetVarsAfterVarFiles: true,
})

// prepare list of items to check
assertList := []testskeleton.AssertExpression{
{OutputName: "tgw_id", Operation: "NotEmpty"},
{OutputName: "tgw_id", Operation: "StartsWith", ExpectedValue: "tgw-", Message: "TGW ID should starts from tgw-"},

{OutputName: "tgw_arn", Operation: "NotEmpty"},
{OutputName: "tgw_arn", Operation: "StartsWith", ExpectedValue: "arn:aws:ec2:us-east-1", Message: "TGW ARN should starts from arn:aws:ec2:us-east-1"},

{OutputName: "tgw_route_tables", Operation: "NotEmpty"},
{OutputName: "tgw_route_tables", Operation: "ListLengthEqual", ExpectedValue: 2},

{OutputName: "tgw_attachment_next_hop_set", Operation: "NotEmpty", ExpectedValue: nil},
{OutputName: "tgw_attachment_next_hop_set_tgw_id", Operation: "NotEmpty", ExpectedValue: nil},
{OutputName: "tgw_attachment_next_hop_set_tgw_id", Operation: "NotEmpty", ExpectedValue: "tgw-", Message: "TGW ID should starts from tgw-"},
}

// deploy test infrastructure and verify outputs
testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList)
}

func TestOutputForModuleTransitGatewayAttachmentMinimumVariables(t *testing.T) {
// define options for Terraform
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: ".",
VarFiles: []string{"terraform_minimum.tfvars"},
Vars: map[string]interface{}{
"name_prefix": "terratest_module_tgw_attach_",
},
Logger: logger.Default,
Lock: true,
Upgrade: true,
SetVarsAfterVarFiles: true,
})

// prepare list of items to check
assertList := []testskeleton.AssertExpression{
{OutputName: "tgw_id", Operation: "NotEmpty"},
{OutputName: "tgw_id", Operation: "StartsWith", ExpectedValue: "tgw-", Message: "TGW ARN should starts from tgw-"},

{OutputName: "tgw_arn", Operation: "NotEmpty"},
{OutputName: "tgw_arn", Operation: "StartsWith", ExpectedValue: "arn:aws:ec2:us-east-1", Message: "TGW ID should starts from arn:aws:ec2:us-east-1"},

{OutputName: "tgw_route_tables", Operation: "NotEmpty"},
{OutputName: "tgw_route_tables", Operation: "ListLengthEqual", ExpectedValue: 0},

{OutputName: "tgw_attachment_next_hop_set", Operation: "NotFound"},
{OutputName: "tgw_attachment_next_hop_set_tgw_id", Operation: "NotFound"},
}

// deploy test infrastructure and verify outputs
testskeleton.DeployInfraCheckOutputs(t, terraformOptions, assertList)
}
19 changes: 19 additions & 0 deletions tests/transit_gateway_attachment/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
output "tgw_id" {
value = module.transit_gateway.transit_gateway.id
}

output "tgw_arn" {
value = module.transit_gateway.transit_gateway.arn
}

output "tgw_route_tables" {
value = [for k, v in module.transit_gateway.route_tables : v.tags["Name"]]
}

output "tgw_attachment_next_hop_set" {
value = length(var.transit_gateway_route_tables) > 0 ? module.security_transit_gateway_attachment[0].next_hop_set : null
}

output "tgw_attachment_next_hop_set_tgw_id" {
value = length(var.transit_gateway_route_tables) > 0 ? module.security_transit_gateway_attachment[0].next_hop_set.id : null
}
44 changes: 44 additions & 0 deletions tests/transit_gateway_attachment/terraform_full.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
region = "us-east-1"
name_prefix = "test_tgw_"

security_vpc_cidr = "10.100.0.0/16"
security_vpc_subnets = {
"10.100.0.0/24" = { az = "us-east-1a", set = "mgmt" }
"10.100.1.0/24" = { az = "us-east-1a", set = "tgw_attach" }
"10.100.2.0/24" = { az = "us-east-1a", set = "natgw" }
"10.100.3.0/24" = { az = "us-east-1a", set = "gwlb" }
"10.100.4.0/24" = { az = "us-east-1a", set = "gwlbe_inbound" }
}
security_vpc_security_groups = {
vmseries_mgmt = {
name = "vmseries_mgmt"
rules = {
all_outbound = {
description = "Permit ALL outbound"
type = "egress", from_port = "0", to_port = "0", protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ssh = {
description = "Permit SSH inbound"
type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
}
security_vpc_app_routes = ["10.231.0.0/16", "10.232.0.0/16"]

security_vpc_tgw_attachment_name = "tgw"

transit_gateway_name = "tgw"
transit_gateway_asn = "65200"
transit_gateway_route_tables = {
"from_security_vpc" = {
create = true
name = "from_security"
}
"from_spoke_vpc" = {
create = true
name = "from_spokes"
}
}
Loading