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
2323const (
2424 resourceName = "permission"
2525)
2626
2727var (
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
3333func NewPermissionResource () resource.Resource {
@@ -65,75 +65,105 @@ func (r *PermissionResource) Metadata(ctx context.Context, req resource.Metadata
6565type 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+
96131func (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
213237func (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