From 00dfc4d086ab846c0ecb3cf723b2742404468711 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Tue, 16 Jun 2020 04:47:33 +0100 Subject: [PATCH] azuread_group: new property `prevent_duplicate_names` --- azuread/helpers/graph/group.go | 28 ++++++++++++++++++++++++++++ azuread/resource_group.go | 16 ++++++++++++++++ azuread/resource_group_test.go | 28 ++++++++++++++++++++++++++++ website/docs/r/group.markdown | 1 + 4 files changed, 73 insertions(+) diff --git a/azuread/helpers/graph/group.go b/azuread/helpers/graph/group.go index 325eb19d86..5ee3c98540 100644 --- a/azuread/helpers/graph/group.go +++ b/azuread/helpers/graph/group.go @@ -182,3 +182,31 @@ func GroupAddOwners(client graphrbac.GroupsClient, ctx context.Context, groupId return nil } + +func GroupFindByName(client graphrbac.GroupsClient, ctx context.Context, name string) (*graphrbac.ADGroup, error) { + nameFilter := fmt.Sprintf("displayName eq '%s'", name) + resp, err := client.List(ctx, nameFilter) + + if err != nil { + return nil, fmt.Errorf("unable to list Groups with filter %q: %+v", nameFilter, err) + } + + for _, group := range resp.Values() { + if *group.DisplayName == name { + return &group, nil + } + } + + return nil, nil +} + +func GroupCheckNameAvailability(client graphrbac.GroupsClient, ctx context.Context, name string) error { + existingGroup, err := GroupFindByName(client, ctx, name) + if err != nil { + return err + } + if existingGroup != nil { + return fmt.Errorf("existing Azure Active Directory Group with name %q (ObjID: %q) was found and `prevent_duplicate_names` was specified", name, *existingGroup.ObjectID) + } + return nil +} diff --git a/azuread/resource_group.go b/azuread/resource_group.go index 17565aac48..f08620e6c9 100644 --- a/azuread/resource_group.go +++ b/azuread/resource_group.go @@ -68,6 +68,11 @@ func resourceGroup() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "prevent_duplicate_names": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -78,6 +83,13 @@ func resourceGroupCreate(d *schema.ResourceData, meta interface{}) error { name := d.Get("name").(string) + if d.Get("prevent_duplicate_names").(bool) { + err := graph.GroupCheckNameAvailability(client, ctx, name) + if err != nil { + return err + } + } + properties := graphrbac.GroupCreateParameters{ DisplayName: &name, MailEnabled: p.Bool(false), // we're defaulting to false, as the API currently only supports the creation of non-mail enabled security groups. @@ -168,6 +180,10 @@ func resourceGroupRead(d *schema.ResourceData, meta interface{}) error { } d.Set("owners", owners) + if preventDuplicates := d.Get("prevent_duplicate_names").(bool); !preventDuplicates { + d.Set("prevent_duplicate_names", false) + } + return nil } diff --git a/azuread/resource_group_test.go b/azuread/resource_group_test.go index 83cb8f58b0..95148abe6d 100644 --- a/azuread/resource_group_test.go +++ b/azuread/resource_group_test.go @@ -2,6 +2,7 @@ package azuread import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" @@ -286,6 +287,22 @@ func TestAccAzureADGroup_ownersUpdate(t *testing.T) { }) } +func TestAccAzureADGroup_preventDuplicateNames(t *testing.T) { + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckADApplicationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureADGroup_duplicateName(ri), + ExpectError: regexp.MustCompile("existing Azure Active Directory Group .+ was found"), + }, + }, + }) +} + func testCheckAzureADGroupExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] @@ -503,3 +520,14 @@ resource "azuread_group" "test" { } `, id) } + +func testAccAzureADGroup_duplicateName(id int) string { + return fmt.Sprintf(` +%s + +resource "azuread_group" "duplicate" { + name = azuread_group.test.name + prevent_duplicate_names = true +} +`, testAccAzureADGroup_basic(id)) +} diff --git a/website/docs/r/group.markdown b/website/docs/r/group.markdown index 5dee3c0a9d..97aa609a43 100644 --- a/website/docs/r/group.markdown +++ b/website/docs/r/group.markdown @@ -49,6 +49,7 @@ The following arguments are supported: * `description` - (Optional) The description for the Group. Changing this forces a new resource to be created. * `members` (Optional) A set of members who should be present in this Group. Supported Object types are Users, Groups or Service Principals. * `owners` (Optional) A set of owners who own this Group. Supported Object types are Users or Service Principals. +* `prevent_duplicate_names` - (Optional) If `true`, will return an error when an existing Application is found with the same name. Defaults to `false`. -> **NOTE:** Group names are not unique within Azure Active Directory.