Skip to content

Commit

Permalink
Added databricks_group_role resource (#1575)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoaihuongbk authored Sep 2, 2022
1 parent d4cc243 commit 6bb078e
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 4 deletions.
4 changes: 3 additions & 1 deletion aws/resource_group_instance_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// ResourceGroupInstanceProfile defines group role resource
func ResourceGroupInstanceProfile() *schema.Resource {
return common.NewPairID("group_id", "instance_profile_id").Schema(func(
r := common.NewPairID("group_id", "instance_profile_id").Schema(func(
m map[string]*schema.Schema) map[string]*schema.Schema {
m["instance_profile_id"].ValidateDiagFunc = ValidInstanceProfile
return m
Expand All @@ -33,4 +33,6 @@ func ResourceGroupInstanceProfile() *schema.Resource {
"remove", fmt.Sprintf(`roles[value eq "%s"]`, roleARN), ""))
},
})
r.DeprecationMessage = "Please migrate to `databricks_group_role`"
return r
}
4 changes: 2 additions & 2 deletions aws/resource_group_instance_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func TestResourceGroupInstanceProfileCreate_Error_InvalidARN(t *testing.T) {
},
Create: true,
}.Apply(t)
assert.EqualError(t, err, "invalid config supplied. [instance_profile_id] Invalid ARN")
assert.EqualError(t, err, "invalid config supplied. [instance_profile_id] Invalid ARN. Deprecated Resource")
}

func TestResourceGroupInstanceProfileCreate_Error_OtherARN(t *testing.T) {
Expand All @@ -117,7 +117,7 @@ func TestResourceGroupInstanceProfileCreate_Error_OtherARN(t *testing.T) {
},
Create: true,
}.Apply(t)
assert.EqualError(t, err, "invalid config supplied. [instance_profile_id] Invalid ARN")
assert.EqualError(t, err, "invalid config supplied. [instance_profile_id] Invalid ARN. Deprecated Resource")
}

func TestResourceGroupInstanceProfileRead(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/group_instance_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ subcategory: "Security"
---
# databricks_group_instance_profile Resource

-> **Note** This resource has an evolving API, which may change in future versions of the provider.
-> **Deprecated** Please migrate to [databricks_group_role](group_role.md).

This resource allows you to attach [databricks_instance_profile](instance_profile.md) (AWS) to [databricks_group](group.md).

Expand Down
50 changes: 50 additions & 0 deletions docs/resources/group_role.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
subcategory: "Security"
---
# databricks_group_role Resource

This resource allows you to attach Role ARN (AWS) to [databricks_group](group.md).

## Example Usage

```hcl
resource "databricks_group" "my_group" {
display_name = "my_group_name"
}
resource "databricks_group_role" "my_group_role" {
group_id = databricks_group.my_group.id
role = "arn:aws:iam::000000000000:role/my-role"
}
```

## Argument Reference

The following arguments are supported:

* `group_id` - (Required) This is the id of the [group](group.md) resource.
* `role` - (Required) This is the AWS role ARN.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The id for the `databricks_group_role` object which is in the format `<group_id>|<role>`.

## Import

-> **Note** Importing this resource is not currently supported.

## Related Resources

The following resources are often used in the same context:

* [End to end workspace management](../guides/workspace-management.md) guide.
* [databricks_aws_bucket_policy](../data-sources/aws_bucket_policy.md) data to configure a simple access policy for AWS S3 buckets, so that Databricks can access data in it.
* [databricks_cluster_policy](cluster_policy.md) to create a [databricks_cluster](cluster.md) policy, which limits the ability to create clusters based on a set of rules.
* [databricks_group](group.md) to manage [groups in Databricks Workspace](https://docs.databricks.com/administration-guide/users-groups/groups.html) or [Account Console](https://accounts.cloud.databricks.com/) (for AWS deployments).
* [databricks_group](../data-sources/group.md) data to retrieve information about [databricks_group](group.md) members, entitlements and instance profiles.
* [databricks_group_member](group_member.md) to attach [users](user.md) and [groups](group.md) as group members.
* [databricks_instance_pool](instance_pool.md) to manage [instance pools](https://docs.databricks.com/clusters/instance-pools/index.html) to reduce [cluster](cluster.md) start and auto-scaling times by maintaining a set of idle, ready-to-use instances.
* [databricks_instance_profile](instance_profile.md) to manage AWS EC2 instance profiles that users can launch [databricks_cluster](cluster.md) and access data, like [databricks_mount](mount.md).
* [databricks_user_instance_profile](user_instance_profile.md) to attach [databricks_instance_profile](instance_profile.md) (AWS) to [databricks_user](user.md).
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func DatabricksProvider() *schema.Provider {
"databricks_group": scim.ResourceGroup(),
"databricks_group_instance_profile": aws.ResourceGroupInstanceProfile(),
"databricks_group_member": scim.ResourceGroupMember(),
"databricks_group_role": scim.ResourceGroupRole(),
"databricks_instance_pool": pools.ResourceInstancePool(),
"databricks_instance_profile": aws.ResourceInstanceProfile(),
"databricks_ip_access_list": access.ResourceIPAccessList(),
Expand Down
30 changes: 30 additions & 0 deletions scim/resource_group_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package scim

import (
"context"
"fmt"

"github.com/databricks/terraform-provider-databricks/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// ResourceGroupRole bind group with role
func ResourceGroupRole() *schema.Resource {
return common.NewPairID("group_id", "role").BindResource(common.BindResource{
CreateContext: func(ctx context.Context, groupID, role string, c *common.DatabricksClient) error {
return NewGroupsAPI(ctx, c).Patch(groupID, PatchRequest("add", "roles", role))
},
ReadContext: func(ctx context.Context, groupID, role string, c *common.DatabricksClient) error {
group, err := NewGroupsAPI(ctx, c).Read(groupID)
hasRole := ComplexValues(group.Roles).HasValue(role)
if err == nil && !hasRole {
return common.NotFound("Group has no role")
}
return err
},
DeleteContext: func(ctx context.Context, groupID, role string, c *common.DatabricksClient) error {
return NewGroupsAPI(ctx, c).Patch(groupID, PatchRequest(
"remove", fmt.Sprintf(`roles[value eq "%s"]`, role), ""))
},
})
}
186 changes: 186 additions & 0 deletions scim/resource_group_role_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package scim

import (
"testing"

"github.com/databricks/terraform-provider-databricks/common"

"github.com/databricks/terraform-provider-databricks/qa"
)

func TestResourceGroupRoleCreate(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "PATCH",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
ExpectedRequest: PatchRequest("add", "roles", "arn:aws:iam::000000000000:role/test-role"),
Response: Group{
ID: "abc",
},
},
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: Group{
Schemas: []URN{"urn:ietf:params:scim:schemas:core:2.0:Group"},
DisplayName: "Data Scientists",
Roles: []ComplexValue{
{
Value: "arn:aws:iam::000000000000:role/test-role",
},
},
ID: "abc",
},
},
},
Resource: ResourceGroupRole(),
State: map[string]any{
"group_id": "abc",
"role": "arn:aws:iam::000000000000:role/test-role",
},
Create: true,
}.ApplyAndExpectData(t, map[string]any{"id": "abc|arn:aws:iam::000000000000:role/test-role"})
}

func TestResourceGroupRoleCreate_Error(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "PATCH",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: common.APIErrorBody{
ErrorCode: "INVALID_REQUEST",
Message: "Internal error happened",
},
Status: 400,
},
},
Resource: ResourceGroupRole(),
State: map[string]any{
"group_id": "abc",
"role": "arn:aws:iam::000000000000:role/test-role",
},
Create: true,
}.ExpectError(t, "Internal error happened")
}

