Skip to content

Commit 8d926f0

Browse files
Merge pull request #3847 from terraform-providers/f-storage-table-acl
Improvement: `azurerm_storage_table` ACL Support
2 parents 9812c84 + 96188d6 commit 8d926f0

File tree

3 files changed

+278
-3
lines changed

3 files changed

+278
-3
lines changed

azurerm/resource_arm_storage_table.go

+136-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"regexp"
77

88
"github.com/hashicorp/terraform/helper/schema"
9+
"github.com/hashicorp/terraform/helper/validation"
910
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
1011
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
12+
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
1113
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
1214
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/table/tables"
1315
)
@@ -17,6 +19,7 @@ func resourceArmStorageTable() *schema.Resource {
1719
Create: resourceArmStorageTableCreate,
1820
Read: resourceArmStorageTableRead,
1921
Delete: resourceArmStorageTableDelete,
22+
Update: resourceArmStorageTableUpdate,
2023
Importer: &schema.ResourceImporter{
2124
State: schema.ImportStatePassthrough,
2225
},
@@ -41,7 +44,42 @@ func resourceArmStorageTable() *schema.Resource {
4144
// TODO: deprecate this in the docs
4245
"resource_group_name": azure.SchemaResourceGroupNameDeprecated(),
4346

44-
// TODO: support for ACL's
47+
"acl": {
48+
Type: schema.TypeSet,
49+
Optional: true,
50+
Elem: &schema.Resource{
51+
Schema: map[string]*schema.Schema{
52+
"id": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ValidateFunc: validation.StringLenBetween(1, 64),
56+
},
57+
"access_policy": {
58+
Type: schema.TypeList,
59+
Optional: true,
60+
Elem: &schema.Resource{
61+
Schema: map[string]*schema.Schema{
62+
"start": {
63+
Type: schema.TypeString,
64+
Required: true,
65+
ValidateFunc: validate.NoEmptyStrings,
66+
},
67+
"expiry": {
68+
Type: schema.TypeString,
69+
Required: true,
70+
ValidateFunc: validate.NoEmptyStrings,
71+
},
72+
"permissions": {
73+
Type: schema.TypeString,
74+
Required: true,
75+
ValidateFunc: validate.NoEmptyStrings,
76+
},
77+
},
78+
},
79+
},
80+
},
81+
},
82+
},
4583
},
4684
}
4785
}
@@ -52,6 +90,8 @@ func resourceArmStorageTableCreate(d *schema.ResourceData, meta interface{}) err
5290

5391
tableName := d.Get("name").(string)
5492
accountName := d.Get("storage_account_name").(string)
93+
aclsRaw := d.Get("acl").(*schema.Set).List()
94+
acls := expandStorageTableACLs(aclsRaw)
5595

5696
resourceGroup, err := storageClient.FindResourceGroup(ctx, accountName)
5797
if err != nil {
@@ -82,6 +122,10 @@ func resourceArmStorageTableCreate(d *schema.ResourceData, meta interface{}) err
82122
return fmt.Errorf("Error creating Table %q within Storage Account %q: %s", tableName, accountName, err)
83123
}
84124

125+
if _, err := client.SetACL(ctx, accountName, tableName, acls); err != nil {
126+
return fmt.Errorf("Error setting ACL's for Storage Table %q (Account %q / Resource Group %q): %+v", tableName, accountName, *resourceGroup, err)
127+
}
128+
85129
d.SetId(id)
86130
return resourceArmStorageTableRead(d, meta)
87131
}
@@ -122,15 +166,19 @@ func resourceArmStorageTableRead(d *schema.ResourceData, meta interface{}) error
122166
return fmt.Errorf("Error retrieving Table %q in Storage Account %q: %s", id.TableName, id.AccountName, err)
123167
}
124168

125-
_, err = client.GetACL(ctx, id.AccountName, id.TableName)
169+
acls, err := client.GetACL(ctx, id.AccountName, id.TableName)
126170
if err != nil {
127-
return fmt.Errorf("Error retrieving Table %q in Storage Account %q: %s", id.TableName, id.AccountName, err)
171+
return fmt.Errorf("Error retrieving ACL's %q in Storage Account %q: %s", id.TableName, id.AccountName, err)
128172
}
129173

130174
d.Set("name", id.TableName)
131175
d.Set("storage_account_name", id.AccountName)
132176
d.Set("resource_group_name", resourceGroup)
133177

178+
if err := d.Set("acl", flattenStorageTableACLs(acls)); err != nil {
179+
return fmt.Errorf("Error flattening `acl`: %+v", err)
180+
}
181+
134182
return nil
135183
}
136184

