github.com/pgray/terraform@v0.5.4-0.20170822184730-b6a464c5214d/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.TestBackend(t, b, nil)
    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.TestBackend(t, b1, b2)
    92  }
    93  
    94  type testResources struct {
    95  	resourceGroupName  string
    96  	storageAccountName string
    97  	containerName      string
    98  	keyName            string
    99  	accessKey          string
   100  }
   101  
   102  func setupResources(t *testing.T, keyName string) testResources {
   103  	clients := getTestClient(t)
   104  
   105  	ri := acctest.RandInt()
   106  	rs := acctest.RandString(4)
   107  	res := testResources{
   108  		resourceGroupName:  fmt.Sprintf("terraform-backend-testing-%d", ri),
   109  		storageAccountName: fmt.Sprintf("tfbackendtesting%s", rs),
   110  		containerName:      "terraform",
   111  		keyName:            keyName,
   112  	}
   113  
   114  	location := os.Getenv("ARM_LOCATION")
   115  	if location == "" {
   116  		location = "westus"
   117  	}
   118  
   119  	t.Logf("creating resource group %s", res.resourceGroupName)
   120  	_, err := clients.groupsClient.CreateOrUpdate(res.resourceGroupName, resources.Group{Location: &location})
   121  	if err != nil {
   122  		t.Fatalf("failed to create test resource group: %s", err)
   123  	}
   124  
   125  	t.Logf("creating storage account %s", res.storageAccountName)
   126  	_, createError := clients.storageAccountsClient.Create(res.resourceGroupName, res.storageAccountName, armStorage.AccountCreateParameters{
   127  		Sku: &armStorage.Sku{
   128  			Name: armStorage.StandardLRS,
   129  			Tier: armStorage.Standard,
   130  		},
   131  		Location: &location,
   132  	}, make(chan struct{}))
   133  	createErr := <-createError
   134  	if createErr != nil {
   135  		destroyResources(t, res.resourceGroupName)
   136  		t.Fatalf("failed to create test storage account: %s", err)
   137  	}
   138  
   139  	t.Log("fetching access key for storage account")
   140  	resp, err := clients.storageAccountsClient.ListKeys(res.resourceGroupName, res.storageAccountName)
   141  	if err != nil {
   142  		destroyResources(t, res.resourceGroupName)
   143  		t.Fatalf("failed to list storage account keys %s:", err)
   144  	}
   145  
   146  	keys := *resp.Keys
   147  	res.accessKey = *keys[0].Value
   148  
   149  	storageClient, err := storage.NewClient(res.storageAccountName, res.accessKey,
   150  		clients.environment.StorageEndpointSuffix, storage.DefaultAPIVersion, true)
   151  	if err != nil {
   152  		destroyResources(t, res.resourceGroupName)
   153  		t.Fatalf("failed to list storage account keys %s:", err)
   154  	}
   155  
   156  	t.Logf("creating container %s", res.containerName)
   157  	blobService := storageClient.GetBlobService()
   158  	container := blobService.GetContainerReference(res.containerName)
   159  	err = container.Create(&storage.CreateContainerOptions{})
   160  	if err != nil {
   161  		destroyResources(t, res.resourceGroupName)
   162  		t.Fatalf("failed to create storage container: %s", err)
   163  	}
   164  
   165  	return res
   166  }
   167  
   168  func destroyResources(t *testing.T, resourceGroupName string) {
   169  	warning := "WARNING: Failed to delete the test Azure resources. They may incur charges. (error was %s)"
   170  
   171  	clients := getTestClient(t)
   172  
   173  	t.Log("destroying created resources")
   174  
   175  	// destroying is simple as deleting the resource group will destroy everything else
   176  	_, deleteErr := clients.groupsClient.Delete(resourceGroupName, make(chan struct{}))
   177  	err := <-deleteErr
   178  	if err != nil {
   179  		t.Logf(warning, err)
   180  		return
   181  	}
   182  
   183  	t.Log("Azure resources destroyed")
   184  }
   185  
   186  type testClient struct {
   187  	subscriptionID        string
   188  	tenantID              string
   189  	clientID              string
   190  	clientSecret          string
   191  	environment           azure.Environment
   192  	groupsClient          resources.GroupsClient
   193  	storageAccountsClient armStorage.AccountsClient
   194  }
   195  
   196  func getTestClient(t *testing.T) testClient {
   197  	client := testClient{
   198  		subscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
   199  		tenantID:       os.Getenv("ARM_TENANT_ID"),
   200  		clientID:       os.Getenv("ARM_CLIENT_ID"),
   201  		clientSecret:   os.Getenv("ARM_CLIENT_SECRET"),
   202  	}
   203  
   204  	if client.subscriptionID == "" || client.tenantID == "" || client.clientID == "" || client.clientSecret == "" {
   205  		t.Fatal("Azure credentials missing or incomplete")
   206  	}
   207  
   208  	env, err := getAzureEnvironment(os.Getenv("ARM_ENVIRONMENT"))
   209  	if err != nil {
   210  		t.Fatalf("Failed to detect Azure environment from ARM_ENVIRONMENT value: %s", os.Getenv("ARM_ENVIRONMENT"))
   211  	}
   212  	client.environment = env
   213  
   214  	oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, client.tenantID)
   215  	if err != nil {
   216  		t.Fatalf("Failed to get OAuth config: %s", err)
   217  	}
   218  
   219  	spt, err := adal.NewServicePrincipalToken(*oauthConfig, client.clientID, client.clientSecret, env.ResourceManagerEndpoint)
   220  	if err != nil {
   221  		t.Fatalf("Failed to create Service Principal Token: %s", err)
   222  	}
   223  
   224  	client.groupsClient = resources.NewGroupsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID)
   225  	client.groupsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
   226  
   227  	client.storageAccountsClient = armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID)
   228  	client.storageAccountsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
   229  
   230  	return client
   231  }