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