233 lines
7.0 KiB
Go
233 lines
7.0 KiB
Go
package azure
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
|
armStorage "github.com/Azure/azure-sdk-for-go/arm/storage"
|
|
"github.com/Azure/azure-sdk-for-go/storage"
|
|
"github.com/Azure/go-autorest/autorest"
|
|
"github.com/Azure/go-autorest/autorest/adal"
|
|
"github.com/Azure/go-autorest/autorest/azure"
|
|
"github.com/hashicorp/terraform/backend"
|
|
"github.com/hashicorp/terraform/helper/acctest"
|
|
)
|
|
|
|
// verify that we are doing ACC tests or the Azure tests specifically
|
|
func testACC(t *testing.T) {
|
|
skip := os.Getenv("TF_ACC") == "" && os.Getenv("TF_AZURE_TEST") == ""
|
|
if skip {
|
|
t.Log("azure backend tests require setting TF_ACC or TF_AZURE_TEST")
|
|
t.Skip()
|
|
}
|
|
}
|
|
|
|
func TestBackend_impl(t *testing.T) {
|
|
var _ backend.Backend = new(Backend)
|
|
}
|
|
|
|
func TestBackendConfig(t *testing.T) {
|
|
// This test just instantiates the client. Shouldn't make any actual
|
|
// requests nor incur any costs.
|
|
|
|
config := map[string]interface{}{
|
|
"storage_account_name": "tfaccount",
|
|
"container_name": "tfcontainer",
|
|
"key": "state",
|
|
// Access Key must be Base64
|
|
"access_key": "QUNDRVNTX0tFWQ0K",
|
|
}
|
|
|
|
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
|
|
|
if b.containerName != "tfcontainer" {
|
|
t.Fatalf("Incorrect bucketName was populated")
|
|
}
|
|
if b.keyName != "state" {
|
|
t.Fatalf("Incorrect keyName was populated")
|
|
}
|
|
}
|
|
|
|
func TestBackend(t *testing.T) {
|
|
testACC(t)
|
|
|
|
keyName := "testState"
|
|
res := setupResources(t, keyName)
|
|
defer destroyResources(t, res.resourceGroupName)
|
|
|
|
b := backend.TestBackendConfig(t, New(), map[string]interface{}{
|
|
"storage_account_name": res.storageAccountName,
|
|
"container_name": res.containerName,
|
|
"key": keyName,
|
|
"access_key": res.accessKey,
|
|
}).(*Backend)
|
|
|
|
backend.TestBackendStates(t, b)
|
|
}
|
|
|
|
func TestBackendLocked(t *testing.T) {
|
|
testACC(t)
|
|
|
|
keyName := "testState"
|
|
res := setupResources(t, keyName)
|
|
defer destroyResources(t, res.resourceGroupName)
|
|
|
|
b1 := backend.TestBackendConfig(t, New(), map[string]interface{}{
|
|
"storage_account_name": res.storageAccountName,
|
|
"container_name": res.containerName,
|
|
"key": keyName,
|
|
"access_key": res.accessKey,
|
|
}).(*Backend)
|
|
|
|
b2 := backend.TestBackendConfig(t, New(), map[string]interface{}{
|
|
"storage_account_name": res.storageAccountName,
|
|
"container_name": res.containerName,
|
|
"key": keyName,
|
|
"access_key": res.accessKey,
|
|
}).(*Backend)
|
|
|
|
backend.TestBackendStateLocks(t, b1, b2)
|
|
backend.TestBackendStateForceUnlock(t, b1, b2)
|
|
}
|
|
|
|
type testResources struct {
|
|
resourceGroupName string
|
|
storageAccountName string
|
|
containerName string
|
|
keyName string
|
|
accessKey string
|
|
}
|
|
|
|
func setupResources(t *testing.T, keyName string) testResources {
|
|
clients := getTestClient(t)
|
|
|
|
ri := acctest.RandInt()
|
|
rs := acctest.RandString(4)
|
|
res := testResources{
|
|
resourceGroupName: fmt.Sprintf("terraform-backend-testing-%d", ri),
|
|
storageAccountName: fmt.Sprintf("tfbackendtesting%s", rs),
|
|
containerName: "terraform",
|
|
keyName: keyName,
|
|
}
|
|
|
|
location := os.Getenv("ARM_LOCATION")
|
|
if location == "" {
|
|
location = "westus"
|
|
}
|
|
|
|
t.Logf("creating resource group %s", res.resourceGroupName)
|
|
_, err := clients.groupsClient.CreateOrUpdate(res.resourceGroupName, resources.Group{Location: &location})
|
|
if err != nil {
|
|
t.Fatalf("failed to create test resource group: %s", err)
|
|
}
|
|
|
|
t.Logf("creating storage account %s", res.storageAccountName)
|
|
_, createError := clients.storageAccountsClient.Create(res.resourceGroupName, res.storageAccountName, armStorage.AccountCreateParameters{
|
|
Sku: &armStorage.Sku{
|
|
Name: armStorage.StandardLRS,
|
|
Tier: armStorage.Standard,
|
|
},
|
|
Location: &location,
|
|
}, make(chan struct{}))
|
|
createErr := <-createError
|
|
if createErr != nil {
|
|
destroyResources(t, res.resourceGroupName)
|
|
t.Fatalf("failed to create test storage account: %s", err)
|
|
}
|
|
|
|
t.Log("fetching access key for storage account")
|
|
resp, err := clients.storageAccountsClient.ListKeys(res.resourceGroupName, res.storageAccountName)
|
|
if err != nil {
|
|
destroyResources(t, res.resourceGroupName)
|
|
t.Fatalf("failed to list storage account keys %s:", err)
|
|
}
|
|
|
|
keys := *resp.Keys
|
|
res.accessKey = *keys[0].Value
|
|
|
|
storageClient, err := storage.NewClient(res.storageAccountName, res.accessKey,
|
|
clients.environment.StorageEndpointSuffix, storage.DefaultAPIVersion, true)
|
|
if err != nil {
|
|
destroyResources(t, res.resourceGroupName)
|
|
t.Fatalf("failed to list storage account keys %s:", err)
|
|
}
|
|
|
|
t.Logf("creating container %s", res.containerName)
|
|
blobService := storageClient.GetBlobService()
|
|
container := blobService.GetContainerReference(res.containerName)
|
|
err = container.Create(&storage.CreateContainerOptions{})
|
|
if err != nil {
|
|
destroyResources(t, res.resourceGroupName)
|
|
t.Fatalf("failed to create storage container: %s", err)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func destroyResources(t *testing.T, resourceGroupName string) {
|
|
warning := "WARNING: Failed to delete the test Azure resources. They may incur charges. (error was %s)"
|
|
|
|
clients := getTestClient(t)
|
|
|
|
t.Log("destroying created resources")
|
|
|
|
// destroying is simple as deleting the resource group will destroy everything else
|
|
_, deleteErr := clients.groupsClient.Delete(resourceGroupName, make(chan struct{}))
|
|
err := <-deleteErr
|
|
if err != nil {
|
|
t.Logf(warning, err)
|
|
return
|
|
}
|
|
|
|
t.Log("Azure resources destroyed")
|
|
}
|
|
|
|
type testClient struct {
|
|
subscriptionID string
|
|
tenantID string
|
|
clientID string
|
|
clientSecret string
|
|
environment azure.Environment
|
|
groupsClient resources.GroupsClient
|
|
storageAccountsClient armStorage.AccountsClient
|
|
}
|
|
|
|
func getTestClient(t *testing.T) testClient {
|
|
client := testClient{
|
|
subscriptionID: os.Getenv("ARM_SUBSCRIPTION_ID"),
|
|
tenantID: os.Getenv("ARM_TENANT_ID"),
|
|
clientID: os.Getenv("ARM_CLIENT_ID"),
|
|
clientSecret: os.Getenv("ARM_CLIENT_SECRET"),
|
|
}
|
|
|
|
if client.subscriptionID == "" || client.tenantID == "" || client.clientID == "" || client.clientSecret == "" {
|
|
t.Fatal("Azure credentials missing or incomplete")
|
|
}
|
|
|
|
env, err := getAzureEnvironment(os.Getenv("ARM_ENVIRONMENT"))
|
|
if err != nil {
|
|
t.Fatalf("Failed to detect Azure environment from ARM_ENVIRONMENT value: %s", os.Getenv("ARM_ENVIRONMENT"))
|
|
}
|
|
client.environment = env
|
|
|
|
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, client.tenantID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get OAuth config: %s", err)
|
|
}
|
|
|
|
spt, err := adal.NewServicePrincipalToken(*oauthConfig, client.clientID, client.clientSecret, env.ResourceManagerEndpoint)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create Service Principal Token: %s", err)
|
|
}
|
|
|
|
client.groupsClient = resources.NewGroupsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID)
|
|
client.groupsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
|
|
|
client.storageAccountsClient = armStorage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, client.subscriptionID)
|
|
client.storageAccountsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
|
|
|
return client
|
|
}
|