diff --git a/azurerm/internal/services/storage/metadata.go b/azurerm/internal/services/storage/metadata.go index a52fdc18e3d2..5358b1ce6600 100644 --- a/azurerm/internal/services/storage/metadata.go +++ b/azurerm/internal/services/storage/metadata.go @@ -1,11 +1,18 @@ package storage -import "github.com/hashicorp/terraform/helper/schema" +import ( + "fmt" + "regexp" + "strings" + + "github.com/hashicorp/terraform/helper/schema" +) func MetaDataSchema() *schema.Schema { return &schema.Schema{ - Type: schema.TypeMap, - Optional: true, + Type: schema.TypeMap, + Optional: true, + ValidateFunc: validateMetaDataKeys, } } @@ -28,3 +35,105 @@ func FlattenMetaData(input map[string]string) map[string]interface{} { return output } + +func validateMetaDataKeys(value interface{}, fieldName string) (warnings []string, errors []error) { + v, ok := value.(map[string]interface{}) + if !ok { + return + } + + for k := range v { + isCSharpKeyword := cSharpKeywords[strings.ToLower(k)] != nil + if isCSharpKeyword { + errors = append(errors, fmt.Errorf("%q is not a valid key (C# keyword)", k)) + } + + // must begin with a letter, underscore + // the rest: letters, digits and underscores + r, _ := regexp.Compile(`^([a-z_]{1}[a-z0-9_]{1,})$`) + if !r.MatchString(k) { + errors = append(errors, fmt.Errorf("MetaData must start with letters or an underscores. Got %q.", k)) + } + } + + return +} + +var cSharpKeywords = map[string]*struct{}{ + "abstract": {}, + "as": {}, + "base": {}, + "bool": {}, + "break": {}, + "byte": {}, + "case": {}, + "catch": {}, + "char": {}, + "checked": {}, + "class": {}, + "const": {}, + "continue": {}, + "decimal": {}, + "default": {}, + "delegate": {}, + "do": {}, + "double": {}, + "else": {}, + "enum": {}, + "event": {}, + "explicit": {}, + "extern": {}, + "false": {}, + "finally": {}, + "fixed": {}, + "float": {}, + "for": {}, + "foreach": {}, + "goto": {}, + "if": {}, + "implicit": {}, + "in": {}, + "int": {}, + "interface": {}, + "internal": {}, + "is": {}, + "lock": {}, + "long": {}, + "namespace": {}, + "new": {}, + "null": {}, + "object": {}, + "operator": {}, + "out": {}, + "override": {}, + "params": {}, + "private": {}, + "protected": {}, + "public": {}, + "readonly": {}, + "ref": {}, + "return": {}, + "sbyte": {}, + "sealed": {}, + "short": {}, + "sizeof": {}, + "stackalloc": {}, + "static": {}, + "string": {}, + "struct": {}, + "switch": {}, + "this": {}, + "throw": {}, + "true": {}, + "try": {}, + "typeof": {}, + "uint": {}, + "ulong": {}, + "unchecked": {}, + "unsafe": {}, + "ushort": {}, + "using": {}, + "void": {}, + "volatile": {}, + "while": {}, +} diff --git a/azurerm/internal/services/storage/metadata_test.go b/azurerm/internal/services/storage/metadata_test.go new file mode 100644 index 000000000000..84d045f49830 --- /dev/null +++ b/azurerm/internal/services/storage/metadata_test.go @@ -0,0 +1,61 @@ +package storage + +import "testing" + +func TestValidateMetaDataKeys(t *testing.T) { + testData := []struct { + Input string + Expected bool + }{ + { + Input: "", + Expected: false, + }, + { + Input: "Hello", + Expected: false, + }, + { + Input: "hello", + Expected: true, + }, + { + Input: "hello", + Expected: true, + }, + { + // C# keyword + Input: "using", + Expected: false, + }, + { + Input: "0hello", + Expected: false, + }, + { + Input: "heLLo", + Expected: false, + }, + { + Input: "panda_cycle", + Expected: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + value := map[string]interface{}{ + v.Input: "hello", + } + warnings, errors := validateMetaDataKeys(value, "field") + if len(warnings) != 0 { + t.Fatalf("Expected no warnings but got %d", len(warnings)) + } + + actual := len(errors) == 0 + if v.Expected != actual { + t.Fatalf("Expected %t but got %t", v.Expected, actual) + } + } +} diff --git a/azurerm/resource_arm_storage_share_test.go b/azurerm/resource_arm_storage_share_test.go index aee53fd106bf..dc96c7a1a952 100644 --- a/azurerm/resource_arm_storage_share_test.go +++ b/azurerm/resource_arm_storage_share_test.go @@ -319,7 +319,7 @@ resource "azurerm_storage_share" "test" { resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" - metadata { + metadata = { hello = "world" } } @@ -336,7 +336,7 @@ resource "azurerm_storage_share" "test" { resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" - metadata { + metadata = { hello = "world" happy = "birthday" }