Skip to content

Commit 15880aa

Browse files
authored
Added tests (#20)
* Added tests * Pin test-helpers * Use DNS delegated * Teardown domain zone * Added tests * Added tests * Added tests * Added tests * Added tests * Added tests * Pin tests * Pin version * Pin version * Added tests
1 parent 4ddd5d2 commit 15880aa

File tree

21 files changed

+1032
-9
lines changed

21 files changed

+1032
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ aws-assumed-role/
77
*.iml
88
.direnv
99
.envrc
10+
.cache
1011

1112
# Compiled and auto-generated files
1213
# Note that the leading "**/" appears necessary for Docker even if not for Git

README.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ description: |-
154154
cluster_size: 0 # serverless
155155
scaling_configuration:
156156
- auto_pause: true
157-
max_capacity: 5
157+
max_capacity: 4
158158
min_capacity: 2
159159
seconds_until_auto_pause: 300
160160
timeout_action: null

src/cluster-regional.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module "aurora_postgres_cluster" {
2121
publicly_accessible = var.publicly_accessible
2222
db_port = var.database_port
2323
vpc_id = local.vpc_id
24-
subnets = local.private_subnet_ids
24+
subnets = var.publicly_accessible ? local.public_subnet_ids : local.private_subnet_ids
2525
zone_id = local.zone_id
2626
cluster_dns_name = local.cluster_dns_name
2727
reader_dns_name = local.reader_dns_name

src/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ locals {
33

44
vpc_id = module.vpc.outputs.vpc_id
55
private_subnet_ids = module.vpc.outputs.private_subnet_ids
6+
public_subnet_ids = module.vpc.outputs.public_subnet_ids
67

78
eks_security_group_enabled = local.enabled && var.eks_security_group_enabled
89
allowed_eks_security_groups = [

src/remote-state.tf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module "vpc" {
22
source = "cloudposse/stack-config/yaml//modules/remote-state"
3-
version = "1.5.0"
3+
version = "1.8.0"
44

55
component = var.vpc_component_name
66

@@ -9,7 +9,7 @@ module "vpc" {
99

1010
module "vpc_ingress" {
1111
source = "cloudposse/stack-config/yaml//modules/remote-state"
12-
version = "1.5.0"
12+
version = "1.8.0"
1313

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

2828
module "eks" {
2929
source = "cloudposse/stack-config/yaml//modules/remote-state"
30-
version = "1.5.0"
30+
version = "1.8.0"
3131

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

3939
module "dns_gbl_delegated" {
4040
source = "cloudposse/stack-config/yaml//modules/remote-state"
41-
version = "1.5.0"
41+
version = "1.8.0"
4242

4343
component = "dns-delegated"
4444
environment = var.dns_gbl_delegated_environment_name

test/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
state/
2+
.cache
3+
test/test-suite.json
4+
.atmos
5+
test_suite.yaml

test/component_test.go

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package test
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"github.com/cloudposse/test-helpers/pkg/atmos"
9+
helper "github.com/cloudposse/test-helpers/pkg/atmos/component-helper"
10+
"github.com/gruntwork-io/terratest/modules/aws"
11+
"github.com/stretchr/testify/assert"
12+
"github.com/gruntwork-io/terratest/modules/random"
13+
)
14+
15+
type ComponentSuite struct {
16+
helper.TestSuite
17+
}
18+
19+
func (s *ComponentSuite) TestBasic() {
20+
const component = "aurora-postgres/basic"
21+
const stack = "default-test"
22+
const awsRegion = "us-east-2"
23+
24+
clusterName := strings.ToLower(random.UniqueId())
25+
26+
defer s.DestroyAtmosComponent(s.T(), component, stack, nil)
27+
inputs := map[string]interface{}{
28+
"name": "db",
29+
"database_name": "postgres",
30+
"admin_user": "postgres",
31+
"database_port": 5432,
32+
"publicly_accessible": true,
33+
"allowed_cidr_blocks": []string{"0.0.0.0/0"},
34+
"cluster_name": clusterName,
35+
}
36+
componentInstance, _ := s.DeployAtmosComponent(s.T(), component, stack, &inputs)
37+
assert.NotNil(s.T(), componentInstance)
38+
39+
databaseName := atmos.Output(s.T(), componentInstance, "database_name")
40+
assert.Equal(s.T(), "postgres", databaseName)
41+
42+
adminUsername := atmos.Output(s.T(), componentInstance, "admin_username")
43+
assert.Equal(s.T(), "postgres", adminUsername)
44+
45+
delegatedDnsOptions := s.GetAtmosOptions("dns-delegated", stack, nil)
46+
delegatedDomainName := atmos.Output(s.T(), delegatedDnsOptions, "default_domain_name")
47+
delegatedDomainNZoneId := atmos.Output(s.T(), delegatedDnsOptions, "default_dns_zone_id")
48+
49+
masterHostname := atmos.Output(s.T(), componentInstance, "master_hostname")
50+
expectedMasterHostname := fmt.Sprintf("%s-%s-writer.%s", inputs["name"], componentInstance.Vars["cluster_name"], delegatedDomainName)
51+
assert.Equal(s.T(), expectedMasterHostname, masterHostname)
52+
53+
replicasHostname := atmos.Output(s.T(), componentInstance, "replicas_hostname")
54+
expectedReplicasHostname := fmt.Sprintf("%s-%s-reader.%s", inputs["name"], componentInstance.Vars["cluster_name"], delegatedDomainName)
55+
assert.Equal(s.T(), expectedReplicasHostname, replicasHostname)
56+
57+
ssmKeyPaths := atmos.OutputList(s.T(), componentInstance, "ssm_key_paths")
58+
assert.Equal(s.T(), 7, len(ssmKeyPaths))
59+
60+
kmsKeyArn := atmos.Output(s.T(), componentInstance, "kms_key_arn")
61+
assert.NotEmpty(s.T(), kmsKeyArn)
62+
63+
allowedSecurityGroups := atmos.OutputList(s.T(), componentInstance, "allowed_security_groups")
64+
assert.Equal(s.T(), 0, len(allowedSecurityGroups))
65+
66+
clusterIdentifier := atmos.Output(s.T(), componentInstance, "cluster_identifier")
67+
68+
configMap := map[string]interface{}{}
69+
atmos.OutputStruct(s.T(), componentInstance, "config_map", &configMap)
70+
71+
assert.Equal(s.T(), clusterIdentifier, configMap["cluster"])
72+
assert.Equal(s.T(), databaseName, configMap["database"])
73+
assert.Equal(s.T(), masterHostname, configMap["hostname"])
74+
assert.EqualValues(s.T(), inputs["database_port"], configMap["port"])
75+
assert.Equal(s.T(), adminUsername, configMap["username"])
76+
77+
masterHostnameDNSRecord := aws.GetRoute53Record(s.T(), delegatedDomainNZoneId, masterHostname, "CNAME", awsRegion)
78+
assert.Equal(s.T(), *masterHostnameDNSRecord.ResourceRecords[0].Value, configMap["endpoint"])
79+
80+
passwordSSMKey, ok := configMap["password_ssm_key"].(string)
81+
assert.True(s.T(), ok, "password_ssm_key should be a string")
82+
83+
adminUserPassword := aws.GetParameter(s.T(), awsRegion, passwordSSMKey)
84+
85+
dbUrl, ok := configMap["endpoint"].(string)
86+
assert.True(s.T(), ok, "endpoint should be a string")
87+
88+
dbPort, ok := inputs["database_port"].(int)
89+
assert.True(s.T(), ok, "database_port should be an int")
90+
91+
schemaExistsInRdsInstance := aws.GetWhetherSchemaExistsInRdsPostgresInstance(s.T(), dbUrl, int32(dbPort), adminUsername, adminUserPassword, databaseName)
92+
assert.True(s.T(), schemaExistsInRdsInstance)
93+
94+
schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(s.T(), masterHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
95+
assert.True(s.T(), schemaExistsInRdsInstance)
96+
97+
schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(s.T(), replicasHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
98+
assert.True(s.T(), schemaExistsInRdsInstance)
99+
100+
s.DriftTest(component, stack, &inputs)
101+
}
102+
103+
func (s *ComponentSuite) TestServerless() {
104+
const component = "aurora-postgres/serverless"
105+
const stack = "default-test"
106+
const awsRegion = "us-east-2"
107+
108+
clusterName := strings.ToLower(random.UniqueId())
109+
110+
defer s.DestroyAtmosComponent(s.T(), component, stack, nil)
111+
inputs := map[string]interface{}{
112+
"name": "db",
113+
"database_name": "postgres",
114+
"admin_user": "postgres",
115+
"database_port": 5432,
116+
"publicly_accessible": true,
117+
"allowed_cidr_blocks": []string{"0.0.0.0/0"},
118+
"cluster_name": clusterName,
119+
}
120+
componentInstance, _ := s.DeployAtmosComponent(s.T(), component, stack, &inputs)
121+
assert.NotNil(s.T(), componentInstance)
122+
123+
databaseName := atmos.Output(s.T(), componentInstance, "database_name")
124+
assert.Equal(s.T(), "postgres", databaseName)
125+
126+
adminUsername := atmos.Output(s.T(), componentInstance, "admin_username")
127+
assert.Equal(s.T(), "postgres", adminUsername)
128+
129+
delegatedDnsOptions := s.GetAtmosOptions("dns-delegated", stack, nil)
130+
delegatedDomainName := atmos.Output(s.T(), delegatedDnsOptions, "default_domain_name")
131+
delegatedDomainNZoneId := atmos.Output(s.T(), delegatedDnsOptions, "default_dns_zone_id")
132+
133+
masterHostname := atmos.Output(s.T(), componentInstance, "master_hostname")
134+
expectedMasterHostname := fmt.Sprintf("%s-%s-writer.%s", inputs["name"], componentInstance.Vars["cluster_name"], delegatedDomainName)
135+
assert.Equal(s.T(), expectedMasterHostname, masterHostname)
136+
137+
ssmKeyPaths := atmos.OutputList(s.T(), componentInstance, "ssm_key_paths")
138+
assert.Equal(s.T(), 7, len(ssmKeyPaths))
139+
140+
kmsKeyArn := atmos.Output(s.T(), componentInstance, "kms_key_arn")
141+
assert.NotEmpty(s.T(), kmsKeyArn)
142+
143+
allowedSecurityGroups := atmos.OutputList(s.T(), componentInstance, "allowed_security_groups")
144+
assert.Equal(s.T(), 0, len(allowedSecurityGroups))
145+
146+
clusterIdentifier := atmos.Output(s.T(), componentInstance, "cluster_identifier")
147+
148+
configMap := map[string]interface{}{}
149+
atmos.OutputStruct(s.T(), componentInstance, "config_map", &configMap)
150+
151+
assert.Equal(s.T(), clusterIdentifier, configMap["cluster"])
152+
assert.Equal(s.T(), databaseName, configMap["database"])
153+
assert.Equal(s.T(), masterHostname, configMap["hostname"])
154+
assert.EqualValues(s.T(), inputs["database_port"], configMap["port"])
155+
assert.Equal(s.T(), adminUsername, configMap["username"])
156+
157+
masterHostnameDNSRecord := aws.GetRoute53Record(s.T(), delegatedDomainNZoneId, masterHostname, "CNAME", awsRegion)
158+
assert.Equal(s.T(), *masterHostnameDNSRecord.ResourceRecords[0].Value, configMap["endpoint"])
159+
160+
passwordSSMKey, ok := configMap["password_ssm_key"].(string)
161+
assert.True(s.T(), ok, "password_ssm_key should be a string")
162+
163+
adminUserPassword := aws.GetParameter(s.T(), awsRegion, passwordSSMKey)
164+
165+
dbUrl, ok := configMap["endpoint"].(string)
166+
assert.True(s.T(), ok, "endpoint should be a string")
167+
168+
dbPort, ok := inputs["database_port"].(int)
169+
assert.True(s.T(), ok, "database_port should be an int")
170+
171+
schemaExistsInRdsInstance := aws.GetWhetherSchemaExistsInRdsPostgresInstance(s.T(), dbUrl, int32(dbPort), adminUsername, adminUserPassword, databaseName)
172+
assert.True(s.T(), schemaExistsInRdsInstance)
173+
174+
schemaExistsInRdsInstance = aws.GetWhetherSchemaExistsInRdsPostgresInstance(s.T(), masterHostname, int32(dbPort), adminUsername, adminUserPassword, databaseName)
175+
assert.True(s.T(), schemaExistsInRdsInstance)
176+
177+
s.DriftTest(component, stack, &inputs)
178+
}
179+
180+
func (s *ComponentSuite) TestDisabled() {
181+
const component = "aurora-postgres/disabled"
182+
const stack = "default-test"
183+
const awsRegion = "us-east-2"
184+
185+
s.VerifyEnabledFlag(component, stack, nil)
186+
}
187+
188+
func TestRunSuite(t *testing.T) {
189+
suite := new(ComponentSuite)
190+
191+
suite.AddDependency(t, "vpc", "default-test", nil)
192+
193+
subdomain := strings.ToLower(random.UniqueId())
194+
inputs := map[string]interface{}{
195+
"zone_config": []map[string]interface{}{
196+
{
197+
"subdomain": subdomain,
198+
"zone_name": "components.cptest.test-automation.app",
199+
},
200+
},
201+
}
202+
suite.AddDependency(t, "dns-delegated", "default-test", &inputs)
203+
helper.Run(t, suite)
204+
}

test/fixtures/atmos.yaml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# CLI config is loaded from the following locations (from lowest to highest priority):
2+
# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows)
3+
# home dir (~/.atmos)
4+
# current directory
5+
# ENV vars
6+
# Command-line arguments
7+
#
8+
# It supports POSIX-style Globs for file names/paths (double-star `**` is supported)
9+
# https://en.wikipedia.org/wiki/Glob_(programming)
10+
11+
# Base path for components, stacks and workflows configurations.
12+
# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument.
13+
# Supports both absolute and relative paths.
14+
# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
15+
# are independent settings (supporting both absolute and relative paths).
16+
# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path`
17+
# are considered paths relative to `base_path`.
18+
base_path: ""
19+
20+
components:
21+
terraform:
22+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument
23+
# Supports both absolute and relative paths
24+
base_path: "components/terraform"
25+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var
26+
apply_auto_approve: true
27+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument
28+
deploy_run_init: true
29+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument
30+
init_run_reconfigure: true
31+
# Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument
32+
auto_generate_backend_file: true
33+
34+
stacks:
35+
# Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments
36+
# Supports both absolute and relative paths
37+
base_path: "stacks"
38+
# Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string)
39+
# Since we are distinguishing stacks based on namespace, and namespace is not part
40+
# of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile
41+
included_paths:
42+
- "orgs/**/*"
43+
44+
# Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string)
45+
excluded_paths:
46+
- "**/_defaults.yaml"
47+
48+
# Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var
49+
name_pattern: "{tenant}-{stage}"
50+
51+
workflows:
52+
# Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments
53+
# Supports both absolute and relative paths
54+
base_path: "stacks/workflows"
55+
56+
# https://github.com/cloudposse/atmos/releases/tag/v1.33.0
57+
logs:
58+
file: "/dev/stdout"
59+
# Supported log levels: Trace, Debug, Info, Warning, Off
60+
level: Info
61+
62+
settings:
63+
# Can also be set using 'ATMOS_SETTINGS_LIST_MERGE_STRATEGY' environment variable, or '--settings-list-merge-strategy' command-line argument
64+
list_merge_strategy: replace
65+
66+
# `Go` templates in Atmos manifests
67+
# https://atmos.tools/core-concepts/stacks/templating
68+
# https://pkg.go.dev/text/template
69+
templates:
70+
settings:
71+
enabled: true
72+
# https://masterminds.github.io/sprig
73+
sprig:
74+
enabled: true
75+
# https://docs.gomplate.ca
76+
gomplate:
77+
enabled: true

0 commit comments

Comments
 (0)