Skip to content

Commit ac8025c

Browse files
Tanchwankvuong
authored andcommitted
resource now only supports single access control block
1 parent 8245c23 commit ac8025c

File tree

1 file changed

+92
-71
lines changed

1 file changed

+92
-71
lines changed

internal/providers/pluginfw/products/permission/resource_permission.go

Lines changed: 92 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"reflect"
87
"strings"
98
"time"
109

@@ -14,20 +13,21 @@ import (
1413
"github.com/databricks/terraform-provider-databricks/common"
1514
pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common"
1615
pluginfwcontext "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/context"
17-
"github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema"
1816
"github.com/hashicorp/terraform-plugin-framework/resource"
1917
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
18+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
2019
"github.com/hashicorp/terraform-plugin-framework/types"
20+
"github.com/hashicorp/terraform-plugin-framework/path"
2121
)
2222

2323
const (
2424
resourceName = "permission"
2525
)
2626

2727
var (
28-
apiPath string
29-
//_ resource.Resource = &PermissionResource{}
30-
//_ resource.ResourceWithConfigure = &PermissionResource{}
28+
_ resource.Resource = &PermissionResource{}
29+
_ resource.ResourceWithConfigure = &PermissionResource{}
30+
_ validator.Object = &accessControlListValidator{}
3131
)
3232

