Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ aws-assumed-role/
*.iml
.direnv
.envrc
.cache

# Compiled and auto-generated files
# Note that the leading "**/" appears necessary for Docker even if not for Git
Expand Down
2 changes: 1 addition & 1 deletion README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ description: |-
cluster_size: 0 # serverless
scaling_configuration:
- auto_pause: true
max_capacity: 5
max_capacity: 4
min_capacity: 2
seconds_until_auto_pause: 300
timeout_action: null
Expand Down
2 changes: 1 addition & 1 deletion src/cluster-regional.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module "aurora_postgres_cluster" {
publicly_accessible = var.publicly_accessible
db_port = var.database_port
vpc_id = local.vpc_id
subnets = local.private_subnet_ids
subnets = var.publicly_accessible ? local.public_subnet_ids : local.private_subnet_ids
zone_id = local.zone_id
cluster_dns_name = local.cluster_dns_name
reader_dns_name = local.reader_dns_name
Expand Down
1 change: 1 addition & 0 deletions src/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ locals {

vpc_id = module.vpc.outputs.vpc_id
private_subnet_ids = module.vpc.outputs.private_subnet_ids
public_subnet_ids = module.vpc.outputs.public_subnet_ids

eks_security_group_enabled = local.enabled && var.eks_security_group_enabled
allowed_eks_security_groups = [
Expand Down
8 changes: 4 additions & 4 deletions src/remote-state.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module "vpc" {
source = "cloudposse/stack-config/yaml//modules/remote-state"
version = "1.5.0"
version = "1.8.0"

component = var.vpc_component_name

Expand All @@ -9,7 +9,7 @@ module "vpc" {

module "vpc_ingress" {
source = "cloudposse/stack-config/yaml//modules/remote-state"
version = "1.5.0"
version = "1.8.0"

for_each = {
for i, account in var.allow_ingress_from_vpc_accounts :
Expand All @@ -27,7 +27,7 @@ module "vpc_ingress" {

module "eks" {
source = "cloudposse/stack-config/yaml//modules/remote-state"
version = "1.5.0"
version = "1.8.0"

for_each = local.eks_security_group_enabled ? var.eks_component_names : toset([])
component = each.value
Expand All @@ -38,7 +38,7 @@ module "eks" {

module "dns_gbl_delegated" {
source = "cloudposse/stack-config/yaml//modules/remote-state"
version = "1.5.0"
version = "1.8.0"

component = "dns-delegated"
environment = var.dns_gbl_delegated_environment_name
Expand Down
4 changes: 4 additions & 0 deletions test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
state/
.cache
test/test-suite.json
.atmos
245 changes: 245 additions & 0 deletions test/component_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
package test

import (
"fmt"
"testing"

"github.com/cloudposse/test-helpers/pkg/atmos"
helper "github.com/cloudposse/test-helpers/pkg/atmos/aws-component-helper"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/stretchr/testify/assert"
)

type validationOption struct {
DomainName string `json:"domain_name"`
ResourceRecordName string `json:"resource_record_name"`
ResourceRecordType string `json:"resource_record_type"`
ResourceRecordValue string `json:"resource_record_value"`
}

type zone struct {
Arn string `json:"arn"`
Comment string `json:"comment"`
DelegationSetId string `json:"delegation_set_id"`
ForceDestroy bool `json:"force_destroy"`
Id string `json:"id"`
Name string `json:"name"`
NameServers []string `json:"name_servers"`
PrimaryNameServer string `json:"primary_name_server"`
Tags map[string]string `json:"tags"`
TagsAll map[string]string `json:"tags_all"`
Vpc []struct {
ID string `json:"vpc_id"`
Region string `json:"vpc_region"`
} `json:"vpc"`
ZoneID string `json:"zone_id"`
}

func TestComponent(t *testing.T) {
t.Parallel()
// Define the AWS region to use for the tests
awsRegion := "us-east-2"

// Initialize the test fixture
fixture := helper.NewFixture(t, "../", awsRegion, "test/fixtures")

// Ensure teardown is executed after the test
defer fixture.TearDown()
fixture.SetUp(&atmos.Options{})

// Define the test suite
fixture.Suite("default", func(t *testing.T, suite *helper.Suite) {
t.Parallel()
suite.AddDependency("vpc", "default-test")

// Setup phase: Create DNS zones for testing
suite.Setup(t, func(t *testing.T, atm *helper.Atmos) {
// Deploy the delegated DNS zone
inputs := map[string]interface{}{
"zone_config": []map[string]interface{}{
{
"subdomain": suite.GetRandomIdentifier(),
"zone_name": "components.cptest.test-automation.app",
},
},
}
atm.GetAndDeploy("dns-delegated", "default-test", inputs)
})

// Teardown phase: Destroy the DNS zones created during setup
suite.TearDown(t, func(t *testing.T, atm *helper.Atmos) {
// Deploy the delegated DNS zone
inputs := map[string]interface{}{
"zone_config": []map[string]interface{}{
{
"subdomain": suite.GetRandomIdentifier(),
"zone_name": "components.cptest.test-automation.app",
},
},
}
atm.GetAndDeploy("dns-delegated", "default-test", inputs)
})

// Test phase: Validate the functionality of the ALB component
suite.Test(t, "basic", func(t *testing.T, atm *helper.Atmos) {
t.Parallel()
inputs := map[string]interface{}{
"name": "db",
"database_name": "postgres",
"admin_user": "postgres",
"database_port": 5432,
"publicly_accessible": true,
"allowed_cidr_blocks": []string{
"0.0.0.0/0",
},
}

component := helper.NewAtmosComponent("aurora-postgres/basic", "default-test", inputs)
component.Vars["cluster_name"] = component.GetRandomIdentifier()

defer atm.Destroy(component)
atm.Deploy(component)
assert.NotNil(t, component)

databaseName := atm.Output(component, "database_name")
assert.Equal(t, "postgres", databaseName)

adminUsername := atm.Output(component, "admin_username")
assert.Equal(t, "postgres", adminUsername)

delegatedDnsComponent := helper.NewAtmosComponent("dns-delegated", "default-test", map[string]interface{}{})
delegatedDomainName := atm.Output(delegatedDnsComponent, "default_domain_name")
delegatedDomainNZoneId := atm.Output(delegatedDnsComponent, "default_dns_zone_id")

masterHostname := atm.Output(component, "master_hostname")
expectedMasterHostname := fmt.Sprintf("%s-%s-writer.%s", inputs["name"], component.Vars["cluster_name"], delegatedDomainName)
assert.Equal(t, expectedMasterHostname, masterHostname)

replicasHostname := atm.Output(component, "replicas_hostname")
expectedReplicasHostname := fmt.Sprintf("%s-%s-reader.%s", inputs["name"], component.Vars["cluster_name"], delegatedDomainName)
assert.Equal(t, expectedReplicasHostname, replicasHostname)

ssmKeyPaths := atm.OutputList(component, "ssm_key_paths")
assert.Equal(t, 7, len(ssmKeyPaths))

kmsKeyArn := atm.Output(component, "kms_key_arn")
assert.NotEmpty(t, kmsKeyArn)

allowedSecurtiyGroups := atm.OutputList(component, "allowed_security_groups")
assert.Equal(t, 0, len(allowedSecurtiyGroups))

clusterIdentifier := atm.Output(component, "cluster_identifier")

configMap := map[string]interface{}{}
atm.OutputStruct(component, "config_map", &configMap)

assert.Equal(t, clusterIdentifier, configMap["cluster"])
assert.Equal(t, databaseName, configMap["database"])
assert.Equal(t, masterHostname, configMap["hostname"])
assert.EqualValues(t, inputs["database_port"], configMap["port"])
assert.Equal(t, adminUsername, configMap["username"])

masterHostnameDNSRecord := aws.GetRoute53Record(t, delegatedDomainNZoneId, masterHostname, "CNAME", awsRegion)
assert.Equal(t, *masterHostnameDNSRecord.ResourceRecords[0].Value, configMap["endpoint"])

// Uncomment the following code block to validate the schema creation in the RDS instance
// when `publicly_accessible=true` will use public subnets

passwordSSMKey, ok := configMap["password_ssm_key"].(string)
assert.True(t, ok, "password_ssm_key should be a string")

adminUserPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)

dbUrl, ok := configMap["endpoint"].(string)
assert.True(t, ok, "endpoint should be a string")

dbPort, ok := inputs["database_port"].(int)
assert.True(t, ok, "database_port should be an int")

schemaExistsInRdsInstance := aws.GetWhetherSchemaExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), adminUsername, adminUserPassword, databaseName)
assert.True(t, schemaExistsInRdsInstance)

schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(t, masterHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
assert.True(t, schemaExistsInRdsInstance)

schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(t, replicasHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
assert.True(t, schemaExistsInRdsInstance)
})

// Test phase: Validate the functionality of the ALB component
suite.Test(t, "serverless", func(t *testing.T, atm *helper.Atmos) {
t.Parallel()
inputs := map[string]interface{}{
"name": "db",
"database_name": "postgres",
"admin_user": "postgres",
"database_port": 5432,
"publicly_accessible": true,
"allowed_cidr_blocks": []string{
"0.0.0.0/0",
},
}

component := helper.NewAtmosComponent("aurora-postgres/serverless", "default-test", inputs)
component.Vars["cluster_name"] = component.GetRandomIdentifier()

defer atm.Destroy(component)
atm.Deploy(component)
assert.NotNil(t, component)

databaseName := atm.Output(component, "database_name")
assert.Equal(t, "postgres", databaseName)

adminUsername := atm.Output(component, "admin_username")
assert.Equal(t, "postgres", adminUsername)

delegatedDnsComponent := helper.NewAtmosComponent("dns-delegated", "default-test", map[string]interface{}{})
delegatedDomainName := atm.Output(delegatedDnsComponent, "default_domain_name")
delegatedDomainNZoneId := atm.Output(delegatedDnsComponent, "default_dns_zone_id")

masterHostname := atm.Output(component, "master_hostname")
expectedMasterHostname := fmt.Sprintf("%s-%s-writer.%s", inputs["name"], component.Vars["cluster_name"], delegatedDomainName)
assert.Equal(t, expectedMasterHostname, masterHostname)

ssmKeyPaths := atm.OutputList(component, "ssm_key_paths")
assert.Equal(t, 7, len(ssmKeyPaths))

kmsKeyArn := atm.Output(component, "kms_key_arn")
assert.NotEmpty(t, kmsKeyArn)

allowedSecurtiyGroups := atm.OutputList(component, "allowed_security_groups")
assert.Equal(t, 0, len(allowedSecurtiyGroups))

clusterIdentifier := atm.Output(component, "cluster_identifier")

configMap := map[string]interface{}{}
atm.OutputStruct(component, "config_map", &configMap)

assert.Equal(t, clusterIdentifier, configMap["cluster"])
assert.Equal(t, databaseName, configMap["database"])
assert.Equal(t, masterHostname, configMap["hostname"])
assert.EqualValues(t, inputs["database_port"], configMap["port"])
assert.Equal(t, adminUsername, configMap["username"])

masterHostnameDNSRecord := aws.GetRoute53Record(t, delegatedDomainNZoneId, masterHostname, "CNAME", awsRegion)
assert.Equal(t, *masterHostnameDNSRecord.ResourceRecords[0].Value, configMap["endpoint"])

passwordSSMKey, ok := configMap["password_ssm_key"].(string)
assert.True(t, ok, "password_ssm_key should be a string")

adminUserPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)

dbUrl, ok := configMap["endpoint"].(string)
assert.True(t, ok, "endpoint should be a string")

dbPort, ok := inputs["database_port"].(int)
assert.True(t, ok, "database_port should be an int")

schemaExistsInRdsInstance := aws.GetWhetherSchemaExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), adminUsername, adminUserPassword, databaseName)
assert.True(t, schemaExistsInRdsInstance)

schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(t, masterHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
assert.True(t, schemaExistsInRdsInstance)
})
})
}
Loading
Loading