diff --git a/.github/workflows/terratest.yml b/.github/workflows/terratest.yml index ecbdc1f..3597d83 100644 --- a/.github/workflows/terratest.yml +++ b/.github/workflows/terratest.yml @@ -25,30 +25,45 @@ env: TF_VAR_google_credentials: ${{ secrets.TERRATEST_GOOGLE_CREDENTIALS }} TF_VAR_shared_vpc_host_google_credentials: ${{ secrets.TERRATEST_GOOGLE_CREDENTIALS }} TF_VAR_google_region: ${{ secrets.TERRATEST_GOOGLE_REGION }} + jobs: terratest: - name: terratest + name: Terratest runs-on: ubuntu-latest + steps: - name: Check out code into the Go module directory - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Updated to latest version with: submodules: true - - name: Set up Go (1.17) - uses: actions/setup-go@v2 + + - name: Cache Go modules + uses: actions/cache@v3 # Use caching to speed up Go modules installation + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Set up Go (1.21) + uses: actions/setup-go@v4 # Updated to latest version with: - go-version: 1.17 - id: go + go-version: 1.21 + - name: Login to Google Cloud - uses: google-github-actions/auth@v0 + uses: google-github-actions/auth@v2 # Updated to latest version with: credentials_json: ${{ env.TERRATEST_GOOGLE_CREDENTIALS }} - name: Set Google Cloud project - run: gcloud config set project $GOOGLE_PROJECT - - name: Run terratest + run: gcloud config set project ${{ env.GOOGLE_PROJECT }} + + - name: Run Terratest run: | make tests + - name: Release uses: cycjimmy/semantic-release-action@v3 env: @@ -58,3 +73,7 @@ jobs: @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @semantic-release/changelog@6.0.1 + + - name: Clear GCloud Config + if: always() + run: gcloud config unset project diff --git a/test/gcp_sql_test.go b/test/gcp_sql_test.go index 02a76a8..dbdc0f3 100644 --- a/test/gcp_sql_test.go +++ b/test/gcp_sql_test.go @@ -1,14 +1,174 @@ +// package test +// +// import ( +// +// "strings" +// "testing" +// +// "github.com/gruntwork-io/terratest/modules/terraform" +// test_structure "github.com/gruntwork-io/terratest/modules/test-structure" +// "github.com/stretchr/testify/assert" +// +// ) +// +// func TestTerraformCreateGCPSQL(t *testing.T) { +// t.Parallel() +// +// t.Run("create mysql with read replica", func(t *testing.T) { +// t.Parallel() +// +// testDirectory := test_structure.CopyTerraformFolderToTemp(t, "..", "examples/mysql_instance_with_read_replica") +// +// // retryable errors in terraform testing. +// terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ +// TerraformDir: testDirectory, +// }) +// +// defer terraform.Destroy(t, terraformOptions) +// +// terraform.InitAndApply(t, terraformOptions) +// +// var output string +// +// output = terraform.Output(t, terraformOptions, "random_string") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_instance_name") +// assert.Contains(t, output, "sql-rr") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_self_link") +// assert.Contains(t, output, "sql-rr") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_instance_name") +// assert.Contains(t, output, "sql-rr") +// assert.Contains(t, output, "-read-replica") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_self_link") +// assert.Contains(t, output, "sql-rr") +// assert.Contains(t, output, "-read-replica") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_service_account_email_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_connection_name") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_user_name") +// assert.Equal(t, output, "sql-user") +// +// output = terraform.Output(t, terraformOptions, "sql_database_master_id") +// assert.Contains(t, output, "db-first") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_public_ip_address") +// assert.Empty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_private_ip_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_public_ip_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_private_ip_address") +// assert.NotEmpty(t, output) +// }) +// +// t.Run("create PostgreSQL with read replica", func(t *testing.T) { +// t.Parallel() +// +// testDirectory := test_structure.CopyTerraformFolderToTemp(t, "..", "examples/postgres_instance_with_read_replica") +// +// // retryable errors in terraform testing. +// terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ +// TerraformDir: testDirectory, +// }) +// +// defer terraform.Destroy(t, terraformOptions) +// +// terraform.InitAndApply(t, terraformOptions) +// +// var output string +// +// output = terraform.Output(t, terraformOptions, "random_string") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_instance_name") +// assert.Contains(t, output, "sql-rr") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_self_link") +// assert.Contains(t, output, "sql-rr") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_instance_name") +// assert.Contains(t, output, "sql-rr") +// assert.Contains(t, output, "-read-replica") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_self_link") +// assert.Contains(t, output, "sql-rr") +// assert.Contains(t, output, "-read-replica") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_service_account_email_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_connection_name") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_user_name") +// assert.Equal(t, output, "sql-user") +// +// output = terraform.Output(t, terraformOptions, "sql_database_master_id") +// assert.Contains(t, output, "db-first") +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_public_ip_address") +// assert.Empty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_master_private_ip_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_public_ip_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "sql_database_instance_read_replica_private_ip_address") +// assert.NotEmpty(t, output) +// +// output = terraform.Output(t, terraformOptions, "database_version") +// assert.True(t, strings.HasPrefix(output, "POSTGRES_")) +// }) +// } package test import ( + "errors" "strings" "testing" + "time" "github.com/gruntwork-io/terratest/modules/terraform" test_structure "github.com/gruntwork-io/terratest/modules/test-structure" "github.com/stretchr/testify/assert" ) +const ( + maxRetries = 3 + retryInterval = 10 * time.Second +) + +func retryTerraformApply(t *testing.T, terraformOptions *terraform.Options) error { + var err error + for i := 0; i < maxRetries; i++ { + // Run terraform.InitAndApply and check for an empty string indicating success + output := terraform.InitAndApply(t, terraformOptions) + if output == "" { + return nil // Success, no error + } + // Convert output to error + err = errors.New(output) + t.Logf("Retry %d/%d: Terraform apply failed with output: %s", i+1, maxRetries, output) + + // Wait before retrying + time.Sleep(retryInterval) + } + return err // Return the last error encountered +} + func TestTerraformCreateGCPSQL(t *testing.T) { t.Parallel() @@ -17,14 +177,14 @@ func TestTerraformCreateGCPSQL(t *testing.T) { testDirectory := test_structure.CopyTerraformFolderToTemp(t, "..", "examples/mysql_instance_with_read_replica") - // retryable errors in terraform testing. terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ TerraformDir: testDirectory, }) defer terraform.Destroy(t, terraformOptions) - terraform.InitAndApply(t, terraformOptions) + err := retryTerraformApply(t, terraformOptions) + assert.NoError(t, err, "Terraform apply failed after multiple retries") var output string @@ -75,14 +235,14 @@ func TestTerraformCreateGCPSQL(t *testing.T) { testDirectory := test_structure.CopyTerraformFolderToTemp(t, "..", "examples/postgres_instance_with_read_replica") - // retryable errors in terraform testing. terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ TerraformDir: testDirectory, }) defer terraform.Destroy(t, terraformOptions) - terraform.InitAndApply(t, terraformOptions) + err := retryTerraformApply(t, terraformOptions) + assert.NoError(t, err, "Terraform apply failed after multiple retries") var output string