@@ -166,6 +214,47 @@ func resourceArmStorageTableDelete(d *schema.ResourceData, meta interface{}) err
166214
return nil
167215
}
168216

217+
func resourceArmStorageTableUpdate(d *schema.ResourceData, meta interface{}) error {
218+
storageClient := meta.(*ArmClient).storage
219+
ctx := meta.(*ArmClient).StopContext
220+
221+
id, err := tables.ParseResourceID(d.Id())
222+
if err != nil {
223+
return err
224+
}
225+
226+
resourceGroup, err := storageClient.FindResourceGroup(ctx, id.AccountName)
227+
if err != nil {
228+
return fmt.Errorf("Error locating Resource Group: %s", err)
229+
}
230+
231+
if resourceGroup == nil {
232+
log.Printf("Unable to determine Resource Group for Storage Account %q (assuming removed)", id.AccountName)
233+
d.SetId("")
234+
return nil
235+
}
236+
237+
client, err := storageClient.TablesClient(ctx, *resourceGroup, id.AccountName)
238+
if err != nil {
239+
return fmt.Errorf("Error building Table Client: %s", err)
240+
}
241+
242+
if d.HasChange("acl") {
243+
log.Printf("[DEBUG] Updating the ACL's for Storage Table %q (Storage Account %q)", id.TableName, id.AccountName)
244+
245+
aclsRaw := d.Get("acl").(*schema.Set).List()
246+
acls := expandStorageTableACLs(aclsRaw)
247+
248+
if _, err := client.SetACL(ctx, id.AccountName, id.TableName, acls); err != nil {
249+
return fmt.Errorf("Error updating ACL's for Storage Table %q (Storage Account %q): %s", id.TableName, id.AccountName, err)
250+
}
251+
252+
log.Printf("[DEBUG] Updated the ACL's for Storage Table %q (Storage Account %q)", id.TableName, id.AccountName)
253+
}
254+
255+
return resourceArmStorageTableRead(d, meta)
256+
}
257+
169258
func validateArmStorageTableName(v interface{}, k string) (warnings []string, errors []error) {
170259
value := v.(string)
171260
if value == "table" {
@@ -181,3 +270,47 @@ func validateArmStorageTableName(v interface{}, k string) (warnings []string, er
181270

182271
return warnings, errors
183272
}
273+
274+
func expandStorageTableACLs(input []interface{}) []tables.SignedIdentifier {
275+
results := make([]tables.SignedIdentifier, 0)
276+
277+
for _, v := range input {
278+
vals := v.(map[string]interface{})
279+
280+
policies := vals["access_policy"].([]interface{})
281+
policy := policies[0].(map[string]interface{})
282+
283+
identifier := tables.SignedIdentifier{
284+
Id: vals["id"].(string),
285+
AccessPolicy: tables.AccessPolicy{
286+
Start: policy["start"].(string),
287+
Expiry: policy["expiry"].(string),
288+
Permission: policy["permissions"].(string),
289+
},
290+
}
291+
results = append(results, identifier)
292+
}
293+
294+
return results
295+
}
296+
297+
func flattenStorageTableACLs(input tables.GetACLResult) []interface{} {
298+
result := make([]interface{}, 0)
299+
300+
for _, v := range input.SignedIdentifiers {
301+
output := map[string]interface{}{
302+
"id": v.Id,
303+
"access_policy": []interface{}{
304+
map[string]interface{}{
305+
"start": v.AccessPolicy.Start,
306+
"expiry": v.AccessPolicy.Expiry,
307+
"permissions": v.AccessPolicy.Permission,
308+
},
309+
},
310+
}
311+
312+
result = append(result, output)
313+
}
314+
315+
return result
316+
}

azurerm/resource_arm_storage_table_test.go

+121
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,45 @@ func TestAccAzureRMStorageTable_disappears(t *testing.T) {
9797
})
9898
}
9999

