Skip to content

Commit 1079f62

Browse files
committed
Added tests
1 parent 4bc7180 commit 1079f62

20 files changed

+1061
-5
lines changed

src/outputs.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ output "additional_schemas" {
1616
output "additional_grants" {
1717
value = keys(module.additional_grants)
1818
description = "Additional grants"
19-
}
19+
}

src/remote-state.tf

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

55
component = var.aurora_postgres_component_name
66

test/.gitignore

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

test/component_test.go

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
package test
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
9+
"github.com/cloudposse/test-helpers/pkg/atmos"
10+
helper "github.com/cloudposse/test-helpers/pkg/atmos/aws-component-helper"
11+
"github.com/gruntwork-io/terratest/modules/aws"
12+
"github.com/gruntwork-io/terratest/modules/random"
13+
"github.com/stretchr/testify/assert"
14+
"github.com/stretchr/testify/require"
15+
)
16+
17+
func TestComponent(t *testing.T) {
18+
t.Parallel()
19+
// Define the AWS region to use for the tests
20+
awsRegion := "us-east-2"
21+
22+
// Initialize the test fixture
23+
fixture := helper.NewFixture(t, "../", awsRegion, "test/fixtures")
24+
25+
// Ensure teardown is executed after the test
26+
defer fixture.TearDown()
27+
fixture.SetUp(&atmos.Options{})
28+
29+
// Define the test suite
30+
fixture.Suite("default", func(t *testing.T, suite *helper.Suite) {
31+
// t.Parallel()
32+
suite.AddDependency("vpc", "default-test")
33+
34+
// Setup phase: Create DNS zones and postgresql for testing
35+
suite.Setup(t, func(t *testing.T, atm *helper.Atmos) {
36+
// Deploy the delegated DNS zone
37+
inputs := map[string]interface{}{
38+
"zone_config": []map[string]interface{}{
39+
{
40+
"subdomain": suite.GetRandomIdentifier(),
41+
"zone_name": "components.cptest.test-automation.app",
42+
},
43+
},
44+
}
45+
atm.GetAndDeploy("dns-delegated", "default-test", inputs)
46+
atm.GetAndDeploy("aurora-postgres", "default-test", map[string]interface{}{
47+
"cluster_name": suite.GetRandomIdentifier(),
48+
})
49+
})
50+
51+
// Teardown phase: Destroy the DNS zones and postgresql created during setup
52+
suite.TearDown(t, func(t *testing.T, atm *helper.Atmos) {
53+
atm.GetAndDestroy("aurora-postgres", "default-test", map[string]interface{}{})
54+
// Deploy the delegated DNS zone
55+
inputs := map[string]interface{}{
56+
"zone_config": []map[string]interface{}{
57+
{
58+
"subdomain": suite.GetRandomIdentifier(),
59+
"zone_name": "components.cptest.test-automation.app",
60+
},
61+
},
62+
}
63+
atm.GetAndDestroy("dns-delegated", "default-test", inputs)
64+
})
65+
66+
// Test phase: Validate the functionality of the component
67+
suite.Test(t, "database", func(t *testing.T, atm *helper.Atmos) {
68+
databaseName := strings.ToLower(random.UniqueId())
69+
70+
inputs := map[string]interface{}{
71+
"additional_databases": []string{databaseName},
72+
}
73+
74+
defer atm.GetAndDestroy("aurora-postgres-resources/database", "default-test", inputs)
75+
component := atm.GetAndDeploy("aurora-postgres-resources/database", "default-test", inputs)
76+
assert.NotNil(t, component)
77+
78+
clusterComponent := helper.NewAtmosComponent("aurora-postgres", "default-test", map[string]interface{}{})
79+
configMap := map[string]interface{}{}
80+
atm.OutputStruct(clusterComponent, "config_map", &configMap)
81+
82+
passwordSSMKey, ok := configMap["password_ssm_key"].(string)
83+
assert.True(t, ok, "password_ssm_key should be a string")
84+
85+
adminUsername, ok := configMap["username"].(string)
86+
assert.True(t, ok, "username should be an string")
87+
88+
adminUserPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)
89+
90+
dbUrl, ok := configMap["hostname"].(string)
91+
assert.True(t, ok, "hostname should be a string")
92+
93+
dbPort, ok := configMap["port"].(float64)
94+
assert.True(t, ok, "database_port should be an int")
95+
96+
schemaExistsInRdsInstance := GetWhetherDatabaseExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), adminUsername, adminUserPassword, databaseName)
97+
assert.True(t, schemaExistsInRdsInstance)
98+
})
99+
100+
suite.Test(t, "schema", func(t *testing.T, atm *helper.Atmos) {
101+
schemaName := strings.ToLower(random.UniqueId())
102+
inputs := map[string]interface{}{
103+
"additional_schemas": map[string]interface{}{
104+
schemaName: map[string]interface{}{
105+
"database": "postgres",
106+
},
107+
},
108+
}
109+
defer atm.GetAndDestroy("aurora-postgres-resources/schema", "default-test", inputs)
110+
component := atm.GetAndDeploy("aurora-postgres-resources/schema", "default-test", inputs)
111+
assert.NotNil(t, component)
112+
113+
clusterComponent := helper.NewAtmosComponent("aurora-postgres", "default-test", map[string]interface{}{})
114+
configMap := map[string]interface{}{}
115+
atm.OutputStruct(clusterComponent, "config_map", &configMap)
116+
117+
passwordSSMKey, ok := configMap["password_ssm_key"].(string)
118+
assert.True(t, ok, "password_ssm_key should be a string")
119+
120+
adminUsername, ok := configMap["username"].(string)
121+
assert.True(t, ok, "username should be an string")
122+
123+
adminUserPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)
124+
125+
dbUrl, ok := configMap["hostname"].(string)
126+
assert.True(t, ok, "hostname should be a string")
127+
128+
dbPort, ok := configMap["port"].(float64)
129+
assert.True(t, ok, "database_port should be an int")
130+
131+
schemaExistsInRdsInstance := GetWhetherSchemaExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), adminUsername, adminUserPassword, "postgres", schemaName)
132+
assert.True(t, schemaExistsInRdsInstance)
133+
})
134+
135+
suite.Test(t, "user", func(t *testing.T, atm *helper.Atmos) {
136+
userName := strings.ToLower(random.UniqueId())
137+
serviceName := strings.ToLower(random.UniqueId())
138+
inputs := map[string]interface{}{
139+
"additional_users": map[string]interface{}{
140+
serviceName: map[string]interface{}{
141+
"db_user": userName,
142+
"db_password": "",
143+
"grants": []map[string]interface{}{
144+
{
145+
"grant": []string{"ALL"},
146+
"db": "postgres",
147+
"object_type": "database",
148+
"schema": "",
149+
},
150+
},
151+
},
152+
},
153+
}
154+
defer atm.GetAndDestroy("aurora-postgres-resources/user", "default-test", inputs)
155+
component := atm.GetAndDeploy("aurora-postgres-resources/user", "default-test", inputs)
156+
assert.NotNil(t, component)
157+
158+
clusterComponent := helper.NewAtmosComponent("aurora-postgres", "default-test", map[string]interface{}{})
159+
configMap := map[string]interface{}{}
160+
atm.OutputStruct(clusterComponent, "config_map", &configMap)
161+
162+
clusterIdenitfier := atm.Output(clusterComponent, "cluster_identifier")
163+
164+
passwordSSMKey := fmt.Sprintf("/aurora-postgres/%s/%s/passwords/%s", clusterIdenitfier, serviceName, userName)
165+
userPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)
166+
167+
dbUrl, ok := configMap["hostname"].(string)
168+
assert.True(t, ok, "hostname should be a string")
169+
170+
dbPort, ok := configMap["port"].(float64)
171+
assert.True(t, ok, "database_port should be an int")
172+
173+
schemaExistsInRdsInstance := GetWhetherDatabaseExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), userName, userPassword, "postgres")
174+
assert.True(t, schemaExistsInRdsInstance)
175+
})
176+
177+
suite.Test(t, "grant", func(t *testing.T, atm *helper.Atmos) {
178+
t.Skip("Additional grants not working. Read more https://github.com/cloudposse-terraform-components/aws-aurora-postgres-resources/issues/17")
179+
userName := strings.ToLower(random.UniqueId())
180+
serviceName := strings.ToLower(random.UniqueId())
181+
inputs := map[string]interface{}{
182+
"additional_users": map[string]interface{}{
183+
serviceName: map[string]interface{}{
184+
"db_user": userName,
185+
"db_password": "",
186+
"grants": []map[string]interface{}{},
187+
},
188+
},
189+
}
190+
defer atm.GetAndDestroy("aurora-postgres-resources/grant", "default-test", inputs)
191+
component := atm.GetAndDeploy("aurora-postgres-resources/grant", "default-test", inputs)
192+
assert.NotNil(t, component)
193+
194+
clusterComponent := helper.NewAtmosComponent("aurora-postgres", "default-test", map[string]interface{}{})
195+
configMap := map[string]interface{}{}
196+
atm.OutputStruct(clusterComponent, "config_map", &configMap)
197+
198+
clusterIdenitfier := atm.Output(clusterComponent, "cluster_identifier")
199+
200+
passwordSSMKey := fmt.Sprintf("/aurora-postgres/%s/%s/passwords/%s", clusterIdenitfier, serviceName, userName)
201+
userPassword := aws.GetParameter(t, awsRegion, passwordSSMKey)
202+
203+
dbUrl, ok := configMap["hostname"].(string)
204+
assert.True(t, ok, "hostname should be a string")
205+
206+
dbPort, ok := configMap["port"].(float64)
207+
assert.True(t, ok, "database_port should be an int")
208+
209+
component.Vars["additional_grants"] = map[string]interface{}{
210+
userName: []map[string]interface{}{
211+
{
212+
"grant": []string{"ALL"},
213+
"db": "postgres",
214+
},
215+
},
216+
}
217+
218+
atm.Deploy(component)
219+
220+
grantsExistsInRdsInstance := GetWhetherGrantsExistsInRdsPostgresInstance(t, dbUrl, int32(dbPort), userName, userPassword, "postgres", "public")
221+
assert.True(t, grantsExistsInRdsInstance)
222+
})
223+
224+
})
225+
}
226+
227+
func GetWhetherDatabaseExistsInRdsPostgresInstance(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string) bool {
228+
output, err := GetWhetherDatabaseExistsInRdsPostgresInstanceE(t, dbUrl, dbPort, dbUsername, dbPassword, databaseName)
229+
require.NoError(t, err)
230+
return output
231+
}
232+
233+
func GetWhetherDatabaseExistsInRdsPostgresInstanceE(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string) (bool, error) {
234+
connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", dbUrl, dbPort, dbUsername, dbPassword, databaseName)
235+
236+
db, connErr := sql.Open("pgx", connectionString)
237+
if connErr != nil {
238+
return false, connErr
239+
}
240+
defer db.Close()
241+
return true, nil
242+
}
243+
244+
func GetWhetherSchemaExistsInRdsPostgresInstance(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string, expectedSchemaName string) bool {
245+
output, err := GetWhetherSchemaExistsInRdsPostgresInstanceE(t, dbUrl, dbPort, dbUsername, dbPassword, databaseName, expectedSchemaName)
246+
if err != nil {
247+
t.Fatal(err)
248+
}
249+
return output
250+
}
251+
252+
func GetWhetherSchemaExistsInRdsPostgresInstanceE(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string, expectedSchemaName string) (bool, error) {
253+
connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", dbUrl, dbPort, dbUsername, dbPassword, databaseName)
254+
255+
db, connErr := sql.Open("pgx", connectionString)
256+
if connErr != nil {
257+
return false, connErr
258+
}
259+
defer db.Close()
260+
var (
261+
schemaName string
262+
)
263+
sqlStatement := `SELECT "schema_name" FROM "information_schema"."schemata" where schema_name=$1`
264+
row := db.QueryRow(sqlStatement, expectedSchemaName)
265+
scanErr := row.Scan(&schemaName)
266+
if scanErr != nil {
267+
return false, scanErr
268+
}
269+
return true, nil
270+
}
271+
272+
func GetWhetherGrantsExistsInRdsPostgresInstance(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string, expectedSchemaName string) bool {
273+
output, err := GetWhetherGrantsExistsInRdsPostgresInstanceE(t, dbUrl, dbPort, dbUsername, dbPassword, databaseName, expectedSchemaName)
274+
if err != nil {
275+
t.Fatal(err)
276+
}
277+
return output
278+
}
279+
280+
func GetWhetherGrantsExistsInRdsPostgresInstanceE(t *testing.T, dbUrl string, dbPort int32, dbUsername string, dbPassword string, databaseName string, expectedSchemaName string) (bool, error) {
281+
connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", dbUrl, dbPort, dbUsername, dbPassword, databaseName)
282+
283+
db, connErr := sql.Open("pgx", connectionString)
284+
if connErr != nil {
285+
return false, connErr
286+
}
287+
defer db.Close()
288+
var (
289+
schemaName string
290+
)
291+
sqlStatement := `SELECT grantee AS user, CONCAT(table_schema, '.', table_name) AS table,
292+
CASE
293+
WHEN COUNT(privilege_type) = 7 THEN 'ALL'
294+
ELSE ARRAY_TO_STRING(ARRAY_AGG(privilege_type), ', ')
295+
END AS grants
296+
FROM information_schema.role_table_grants
297+
WHERE grantee = '$1'
298+
GROUP BY table_name, table_schema, grantee;`
299+
row := db.QueryRow(sqlStatement, dbUsername)
300+
scanErr := row.Scan(&schemaName)
301+
if scanErr != nil {
302+
return false, scanErr
303+
}
304+
return true, nil
305+
}

0 commit comments

Comments
 (0)