All in with PG
This commit is contained in:
177
test/example_postgres_replicas_test.go
Normal file
177
test/example_postgres_replicas_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gruntwork-io/terratest/modules/gcp"
|
||||
"github.com/gruntwork-io/terratest/modules/logger"
|
||||
"github.com/gruntwork-io/terratest/modules/terraform"
|
||||
"github.com/gruntwork-io/terratest/modules/test-structure"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const NAME_PREFIX_POSTGRES_REPLICAS = "postgres-replicas"
|
||||
const EXAMPLE_NAME_POSTGRES_REPLICAS = "postgres-replicas"
|
||||
|
||||
func TestPostgresReplicas(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//os.Setenv("SKIP_bootstrap", "true")
|
||||
//os.Setenv("SKIP_deploy", "true")
|
||||
//os.Setenv("SKIP_validate_outputs", "true")
|
||||
//os.Setenv("SKIP_sql_tests", "true")
|
||||
//os.Setenv("SKIP_read_replica_tests", "true")
|
||||
//os.Setenv("SKIP_teardown", "true")
|
||||
|
||||
_examplesDir := test_structure.CopyTerraformFolderToTemp(t, "../", "examples")
|
||||
exampleDir := filepath.Join(_examplesDir, EXAMPLE_NAME_POSTGRES_REPLICAS)
|
||||
|
||||
// BOOTSTRAP VARIABLES FOR THE TESTS
|
||||
test_structure.RunTestStage(t, "bootstrap", func() {
|
||||
projectId := gcp.GetGoogleProjectIDFromEnvVar(t)
|
||||
region := getRandomRegion(t, projectId)
|
||||
|
||||
masterZone, readReplicaZone := getTwoDistinctRandomZonesForRegion(t, projectId, region)
|
||||
|
||||
test_structure.SaveString(t, exampleDir, KEY_REGION, region)
|
||||
test_structure.SaveString(t, exampleDir, KEY_MASTER_ZONE, masterZone)
|
||||
test_structure.SaveString(t, exampleDir, KEY_READ_REPLICA_ZONE, readReplicaZone)
|
||||
test_structure.SaveString(t, exampleDir, KEY_PROJECT, projectId)
|
||||
})
|
||||
|
||||
// AT THE END OF THE TESTS, RUN `terraform destroy`
|
||||
// TO CLEAN UP ANY RESOURCES THAT WERE CREATED
|
||||
defer test_structure.RunTestStage(t, "teardown", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir)
|
||||
terraform.Destroy(t, terraformOptions)
|
||||
})
|
||||
|
||||
test_structure.RunTestStage(t, "deploy", func() {
|
||||
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
|
||||
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
|
||||
masterZone := test_structure.LoadString(t, exampleDir, KEY_MASTER_ZONE)
|
||||
readReplicaZone := test_structure.LoadString(t, exampleDir, KEY_READ_REPLICA_ZONE)
|
||||
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_REPLICAS, masterZone, "", 1, readReplicaZone)
|
||||
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
|
||||
|
||||
terraform.InitAndApply(t, terraformOptions)
|
||||
})
|
||||
|
||||
// VALIDATE MODULE OUTPUTS
|
||||
test_structure.RunTestStage(t, "validate_outputs", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir)
|
||||
|
||||
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
|
||||
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
|
||||
|
||||
instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_INSTANCE_NAME)
|
||||
dbNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_DB_NAME)
|
||||
proxyConnectionFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PROXY_CONNECTION)
|
||||
|
||||
expectedDBConn := fmt.Sprintf("%s:%s:%s", projectId, region, instanceNameFromOutput)
|
||||
|
||||
assert.True(t, strings.HasPrefix(instanceNameFromOutput, NAME_PREFIX_POSTGRES_REPLICAS))
|
||||
assert.Equal(t, DB_NAME, dbNameFromOutput)
|
||||
assert.Equal(t, expectedDBConn, proxyConnectionFromOutput)
|
||||
|
||||
// Read replica outputs
|
||||
readReplicaInstanceNameFromOutputList := terraform.OutputList(t, terraformOptions, OUTPUT_READ_REPLICA_INSTANCE_NAMES)
|
||||
readReplicaProxyConnectionFromOutputList := terraform.OutputList(t, terraformOptions, OUTPUT_READ_REPLICA_PROXY_CONNECTIONS)
|
||||
|
||||
readReplicaInstanceNameFromOutput := readReplicaInstanceNameFromOutputList[0]
|
||||
readReplicaProxyConnectionFromOutput := readReplicaProxyConnectionFromOutputList[0]
|
||||
|
||||
expectedReadReplicaDBConn := fmt.Sprintf("%s:%s:%s", projectId, region, readReplicaInstanceNameFromOutput)
|
||||
|
||||
assert.True(t, strings.HasPrefix(readReplicaInstanceNameFromOutput, NAME_PREFIX_POSTGRES_REPLICAS))
|
||||
assert.Equal(t, expectedReadReplicaDBConn, readReplicaProxyConnectionFromOutput)
|
||||
})
|
||||
|
||||
// TEST REGULAR SQL CLIENT
|
||||
test_structure.RunTestStage(t, "sql_tests", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir)
|
||||
|
||||
publicIp := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PUBLIC_IP)
|
||||
|
||||
connectionString := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", DB_USER, DB_PASS, publicIp, DB_NAME)
|
||||
|
||||
// Does not actually open up the connection - just returns a DB ref
|
||||
logger.Logf(t, "Connecting to: %s", publicIp)
|
||||
db, err := sql.Open("postgres", connectionString)
|
||||
require.NoError(t, err, "Failed to open DB connection")
|
||||
|
||||
// Make sure we clean up properly
|
||||
defer db.Close()
|
||||
|
||||
// Run ping to actually test the connection
|
||||
logger.Log(t, "Ping the DB")
|
||||
if err = db.Ping(); err != nil {
|
||||
t.Fatalf("Failed to ping DB: %v", err)
|
||||
}
|
||||
|
||||
// Create table if not exists
|
||||
logger.Logf(t, "Create table: %s", POSTGRES_CREATE_TEST_TABLE_WITH_SERIAL)
|
||||
if _, err = db.Exec(POSTGRES_CREATE_TEST_TABLE_WITH_SERIAL); err != nil {
|
||||
t.Fatalf("Failed to create table: %v", err)
|
||||
}
|
||||
|
||||
// Clean up
|
||||
logger.Logf(t, "Empty table: %s", SQL_EMPTY_TEST_TABLE_STATEMENT)
|
||||
if _, err = db.Exec(SQL_EMPTY_TEST_TABLE_STATEMENT); err != nil {
|
||||
t.Fatalf("Failed to clean up table: %v", err)
|
||||
}
|
||||
|
||||
logger.Logf(t, "Insert data: %s", POSTGRES_INSERT_TEST_ROW)
|
||||
var testid int
|
||||
err = db.QueryRow(POSTGRES_INSERT_TEST_ROW).Scan(&testid)
|
||||
require.NoError(t, err, "Failed to insert data")
|
||||
|
||||
assert.True(t, testid > 0, "Data was inserted")
|
||||
})
|
||||
|
||||
// TEST READ REPLICA WITH REGULAR SQL CLIENT
|
||||
test_structure.RunTestStage(t, "read_replica_tests", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir)
|
||||
|
||||
readReplicaPublicIpList := terraform.OutputList(t, terraformOptions, OUTPUT_READ_REPLICA_PUBLIC_IPS)
|
||||
readReplicaPublicIp := readReplicaPublicIpList[0]
|
||||
|
||||
connectionString := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", DB_USER, DB_PASS, readReplicaPublicIp, DB_NAME)
|
||||
|
||||
// Does not actually open up the connection - just returns a DB ref
|
||||
logger.Logf(t, "Connecting to: %s", readReplicaPublicIp)
|
||||
db, err := sql.Open("postgres", connectionString)
|
||||
require.NoError(t, err, "Failed to open DB connection")
|
||||
|
||||
// Make sure we clean up properly
|
||||
defer db.Close()
|
||||
|
||||
// Run ping to actually test the connection
|
||||
logger.Log(t, "Ping the DB")
|
||||
if err = db.Ping(); err != nil {
|
||||
t.Fatalf("Failed to ping DB: %v", err)
|
||||
}
|
||||
|
||||
// Try to insert data to verify we cannot write
|
||||
logger.Logf(t, "Insert data: %s", POSTGRES_INSERT_TEST_ROW)
|
||||
var testid int
|
||||
err = db.QueryRow(POSTGRES_INSERT_TEST_ROW).Scan(&testid)
|
||||
|
||||
// This time we actually expect an error:
|
||||
// 'cannot execute INSERT in a read-only transaction'
|
||||
require.Error(t, err, "Should not be able to write to read replica")
|
||||
logger.Logf(t, "Failed to insert data to read replica as expected: %v", err)
|
||||
|
||||
// Query data, results don't matter...
|
||||
logger.Logf(t, "Query r/o data: %s", SQL_QUERY_ROW_COUNT)
|
||||
rows, err := db.Query(SQL_QUERY_ROW_COUNT)
|
||||
require.NoError(t, err, "Failed to execute query statement on read replica")
|
||||
|
||||
assert.True(t, rows.Next(), "We have a result")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user