100+
func TestAccAzureRMStorageTable_acl(t *testing.T) {
101+
var table storage.Table
102+
103+
ri := tf.AccRandTimeInt()
104+
rs := strings.ToLower(acctest.RandString(11))
105+
location := testLocation()
106+
resourceName := "azurerm_storage_table.test"
107+
108+
resource.ParallelTest(t, resource.TestCase{
109+
PreCheck: func() { testAccPreCheck(t) },
110+
Providers: testAccProviders,
111+
CheckDestroy: testCheckAzureRMStorageTableDestroy,
112+
Steps: []resource.TestStep{
113+
{
114+
Config: testAccAzureRMStorageTable_acl(ri, rs, location),
115+
Check: resource.ComposeTestCheckFunc(
116+
testCheckAzureRMStorageTableExists(resourceName, &table),
117+
),
118+
},
119+
{
120+
ResourceName: resourceName,
121+
ImportState: true,
122+
ImportStateVerify: true,
123+
},
124+
{
125+
Config: testAccAzureRMStorageTable_aclUpdated(ri, rs, location),
126+
Check: resource.ComposeTestCheckFunc(
127+
testCheckAzureRMStorageTableExists(resourceName, &table),
128+
),
129+
},
130+
{
131+
ResourceName: resourceName,
132+
ImportState: true,
133+
ImportStateVerify: true,
134+
},
135+
},
136+
})
137+
}
138+
100139
func testCheckAzureRMStorageTableExists(resourceName string, t *storage.Table) resource.TestCheckFunc {
101140
return func(s *terraform.State) error {
102141

@@ -291,3 +330,85 @@ resource "azurerm_storage_table" "import" {
291330
}
292331
`, template)
293332
}
333+
334+
func testAccAzureRMStorageTable_acl(rInt int, rString string, location string) string {
335+
return fmt.Sprintf(`
336+
resource "azurerm_resource_group" "test" {
337+
name = "acctestRG-%d"
338+
location = "%s"
339+
}
340+
341+
resource "azurerm_storage_account" "test" {
342+
name = "acctestacc%s"
343+
resource_group_name = "${azurerm_resource_group.test.name}"
344+
location = "${azurerm_resource_group.test.location}"
345+
account_tier = "Standard"
346+
account_replication_type = "LRS"
347+
348+
tags = {
349+
environment = "staging"
350+
}
351+
}
352+
353+
resource "azurerm_storage_table" "test" {
354+
name = "acctestst%d"
355+
resource_group_name = "${azurerm_resource_group.test.name}"
356+
storage_account_name = "${azurerm_storage_account.test.name}"
357+
acl {
358+
id = "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI"
359+
360+
access_policy {
361+
permissions = "raud"
362+
start = "2020-11-26T08:49:37.0000000Z"
363+
expiry = "2020-11-27T08:49:37.0000000Z"
364+
}
365+
}
366+
}
367+
`, rInt, location, rString, rInt)
368+
}
369+
370+
func testAccAzureRMStorageTable_aclUpdated(rInt int, rString string, location string) string {
371+
return fmt.Sprintf(`
372+
resource "azurerm_resource_group" "test" {
373+
name = "acctestRG-%d"
374+
location = "%s"
375+
}
376+
377+
resource "azurerm_storage_account" "test" {
378+
name = "acctestacc%s"
379+
resource_group_name = "${azurerm_resource_group.test.name}"
380+
location = "${azurerm_resource_group.test.location}"
381+
account_tier = "Standard"
382+
account_replication_type = "LRS"
383+
384+
tags = {
385+
environment = "staging"
386+
}
387+
}
388+
389+
resource "azurerm_storage_table" "test" {
390+
name = "acctestst%d"
391+
resource_group_name = "${azurerm_resource_group.test.name}"
392+
storage_account_name = "${azurerm_storage_account.test.name}"
393+
394+
acl {
395+
id = "AAAANDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI"
396+
397+
access_policy {
398+
permissions = "raud"
399+
start = "2020-11-26T08:49:37.0000000Z"
400+
expiry = "2020-11-27T08:49:37.0000000Z"
401+
}
402+
}
403+
acl {
404+
id = "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI"
405+
406+
access_policy {
407+
permissions = "raud"
408+
start = "2019-07-02T09:38:21.0000000Z"
409+
expiry = "2019-07-02T10:38:21.0000000Z"
410+
}
411+
}
412+
}
413+
`, rInt, location, rString, rInt)
414+
}

website/docs/r/storage_table.html.markdown

+21
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ The following arguments are supported:
4444

4545
* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to create the storage table.
4646

47+
* `acl` - (Optional) One or more `acl` blocks as defined below.
48+
49+
---
50+
51+
A `acl` block supports the following:
52+
53+
* `id` - (Required) The ID which should be used for this Shared Identifier.
54+
55+
* `access_policy` - (Required) An `access_policy` block as defined below.
56+
57+
---
58+
59+
A `access_policy` block supports the following:
60+
61+
* `expiry` - (Required) The ISO8061 UTC time at which this Access Policy should be valid until.
62+
63+
* `permissions` - (Required) The permissions which should associated with this Shared Identifier.
64+
65+
* `start` - (Required) The ISO8061 UTC time at which this Access Policy should be valid from.
66+
67+
4768
## Attributes Reference
4869

4970
The following attributes are exported in addition to the arguments listed above:

0 commit comments

Comments
 (0)