Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/storage_table: switching over to using the new sdk #3834

Merged
merged 2 commits into from
Jul 12, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -901,22 +901,3 @@ func (c *ArmClient) getBlobStorageClientForStorageAccount(ctx context.Context, r
blobClient := storageClient.GetBlobService()
return &blobClient, true, nil
}

func (c *ArmClient) getTableServiceClientForStorageAccount(ctx context.Context, resourceGroupName, storageAccountName string) (*mainStorage.TableServiceClient, bool, error) {
key, accountExists, err := c.getKeyForStorageAccount(ctx, resourceGroupName, storageAccountName)
if err != nil {
return nil, accountExists, err
}
if !accountExists {
return nil, false, nil
}

storageClient, err := mainStorage.NewClient(storageAccountName, key, c.environment.StorageEndpointSuffix,
mainStorage.DefaultAPIVersion, true)
if err != nil {
return nil, true, fmt.Errorf("Error creating storage client for storage storeAccount %q: %s", storageAccountName, err)
}

tableClient := storageClient.GetTableService()
return &tableClient, true, nil
}
14 changes: 14 additions & 0 deletions azurerm/internal/services/storage/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/shares"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/entities"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/tables"
)

type Client struct {
Expand Down Expand Up @@ -94,6 +95,7 @@ func (client Client) QueuesClient(ctx context.Context, resourceGroup, accountNam
queuesClient.Client.Authorizer = storageAuth
return &queuesClient, nil
}

func (client Client) TableEntityClient(ctx context.Context, resourceGroup, accountName string) (*entities.Client, error) {
accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName)
if err != nil {
Expand All @@ -106,6 +108,18 @@ func (client Client) TableEntityClient(ctx context.Context, resourceGroup, accou
return &entitiesClient, nil
}

func (client Client) TablesClient(ctx context.Context, resourceGroup, accountName string) (*tables.Client, error) {
accountKey, err := client.findAccountKey(ctx, resourceGroup, accountName)
if err != nil {
return nil, fmt.Errorf("Error retrieving Account Key: %s", err)
}

storageAuth := authorizers.NewSharedKeyLiteTableAuthorizer(accountName, *accountKey)
tablesClient := tables.New()
tablesClient.Client.Authorizer = storageAuth
return &tablesClient, nil
}

func (client Client) findAccountKey(ctx context.Context, resourceGroup, accountName string) (*string, error) {
props, err := client.accountsClient.ListKeys(ctx, resourceGroup, accountName)
if err != nil {
Expand Down
197 changes: 75 additions & 122 deletions azurerm/resource_arm_storage_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package azurerm
import (
"fmt"
"log"
"net/url"
"regexp"
"strings"

"github.com/Azure/azure-sdk-for-go/storage"
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/tables"
)

func resourceArmStorageTable() *schema.Resource {
Expand All @@ -31,200 +30,154 @@ func resourceArmStorageTable() *schema.Resource {
ForceNew: true,
ValidateFunc: validateArmStorageTableName,
},
"resource_group_name": azure.SchemaResourceGroupName(),

"storage_account_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateArmStorageAccountName,
},
},
}
}

func validateArmStorageTableName(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)
if value == "table" {
errors = append(errors, fmt.Errorf(
"Table Storage %q cannot use the word `table`: %q",
k, value))
}
if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]{2,62}$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"Table Storage %q cannot begin with a numeric character, only alphanumeric characters are allowed and must be between 3 and 63 characters long: %q",
k, value))
}
// TODO: deprecate this in the docs
"resource_group_name": azure.SchemaResourceGroupNameDeprecated(),

return warnings, errors
// TODO: support for ACL's
},
}
}

func resourceArmStorageTableCreate(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*ArmClient)
ctx := armClient.StopContext
environment := armClient.environment
ctx := meta.(*ArmClient).StopContext
storageClient := meta.(*ArmClient).storage

name := d.Get("name").(string)
resourceGroupName := d.Get("resource_group_name").(string)
storageAccountName := d.Get("storage_account_name").(string)
tableName := d.Get("name").(string)
accountName := d.Get("storage_account_name").(string)

