github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/test/gcp/terraform_gcp_example_test.go (about) 1 // +build gcp 2 3 // NOTE: We use build tags to differentiate GCP testing for better isolation and parallelism when executing our tests. 4 5 package test 6 7 import ( 8 "fmt" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/gruntwork-io/terratest/modules/gcp" 14 "github.com/gruntwork-io/terratest/modules/random" 15 "github.com/gruntwork-io/terratest/modules/retry" 16 "github.com/gruntwork-io/terratest/modules/ssh" 17 "github.com/gruntwork-io/terratest/modules/terraform" 18 test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 19 "github.com/stretchr/testify/assert" 20 ) 21 22 func TestTerraformGcpExample(t *testing.T) { 23 t.Parallel() 24 25 exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/terraform-gcp-example") 26 27 // Get the Project Id to use 28 projectId := gcp.GetGoogleProjectIDFromEnvVar(t) 29 30 // Create all resources in the following zone 31 zone := "us-east1-b" 32 33 // Give the example bucket a unique name so we can distinguish it from any other bucket in your GCP account 34 expectedBucketName := fmt.Sprintf("terratest-gcp-example-%s", strings.ToLower(random.UniqueId())) 35 36 // Also give the example instance a unique name 37 expectedInstanceName := fmt.Sprintf("terratest-gcp-example-%s", strings.ToLower(random.UniqueId())) 38 39 // website::tag::1::Configure Terraform setting path to Terraform code, bucket name, and instance name. Construct 40 // the terraform options with default retryable errors to handle the most common retryable errors in terraform 41 // testing. 42 terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 43 // The path to where our Terraform code is located 44 TerraformDir: exampleDir, 45 46 // Variables to pass to our Terraform code using -var options 47 Vars: map[string]interface{}{ 48 "gcp_project_id": projectId, 49 "zone": zone, 50 "instance_name": expectedInstanceName, 51 "bucket_name": expectedBucketName, 52 }, 53 }) 54 55 // website::tag::5::At the end of the test, run `terraform destroy` to clean up any resources that were created 56 defer terraform.Destroy(t, terraformOptions) 57 58 // website::tag::2::This will run `terraform init` and `terraform apply` and fail the test if there are any errors 59 terraform.InitAndApply(t, terraformOptions) 60 61 // Run `terraform output` to get the value of some of the output variables 62 bucketURL := terraform.Output(t, terraformOptions, "bucket_url") 63 instanceName := terraform.Output(t, terraformOptions, "instance_name") 64 65 // website::tag::3::Verify that the new bucket url matches the expected url 66 expectedURL := fmt.Sprintf("gs://%s", expectedBucketName) 67 assert.Equal(t, expectedURL, bucketURL) 68 69 // Verify that the Storage Bucket exists 70 gcp.AssertStorageBucketExists(t, expectedBucketName) 71 72 // Add a tag to the Compute Instance 73 instance := gcp.FetchInstance(t, projectId, instanceName) 74 instance.SetLabels(t, map[string]string{"testing": "testing-tag-value2"}) 75 76 // Check for the labels within a retry loop as it can sometimes take a while for the 77 // changes to propagate. 78 maxRetries := 12 79 timeBetweenRetries := 5 * time.Second 80 expectedText := "testing-tag-value2" 81 82 // website::tag::4::Check if the GCP instance contains a given tag. 83 retry.DoWithRetry(t, fmt.Sprintf("Checking Instance %s for labels", instanceName), maxRetries, timeBetweenRetries, func() (string, error) { 84 // Look up the tags for the given Instance ID 85 instance := gcp.FetchInstance(t, projectId, instanceName) 86 instanceLabels := instance.GetLabels(t) 87 88 testingTag, containsTestingTag := instanceLabels["testing"] 89 actualText := strings.TrimSpace(testingTag) 90 if !containsTestingTag { 91 return "", fmt.Errorf("Expected the tag 'testing' to exist") 92 } 93 94 if actualText != expectedText { 95 return "", fmt.Errorf("Expected GetLabelsForComputeInstanceE to return '%s' but got '%s'", expectedText, actualText) 96 } 97 98 return "", nil 99 }) 100 } 101 102 // Create a Compute Instance, and attempt to SSH in and run a command. 103 func TestSshAccessToComputeInstance(t *testing.T) { 104 t.Parallel() 105 106 exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/terraform-gcp-example") 107 108 // Setup values for our Terraform apply 109 projectID := gcp.GetGoogleProjectIDFromEnvVar(t) 110 randomValidGcpName := gcp.RandomValidGcpName() 111 // On October 22, 2018, GCP launched the asia-east2 region, which promptly failed all our tests, so blacklist asia-east2. 112 zone := gcp.GetRandomZone(t, projectID, nil, nil, []string{"asia-east2"}) 113 114 terraformOptions := &terraform.Options{ 115 // The path to where our Terraform code is located 116 TerraformDir: exampleDir, 117 118 // Variables to pass to our Terraform code using -var options 119 Vars: map[string]interface{}{ 120 "gcp_project_id": projectID, 121 "instance_name": randomValidGcpName, 122 "bucket_name": randomValidGcpName, 123 "zone": zone, 124 }, 125 } 126 127 // At the end of the test, run `terraform destroy` to clean up any resources that were created 128 defer terraform.Destroy(t, terraformOptions) 129 130 // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 131 terraform.InitAndApply(t, terraformOptions) 132 133 // Run `terraform output` to get the value of an output variable 134 publicIp := terraform.Output(t, terraformOptions, "public_ip") 135 136 // Attempt to SSH and execute the command 137 instance := gcp.FetchInstance(t, projectID, randomValidGcpName) 138 139 sampleText := "Hello World" 140 sshUsername := "terratest" 141 142 keyPair := ssh.GenerateRSAKeyPair(t, 2048) 143 instance.AddSshKey(t, sshUsername, keyPair.PublicKey) 144 145 host := ssh.Host{ 146 Hostname: publicIp, 147 SshKeyPair: keyPair, 148 SshUserName: sshUsername, 149 } 150 151 maxRetries := 20 152 sleepBetweenRetries := 3 * time.Second 153 154 retry.DoWithRetry(t, "Attempting to SSH", maxRetries, sleepBetweenRetries, func() (string, error) { 155 output, err := ssh.CheckSshCommandE(t, host, fmt.Sprintf("echo '%s'", sampleText)) 156 if err != nil { 157 return "", err 158 } 159 160 if strings.TrimSpace(sampleText) != strings.TrimSpace(output) { 161 return "", fmt.Errorf("Expected: %s. Got: %s\n", sampleText, output) 162 } 163 164 return "", nil 165 }) 166 }