func TestResourceGroupRoleRead(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: Group{
Schemas: []URN{"urn:ietf:params:scim:schemas:core:2.0:Group"},
DisplayName: "Data Scientists",
Roles: []ComplexValue{
{
Value: "arn:aws:iam::000000000000:role/test-role",
},
},
ID: "abc",
},
},
},
Resource: ResourceGroupRole(),
Read: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ApplyAndExpectData(t, map[string]any{"id": "abc|arn:aws:iam::000000000000:role/test-role"})
}

func TestResourceGroupRoleRead_NoRole(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: Group{
Schemas: []URN{"urn:ietf:params:scim:schemas:core:2.0:Group"},
DisplayName: "Data Scientists",
ID: "abc",
},
},
},
Resource: ResourceGroupRole(),
Read: true,
Removed: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ApplyNoError(t)
}

func TestResourceGroupRoleRead_NotFound(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: common.APIErrorBody{
ErrorCode: "NOT_FOUND",
Message: "Item not found",
},
Status: 404,
},
},
Resource: ResourceGroupRole(),
Read: true,
Removed: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ApplyNoError(t)
}

func TestResourceGroupRoleRead_Error(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: common.APIErrorBody{
ErrorCode: "INVALID_REQUEST",
Message: "Internal error happened",
},
Status: 400,
},
},
Resource: ResourceGroupRole(),
Read: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ExpectError(t, "Internal error happened")
}

func TestResourceGroupRoleDelete(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "PATCH",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
ExpectedRequest: PatchRequest(
"remove",
`roles[value eq "arn:aws:iam::000000000000:role/test-role"]`,
""),
},
},
Resource: ResourceGroupRole(),
Delete: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ApplyNoError(t)
}

func TestResourceGroupRoleDelete_Error(t *testing.T) {
qa.ResourceFixture{
Fixtures: []qa.HTTPFixture{
{
Method: "PATCH",
Resource: "/api/2.0/preview/scim/v2/Groups/abc",
Response: common.APIErrorBody{
ErrorCode: "INVALID_REQUEST",
Message: "Internal error happened",
},
Status: 400,
},
},
Resource: ResourceGroupRole(),
Delete: true,
ID: "abc|arn:aws:iam::000000000000:role/test-role",
}.ExpectError(t, "Internal error happened")
}

0 comments on commit 6bb078e

Please sign in to comment.