tableClient, accountExists, err := armClient.getTableServiceClientForStorageAccount(ctx, resourceGroupName, storageAccountName)
resourceGroup, err := storageClient.FindResourceGroup(ctx, accountName)
if err != nil {
return err
}
if !accountExists {
return fmt.Errorf("Storage Account %q Not Found", storageAccountName)
return fmt.Errorf("Error locating Resource Group: %s", err)
}

table := tableClient.GetTableReference(name)
id := fmt.Sprintf("https://%s.table.%s/%s", storageAccountName, environment.StorageEndpointSuffix, name)
client, err := storageClient.TablesClient(ctx, *resourceGroup, accountName)
if err != nil {
return fmt.Errorf("Error building File Share Client: %s", err)
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
}

id := client.GetResourceID(accountName, tableName)
if requireResourcesToBeImported {
metaDataLevel := storage.MinimalMetadata
options := &storage.QueryTablesOptions{}
tables, e := tableClient.QueryTables(metaDataLevel, options)
if e != nil {
return fmt.Errorf("Error checking if Table %q exists (Account %q / Resource Group %q): %s", name, storageAccountName, resourceGroupName, e)
existing, err := client.Exists(ctx, *resourceGroup, tableName)
if err != nil {
if !utils.ResponseWasNotFound(existing) {
return fmt.Errorf("Error checking for existence of existing Storage Table %q (Account %q / Resource Group %q): %+v", tableName, accountName, *resourceGroup, err)
}
}

for _, table := range tables.Tables {
if table.Name == name {
return tf.ImportAsExistsError("azurerm_storage_table", id)
}
if !utils.ResponseWasNotFound(existing) {
return tf.ImportAsExistsError("azurerm_storage_table", id)
}
}

log.Printf("[INFO] Creating table %q in storage account %q.", name, storageAccountName)
timeout := uint(60)
options := &storage.TableOptions{}
err = table.Create(timeout, storage.NoMetadata, options)
if err != nil {
return fmt.Errorf("Error creating table %q in storage account %q: %s", name, storageAccountName, err)
log.Printf("[DEBUG] Creating Table %q in Storage Account %q.", tableName, accountName)
if _, err := client.Create(ctx, accountName, tableName); err != nil {
return fmt.Errorf("Error creating Table %q within Storage Account %q: %s", tableName, accountName, err)
}

d.SetId(id)
return resourceArmStorageTableRead(d, meta)
}

func resourceArmStorageTableRead(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*ArmClient)
ctx := armClient.StopContext
storageClient := meta.(*ArmClient).storage
ctx := meta.(*ArmClient).StopContext

id, err := parseStorageTableID(d.Id())
id, err := tables.ParseResourceID(d.Id())
if err != nil {
return err
}

resourceGroup, err := determineResourceGroupForStorageAccount(id.storageAccountName, armClient)
resourceGroup, err := storageClient.FindResourceGroup(ctx, id.AccountName)
if err != nil {
return err
return fmt.Errorf("Error locating Resource Group: %s", err)
}

if resourceGroup == nil {
log.Printf("Unable to determine Resource Group for Storage Account %q (assuming removed)", id.storageAccountName)
log.Printf("Unable to determine Resource Group for Storage Account %q (assuming removed)", id.AccountName)
d.SetId("")
return nil
}

tableClient, accountExists, err := armClient.getTableServiceClientForStorageAccount(ctx, *resourceGroup, id.storageAccountName)
client, err := storageClient.TablesClient(ctx, *resourceGroup, id.AccountName)
if err != nil {
return err
return fmt.Errorf("Error building File Share Client: %s", err)
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
}

if !accountExists {
log.Printf("[DEBUG] Storage account %q not found, removing table %q from state", id.storageAccountName, id.tableName)
d.SetId("")
return nil
}

metaDataLevel := storage.MinimalMetadata
options := &storage.QueryTablesOptions{}
tables, err := tableClient.QueryTables(metaDataLevel, options)
exists, err := client.Exists(ctx, id.AccountName, id.TableName)
if err != nil {
return fmt.Errorf("Failed to retrieve Tables in Storage Account %q: %s", id.tableName, err)
}

var storageTable *storage.Table
for _, table := range tables.Tables {
if table.Name == id.tableName {
storageTable = &table
break
if utils.ResponseWasNotFound(exists) {
log.Printf("[DEBUG] Storage Account %q not found, removing table %q from state", id.AccountName, id.TableName)
d.SetId("")
return nil
}

return fmt.Errorf("Error retrieving Table %q in Storage Account %q: %s", id.TableName, id.AccountName, err)
}

if storageTable == nil {
log.Printf("[INFO] Table %q does not exist in Storage Account %q, removing from state...", id.tableName, id.storageAccountName)
d.SetId("")
return nil
_, err = client.GetACL(ctx, id.AccountName, id.TableName)
if err != nil {
return fmt.Errorf("Error retrieving Table %q in Storage Account %q: %s", id.TableName, id.AccountName, err)
}

d.Set("name", id.tableName)
d.Set("storage_account_name", id.storageAccountName)
d.Set("name", id.TableName)
d.Set("storage_account_name", id.AccountName)
d.Set("resource_group_name", resourceGroup)

return nil
}

func resourceArmStorageTableDelete(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*ArmClient)
ctx := armClient.StopContext
storageClient := meta.(*ArmClient).storage
ctx := meta.(*ArmClient).StopContext

id, err := parseStorageTableID(d.Id())
id, err := tables.ParseResourceID(d.Id())
if err != nil {
return err
}

resourceGroup, err := determineResourceGroupForStorageAccount(id.storageAccountName, armClient)
resourceGroup, err := storageClient.FindResourceGroup(ctx, id.AccountName)
if err != nil {
return err
return fmt.Errorf("Error locating Resource Group: %s", err)
}

if resourceGroup == nil {
log.Printf("Unable to determine Resource Group for Storage Account %q (assuming removed)", id.storageAccountName)
log.Printf("Unable to determine Resource Group for Storage Account %q (assuming removed)", id.AccountName)
return nil
}

tableClient, accountExists, err := armClient.getTableServiceClientForStorageAccount(ctx, *resourceGroup, id.storageAccountName)
client, err := storageClient.TablesClient(ctx, *resourceGroup, id.AccountName)
if err != nil {
return err
}
if !accountExists {
log.Printf("[INFO] Storage Account %q doesn't exist so the table won't exist", id.storageAccountName)
return nil
return fmt.Errorf("Error building File Share Client: %s", err)
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved
}

table := tableClient.GetTableReference(id.tableName)
timeout := uint(60)
options := &storage.TableOptions{}

log.Printf("[INFO] Deleting Table %q in Storage Account %q", id.tableName, id.storageAccountName)
if err := table.Delete(timeout, options); err != nil {
return fmt.Errorf("Error deleting table %q from Storage Account %q: %s", id.tableName, id.storageAccountName, err)
log.Printf("[INFO] Deleting Table %q in Storage Account %q", id.TableName, id.AccountName)
if _, err := client.Delete(ctx, id.AccountName, id.TableName); err != nil {
return fmt.Errorf("Error deleting Table %q from Storage Account %q: %s", id.TableName, id.AccountName, err)
}

return nil
}

type storageTableId struct {
storageAccountName string
tableName string
}

func parseStorageTableID(input string) (*storageTableId, error) {
// https://myaccount.table.core.windows.net/table1
uri, err := url.Parse(input)
if err != nil {
return nil, fmt.Errorf("Error parsing %q as a URI: %+v", input, err)
func validateArmStorageTableName(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)
if value == "table" {
errors = append(errors, fmt.Errorf(
"Table Storage %q cannot use the word `table`: %q",
k, value))
}

segments := strings.Split(uri.Host, ".")
if len(segments) > 0 {
storageAccountName := segments[0]
table := strings.Replace(uri.Path, "/", "", 1)
id := storageTableId{
storageAccountName: storageAccountName,
tableName: table,
}
return &id, nil
if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]{2,62}$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"Table Storage %q cannot begin with a numeric character, only alphanumeric characters are allowed and must be between 3 and 63 characters long: %q",
k, value))
}

return nil, nil
return warnings, errors
}
2 changes: 1 addition & 1 deletion azurerm/resource_arm_storage_table_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func resourceArmStorageTableEntity() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.NoEmptyStrings,
ValidateFunc: validateArmStorageAccountName,
},
"partition_key": {
Type: schema.TypeString,
Expand Down
Loading