github.com/kcburge/terraform@v0.11.12-beta1/backend/remote-state/azure/backend_test.go (about) 1 package azure 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 8 "github.com/Azure/azure-sdk-for-go/arm/resources/resources" 9 armStorage "github.com/Azure/azure-sdk-for-go/arm/storage" 10 "github.com/Azure/azure-sdk-for-go/storage" 11 "github.com/Azure/go-autorest/autorest" 12 "github.com/Azure/go-autorest/autorest/adal" 13 "github.com/Azure/go-autorest/autorest/azure" 14 "github.com/hashicorp/terraform/backend" 15 "github.com/hashicorp/terraform/helper/acctest" 16 ) 17 18 // verify that we are doing ACC tests or the Azure tests specifically 19 func testACC(t *testing.T) { 20 skip := os.Getenv("TF_ACC") == "" && os.Getenv("TF_AZURE_TEST") == "" 21 if skip { 22 t.Log("azure backend tests require setting TF_ACC or TF_AZURE_TEST") 23 t.Skip() 24 } 25 } 26 27 func TestBackend_impl(t *testing.T) { 28 var _ backend.Backend = new(Backend) 29 } 30 31 func TestBackendConfig(t *testing.T) { 32 // This test just instantiates the client. Shouldn't make any actual 33 // requests nor incur any costs. 34 35 config := map[string]interface{}{ 36 "storage_account_name": "tfaccount", 37 "container_name": "tfcontainer", 38 "key": "state", 39 // Access Key must be Base64 40 "access_key": "QUNDRVNTX0tFWQ0K", 41 } 42 43 b := backend.TestBackendConfig(t, New(), config).(*Backend) 44 45 if b.containerName != "tfcontainer" { 46 t.Fatalf("Incorrect bucketName was populated") 47 } 48 if b.keyName != "state" { 49 t.Fatalf("Incorrect keyName was populated") 50 } 51 } 52 53 func TestBackend(t *testing.T) { 54 testACC(t) 55 56 keyName := "testState" 57 res := setupResources(t, keyName) 58 defer destroyResources(t, res.resourceGroupName) 59 60 b := backend.TestBackendConfig(t, New(), map[string]interface{}{ 61 "storage_account_name": res.storageAccountName, 62 "container_name": res.containerName, 63 "key": keyName, 64 "access_key": res.accessKey, 65 }).(*Backend) 66 67 backend.TestBackendStates(t, b) 68 } 69 70 func TestBackendLocked(t *testing.T) { 71 testACC(t) 72 73 keyName := "testState" 74 res := setupResources(t, keyName) 75 defer destroyResources(t, res.resourceGroupName) 76 77 b1 := backend.TestBackendConfig(t, New(), map[string]interface{}{ 78 "storage_account_name": res.storageAccountName, 79 "container_name": res.containerName, 80 "key": keyName, 81 "access_key": res.accessKey, 82 }).(*Backend) 83 84 b2 := backend.TestBackendConfig(t, New(), map[string]interface{}{ 85 "storage_account_name": res.storageAccountName, 86 "container_name": res.containerName, 87 "key": keyName, 88 "access_key": res.accessKey, 89 }).(*Backend) 90 91 backend.TestBackendStateLocks(t, b1, b2) 92 backend.TestBackendStateForceUnlock(t, b1, b2) 93 } 94 95 type testResources struct { 96 resourceGroupName string 97 storageAccountName string 98 containerName string 99 keyName string 100 accessKey string 101 } 102 103 func setupResources(t *testing.T, keyName string) testResources { 104 clients := getTestClient(t) 105 106 ri := acctest.RandInt() 107 rs := acctest.RandString(4) 108 res := testResources{ 109 resourceGroupName: fmt.Sprintf("terraform-backend-testing-%d", ri), 110 storageAccountName: fmt.Sprintf("tfbackendtesting%s", rs), 111 containerName: "terraform", 112 keyName: keyName, 113 } 114 115 location := os.Getenv("ARM_LOCATION") 116 if location == "" { 117 location = "westus" 118 } 119 120 t.Logf("creating resource group %s", res.resourceGroupName) 121 _, err := clients.groupsClient.CreateOrUpdate(res.resourceGroupName, resources.Group{Location: &location}) 122 if err != nil { 123 t.Fatalf("failed to create test resource group: %s", err) 124 } 125 126 t.Logf("creating storage account %s", res.storageAccountName) 127 _, createError := clients.storageAccountsClient.Create(res.resourceGroupName, res.storageAccountName, armStorage.AccountCreateParameters{ 128 Sku: &armStorage.Sku{ 129 Name: armStorage.StandardLRS, 130 Tier: armStorage.Standard, 131 }, 132 Location: &location, 133 }, make(chan struct{})) 134 createErr := <-createError 135 if createErr != nil { 136 destroyResources(t, res.resourceGroupName) 137 t.Fatalf("failed to create test storage account: %s", err) 138 } 139 140 t.Log("fetching access key for storage account") 141 resp, err := clients.storageAccountsClient.ListKeys(res.resourceGroupName, res.storageAccountName) 142 if err != nil { 143 destroyResources(t, res.resourceGroupName) 144 t.Fatalf("failed to list storage account keys %s:", err) 145 } 146 147 keys := *resp.Keys 148 res.accessKey = *keys[0].Value 149 150 storageClient, err := storage.NewClient(res.storageAccountName, res.accessKey, 151 clients.environment.StorageEndpointSuffix, storage.DefaultAPIVersion, true) 152 if err != nil { 153 destroyResources(t, res.resourceGroupName) 154 t.Fatalf("failed to list storage account keys %s:", err) 155 } 156 157 t.Logf("creating container %s", res.containerName) 158 blobService := storageClient.GetBlobService() 159 container := blobService.GetContainerReference(res.containerName) 160 err = container.Create(&storage.CreateContainerOptions{}) 161 if err != nil { 162 destroyResources(t, res.resourceGroupName) 163 t.Fatalf("failed to create storage container: %s", err) 164 } 165 166 return res 167 } 168 169 func destroyResources(t *testing.T, resourceGroupName string) { 170 warning := "WARNING: Failed to delete the test Azure resources. They may incur charges. (error was %s)" 171 172 clients := getTestClient(t) 173 174 t.Log("destroying created resources") 175 176 // destroying is simple as deleting the resource group will destroy everything else 177 _, deleteErr := clients.groupsClient.Delete(resourceGroupName, make(chan struct{})) 178 err := <-deleteErr 179 if err != nil { 180 t.Logf(warning, err) 181 return 182 } 183 184 t.Log("Azure resources destroyed") 185 } 186 187 type testClient struct { 188 subscriptionID string 189 tenantID string 190 clientID string 191 clientSecret string 192 environment azure.Environment 193 groupsClient resources.GroupsClient 194 storageAccountsClient armStorage.AccountsClient 195 } 196 197 func getTestClient(t *testing.T) testClient { 198 client := testClient{ 199 subscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"), 200 tenantID: os.Getenv("ARM_TENANT_ID"), 201 clientID: os.Getenv("ARM_CLIENT_ID"), 202 clientSecret: os.Getenv("ARM_CLIENT_SECRET"), 203 } 204 205 if client.subscriptionID == "" || client.tenantID == "" || client.clientID == "" || client.clientSecret == "" { 206 t.Fatal("Azure credentials missing or incomplete") 207 } 208 209 env, err := getAzureEnvironment(os.Getenv("ARM_ENVIRONMENT")) 210 if err != nil { 211 t.Fatalf("Failed to detect Azure environment from ARM_ENVIRONMENT value: %s", os.Getenv("ARM_ENVIRONMENT")) 212 } 213 client.environment = env 214 215 oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, client.tenantID) 216 if err != nil { 217 t.Fatalf("Failed to get OAuth config: %s", err) 218 } 219 220 spt, err := adal.NewServicePrincipalToken(*oauthConfig, client.clientID, client.clientSecret, env.ResourceManagerEndpoint) 221 if err != nil { 222 t.Fatalf("Failed to create Service Principal Token: %s", err) 223 } 224 225 client.groupsClient = resources.NewGroupsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID) 226 client.groupsClient.Authorizer = autorest.NewBearerAuthorizer(spt) 227 228 client.storageAccountsClient = armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID) 229 client.storageAccountsClient.Authorizer = autorest.NewBearerAuthorizer(spt) 230 231 return client 232 }