Skip to content

Commit d5d5ddd

Browse files
authored
Implicitly force import manually added group (#1067)
1 parent 2d138fb commit d5d5ddd

File tree

4 files changed

+100
-3
lines changed

4 files changed

+100
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Version changelog
22

3+
## 0.4.7
4+
* Added optional `force` argument to `databricks_group` resource to ignore `cannot create group: Group with name X already exists.` errors and implicitly import the specific group into Terraform state, enforcing entitlements defined in the instance of resource ([#1066](https://github.com/databrickslabs/terraform-provider-databricks/pull/1066)).
5+
36
## 0.4.6
47

58
* Clarified error messages around `azure_workspace_resource_id` provider configuration ([#1049](https://github.com/databrickslabs/terraform-provider-databricks/issues/1049)).

docs/resources/group.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ The following arguments are supported:
5252
* `allow_instance_pool_create` - (Optional) This is a field to allow the group to have [instance pool](instance_pool.md) create privileges. More fine grained permissions could be assigned with [databricks_permissions](permissions.md#Instance-Pool-usage) and [instance_pool_id](permissions.md#instance_pool_id) argument.
5353
* `databricks_sql_access` - (Optional) This is a field to allow the group to have access to [Databricks SQL](https://databricks.com/product/databricks-sql) feature in User Interface and through [databricks_sql_endpoint](sql_endpoint.md).
5454
* `workspace_access` - (Optional) This is a field to allow the group to have access to Databricks Workspace.
55+
* `force` - (Optional) Ignore `cannot create group: Group with name X already exists.` errors and implicitly import the specific group into Terraform state, enforcing entitlements defined in the instance of resource. _This functionality is experimental_ and is designed to simplify corner cases, like Azure Active Directory synchronisation.
5556

5657
## Attribute Reference
5758

scim/resource_group.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package scim
22

33
import (
44
"context"
5+
"fmt"
6+
"strings"
57

68
"github.com/databrickslabs/terraform-provider-databricks/common"
79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -24,18 +26,24 @@ func ResourceGroup() *schema.Resource {
2426
Optional: true,
2527
ForceNew: true,
2628
},
29+
"force": {
30+
Type: schema.TypeBool,
31+
Optional: true,
32+
},
2733
}
2834
addEntitlementsToSchema(&groupSchema)
2935
return common.Resource{
3036
Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
3137
groupName := d.Get("display_name").(string)
32-
group, err := NewGroupsAPI(ctx, c).Create(Group{
38+
g := Group{
3339
DisplayName: groupName,
3440
Entitlements: readEntitlementsFromData(d),
3541
ExternalID: d.Get("external_id").(string),
36-
})
42+
}
43+
groupsAPI := NewGroupsAPI(ctx, c)
44+
group, err := groupsAPI.Create(g)
3745
if err != nil {
38-
return err
46+
return createForceOverridesManuallyAddedGroup(err, d, groupsAPI, g)
3947
}
4048
d.SetId(group.ID)
4149
return nil
@@ -61,3 +69,22 @@ func ResourceGroup() *schema.Resource {
6169
Schema: groupSchema,
6270
}.ToResource()
6371
}
72+
73+
func createForceOverridesManuallyAddedGroup(err error, d *schema.ResourceData, groupsAPI GroupsAPI, g Group) error {
74+
forceCreate := d.Get("force").(bool)
75+
if !forceCreate {
76+
return err
77+
}
78+
// corner-case for overriding manually provisioned groups
79+
groupName := strings.ReplaceAll(g.DisplayName, "'", "")
80+
force := fmt.Sprintf("Group with name %s already exists.", groupName)
81+
if err.Error() != force {
82+
return err
83+
}
84+
group, err := groupsAPI.ReadByDisplayName(groupName)
85+
if err != nil {
86+
return err
87+
}
88+
d.SetId(group.ID)
89+
return groupsAPI.UpdateNameAndEntitlements(d.Id(), g.DisplayName, g.ExternalID, g.Entitlements)
90+
}

scim/resource_group_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package scim
22

33
import (
4+
"context"
5+
"fmt"
46
"testing"
57

68
"github.com/databrickslabs/terraform-provider-databricks/common"
@@ -346,3 +348,67 @@ func TestResourceGroupDelete_Error(t *testing.T) {
346348
ID: "abc",
347349
}.ExpectError(t, "Internal error happened")
348350
}
351+
352+
func TestCreateForceOverwriteCannotListGroups(t *testing.T) {
353+
qa.HTTPFixturesApply(t, []qa.HTTPFixture{
354+
{
355+
Method: "GET",
356+
Resource: "/api/2.0/preview/scim/v2/Groups?filter=displayName%20eq%20%27abc%27",
357+
Status: 417,
358+
Response: common.APIError{
359+
Message: "cannot find group",
360+
},
361+
},
362+
}, func(ctx context.Context, client *common.DatabricksClient) {
363+
d := ResourceGroup().TestResourceData()
364+
d.Set("force", true)
365+
err := createForceOverridesManuallyAddedGroup(
366+
fmt.Errorf("Group with name abc already exists."),
367+
d, NewGroupsAPI(ctx, client), Group{
368+
DisplayName: "abc",
369+
})
370+
assert.EqualError(t, err, "cannot find group")
371+
})
372+
}
373+
374+
func TestCreateForceOverwriteFindsAndSetsGroupID(t *testing.T) {
375+
qa.HTTPFixturesApply(t, []qa.HTTPFixture{
376+
{
377+
Method: "GET",
378+
Resource: "/api/2.0/preview/scim/v2/Groups?filter=displayName%20eq%20%27abc%27",
379+
Response: GroupList{
380+
Resources: []Group{
381+
{
382+
ID: "123",
383+
},
384+
},
385+
},
386+
},
387+
{
388+
Method: "GET",
389+
Resource: "/api/2.0/preview/scim/v2/Groups/123",
390+
Response: Group{
391+
ID: "123",
392+
},
393+
},
394+
{
395+
Method: "PUT",
396+
Resource: "/api/2.0/preview/scim/v2/Groups/123",
397+
ExpectedRequest: Group{
398+
Schemas: []URN{"urn:ietf:params:scim:schemas:core:2.0:Group"},
399+
DisplayName: "abc",
400+
},
401+
},
402+
}, func(ctx context.Context, client *common.DatabricksClient) {
403+
d := ResourceGroup().TestResourceData()
404+
d.Set("force", true)
405+
d.Set("display_name", "abc")
406+
err := createForceOverridesManuallyAddedGroup(
407+
fmt.Errorf("Group with name abc already exists."),
408+
d, NewGroupsAPI(ctx, client), Group{
409+
DisplayName: "abc",
410+
})
411+
assert.NoError(t, err)
412+
assert.Equal(t, "123", d.Id())
413+
})
414+
}

0 commit comments

Comments
 (0)