3333
func NewPermissionResource() resource.Resource {
@@ -65,75 +65,105 @@ func (r *PermissionResource) Metadata(ctx context.Context, req resource.Metadata
6565
type permissionResourceModel struct {
6666
ObjectID types.String `tfsdk:"object_id"`
6767
ObjectType types.String `tfsdk:"object_type"`
68-
AccessControlList []permissionAccessControlListModel `tfsdk:"access_control"`
68+
AccessControlList permissionAccessControlModel `tfsdk:"access_control"`
6969
LastUpdated types.String `tfsdk:"last_updated"`
7070
}
7171

7272
// accessControlListModel is the same as iam.AccessControlRequest
7373
// was originally just called this way in entity.go
74-
type permissionAccessControlListModel struct {
74+
type permissionAccessControlModel struct {
7575
ServicePrincipalId types.String `tfsdk:"service_principal_id"`
7676
GroupName types.String `tfsdk:"group_name"`
7777
UserName types.String `tfsdk:"user_name"`
7878
PermissionLevel types.String `tfsdk:"permission_level"`
7979
}
8080

81-
func (permissionResourceModel) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder {
82-
attrs["object_id"] = attrs["object_id"].SetOptional().SetComputed()
83-
attrs["object_type"] = attrs["object_type"].SetOptional().SetComputed()
84-
attrs["access_control"] = attrs["access_control"].SetRequired().SetComputed()
81+
type accessControlListValidator struct {}
8582

86-
return attrs
83+
func (v accessControlListValidator) Description(ctx context.Context) string {
84+
return "Only one of user_name, group_name, or service_principal_id may be set"
8785
}
8886

87+
func (v accessControlListValidator) MarkdownDescription(ctx context.Context) string {
88+
return v.Description(ctx)
89+
}
8990

90-
func (permissionResourceModel) GetComplexFieldTypes(context.Context) map[string]reflect.Type {
91-
return map[string]reflect.Type{
92-
"access_control" : reflect.TypeOf(permissionAccessControlListModel{}),
93-
}
91+
92+
func (v accessControlListValidator) ValidateObject(ctx context.Context, req validator.ObjectRequest, resp *validator.ObjectResponse) {
93+
var userName, groupName, spID types.String
94+
95+
// You must check for each field using its path
96+
if diags := req.Config.GetAttribute(ctx, path.Root("access_control").AtName("user_name"), &userName); diags.HasError() {
97+
resp.Diagnostics.Append(diags...)
98+
return
99+
}
100+
if diags := req.Config.GetAttribute(ctx, path.Root("access_control").AtName("group_name"), &groupName); diags.HasError() {
101+
resp.Diagnostics.Append(diags...)
102+
return
103+
}
104+
if diags := req.Config.GetAttribute(ctx, path.Root("access_control").AtName("service_principal_id"), &spID); diags.HasError() {
105+
resp.Diagnostics.Append(diags...)
106+
return
107+
}
108+
109+
// Count how many are set
110+
count := 0
111+
if !userName.IsNull() && userName.ValueString() != "" {
112+
count++
113+
}
114+
if !groupName.IsNull() && groupName.ValueString() != "" {
115+
count++
116+
}
117+
if !spID.IsNull() && spID.ValueString() != "" {
118+
count++
119+
}
120+
121+
if count != 1 {
122+
resp.Diagnostics.AddError(
123+
"Invalid access control configuration",
124+
"Exactly one of `user_name`, `group_name`, or `service_principal_id` must be set.",
125+
)
126+
}
94127
}
95128

129+
130+
96131
func (r *PermissionResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
97132
resp.Schema = schema.Schema{
98133
Attributes: map[string]schema.Attribute{
99134
"object_id": schema.StringAttribute{
100-
Computed: true,
101-
Optional: true,
135+
Required: true,
102136
},
103137
"object_type": schema.StringAttribute{
104-
Computed: true,
105-
Optional: true,
138+
Required: true,
106139
},
107140
"last_updated": schema.StringAttribute{
108141
Computed: true,
109142
},
110143
},
111144
Blocks: map[string]schema.Block{
112-
"access_control": schema.SetNestedBlock{
113-
NestedObject: schema.NestedBlockObject{
114-
Attributes: map[string]schema.Attribute{
115-
"service_principal_id": schema.StringAttribute{
116-
Computed: true,
117-
Optional: true,
118-
Description: "The service principal ID of the access control entry.",
119-
},
120-
"group_name": schema.StringAttribute{
121-
Computed: true,
122-
Optional: true,
123-
Description: "The group name of the access control entry.",
124-
},
125-
"user_name": schema.StringAttribute{
126-
Computed: true,
127-
Optional: true,
128-
Description: "The user name of the access control entry.",
129-
},
130-
"permission_level": schema.StringAttribute{
131-
Computed: true,
132-
Optional: true,
133-
Description: "The permission level of the access control entry.",
134-
},
145+
"access_control": schema.SingleNestedBlock{
146+
Attributes: map[string]schema.Attribute{
147+
"service_principal_id": schema.StringAttribute{
148+
Optional: true,
149+
Description: "The service principal ID of the access control entry.",
150+
},
151+
"group_name": schema.StringAttribute{
152+
Optional: true,
153+
Description: "The group name of the access control entry.",
154+
},
155+
"user_name": schema.StringAttribute{
156+
Optional: true,
157+
Description: "The user name of the access control entry.",
158+
},
159+
"permission_level": schema.StringAttribute{
160+
Optional: true,
161+
Description: "The permission level of the access control entry.",
162+
},
163+
},
164+
Validators: []validator.Object{
165+
accessControlListValidator{},
135166
},
136-
},
137167
},
138168
},
139169
}
@@ -159,23 +189,20 @@ func (r *PermissionResource) Create(ctx context.Context, req resource.CreateRequ
159189
return
160190
}
161191

192+
162193
// generate API request from plan
163-
var acls []iam.AccessControlRequest
164-
for _, acl := range plan.AccessControlList {
165-
acls = append(acls, iam.AccessControlRequest{
166-
//ServicePrincipalName: strings.Trim(acl.ServicePrincipalId.String(), "\""),
167-
GroupName: strings.Trim(acl.GroupName.String(), "\""),
168-
//UserName: strings.Trim(acl.UserName.String(), "\""),
169-
PermissionLevel: iam.PermissionLevel(strings.Trim(acl.PermissionLevel.String(), "\"")),
170-
})
171-
}
194+
var acl iam.AccessControlRequest
195+
acl.ServicePrincipalName = strings.Trim(plan.AccessControlList.ServicePrincipalId.String(), "\"")
196+
acl.GroupName = strings.Trim(plan.AccessControlList.GroupName.String(), "\"")
197+
acl.UserName = strings.Trim(plan.AccessControlList.UserName.String(), "\"")
198+
acl.PermissionLevel = iam.PermissionLevel(strings.Trim(plan.AccessControlList.PermissionLevel.String(), "\""))
172199

173200

174201
// create the permission
175202
permission, err := r.workspaceClient.Permissions.Update(ctx, iam.PermissionsRequest{
176203
RequestObjectId: plan.ObjectID.ValueString(),
177204
RequestObjectType: plan.ObjectType.ValueString(),
178-
AccessControlList: acls,
205+
AccessControlList: []iam.AccessControlRequest{acl},
179206
})
180207
if err != nil {
181208
resp.Diagnostics.AddError(
@@ -188,13 +215,11 @@ func (r *PermissionResource) Create(ctx context.Context, req resource.CreateRequ
188215
//Map response to to schema and populate Computed attribute values
189216
plan.ObjectID = types.StringValue(permission.ObjectId)
190217
plan.ObjectType = types.StringValue(permission.ObjectType)
191-
for permissionAclIndex, permissionAcl := range permission.AccessControlList {
192-
plan.AccessControlList[permissionAclIndex] = permissionAccessControlListModel{
193-
ServicePrincipalId: types.StringValue(permissionAcl.ServicePrincipalName),
194-
GroupName: types.StringValue(permissionAcl.GroupName),
195-
UserName: types.StringValue(permissionAcl.UserName),
196-
PermissionLevel: types.StringValue(string(permissionAcl.AllPermissions[permissionAclIndex].PermissionLevel)),
197-
}
218+
plan.AccessControlList = permissionAccessControlModel{
219+
ServicePrincipalId: types.StringValue(permission.AccessControlList[0].ServicePrincipalName),
220+
GroupName: types.StringValue(permission.AccessControlList[0].GroupName),
221+
UserName: types.StringValue(permission.AccessControlList[0].UserName),
222+
PermissionLevel: types.StringValue(string(permission.AccessControlList[0].AllPermissions[0].PermissionLevel)),
198223
}
199224

200225

@@ -208,7 +233,6 @@ func (r *PermissionResource) Create(ctx context.Context, req resource.CreateRequ
208233
}
209234
}
210235

211-
//apiPath = fmt.Sprintf("/api/2.0/permissions/%s/%s", plan.ObjectType.ValueString(), plan.ObjectID.ValueString())
212236

213237
func (r *PermissionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
214238
ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName)
@@ -250,15 +274,12 @@ func (r *PermissionResource) Read(ctx context.Context, req resource.ReadRequest,
250274

251275
//Overwrite data with refreshed state
252276
//TODO: parse getResponse to permissionResourceModel
253-
state.AccessControlList = []permissionAccessControlListModel{}
254-
for aclIndex, acl := range permissions.AccessControlList {
255-
state.AccessControlList = append(state.AccessControlList, permissionAccessControlListModel{
256-
ServicePrincipalId: types.StringValue(acl.ServicePrincipalName),
257-
GroupName: types.StringValue(acl.GroupName),
258-
UserName: types.StringValue(acl.UserName),
259-
PermissionLevel: types.StringValue(string(acl.AllPermissions[aclIndex].PermissionLevel)),
260-
})
261-
}
277+
state.AccessControlList.UserName = types.StringValue(permissions.AccessControlList[0].UserName)
278+
state.AccessControlList.GroupName = types.StringValue(permissions.AccessControlList[0].GroupName)
279+
state.AccessControlList.ServicePrincipalId = types.StringValue(permissions.AccessControlList[0].ServicePrincipalName)
280+
state.AccessControlList.PermissionLevel = types.StringValue(string(permissions.AccessControlList[0].AllPermissions[0].PermissionLevel))
281+
state.ObjectID = types.StringValue(permissions.ObjectId)
282+
state.ObjectType = types.StringValue(permissions.ObjectType)
262283

263284
//Set refreshed State
264285
diags = resp.State.Set(ctx, &state)

0 commit comments

Comments
 (0)