@@ -14,7 +14,6 @@ import (
14
14
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
15
15
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
16
16
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
17
- "github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault"
18
17
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
19
18
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
20
19
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -88,7 +87,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
88
87
Required : true ,
89
88
},
90
89
"roles" : schema.SetAttribute {
91
- MarkdownDescription : "Roles assigned to the user. Valid roles are `owner`, `template-admin`, `user-admin`, and `auditor`." ,
90
+ MarkdownDescription : "Roles assigned to the user. Valid roles are `owner`, `template-admin`, `user-admin`, and `auditor`. If `null`, roles will not be managed by Terraform. This attribute must be null if the user was created via OIDC and uses role sync. " ,
92
91
Computed : true ,
93
92
Optional : true ,
94
93
ElementType : types .StringType ,
@@ -97,7 +96,6 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
97
96
stringvalidator .OneOf ("owner" , "template-admin" , "user-admin" , "auditor" ),
98
97
),
99
98
},
100
- Default : setdefault .StaticValue (types .SetValueMust (types .StringType , []attr.Value {})),
101
99
},
102
100
"login_type" : schema.StringAttribute {
103
101
MarkdownDescription : "Type of login for the user. Valid types are `none`, `password`, `github`, and `oidc`." ,
@@ -209,21 +207,26 @@ func (r *UserResource) Create(ctx context.Context, req resource.CreateRequest, r
209
207
tflog .Info (ctx , "successfully updated user profile" )
210
208
data .Name = types .StringValue (user .Name )
211
209
212
- var roles []string
213
- resp .Diagnostics .Append (
214
- data .Roles .ElementsAs (ctx , & roles , false )... ,
215
- )
216
- tflog .Info (ctx , "updating user roles" , map [string ]any {
217
- "new_roles" : roles ,
218
- })
219
- user , err = client .UpdateUserRoles (ctx , user .ID .String (), codersdk.UpdateRoles {
220
- Roles : roles ,
221
- })
222
- if err != nil {
223
- resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update newly created user roles, got error: %s" , err ))
224
- return
210
+ if ! data .Roles .IsNull () {
211
+ var roles []string
212
+ resp .Diagnostics .Append (
213
+ data .Roles .ElementsAs (ctx , & roles , false )... ,
214
+ )
215
+ if resp .Diagnostics .HasError () {
216
+ return
217
+ }
218
+ tflog .Info (ctx , "updating user roles" , map [string ]any {
219
+ "new_roles" : roles ,
220
+ })
221
+ user , err = client .UpdateUserRoles (ctx , user .ID .String (), codersdk.UpdateRoles {
222
+ Roles : roles ,
223
+ })
224
+ if err != nil {
225
+ resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update newly created user roles, got error: %s" , err ))
226
+ return
227
+ }
228
+ tflog .Info (ctx , "successfully updated user roles" )
225
229
}
226
- tflog .Info (ctx , "successfully updated user roles" )
227
230
228
231
if data .Suspended .ValueBool () {
229
232
_ , err = client .UpdateUserStatus (ctx , data .ID .ValueString (), codersdk .UserStatus ("suspended" ))
@@ -267,11 +270,13 @@ func (r *UserResource) Read(ctx context.Context, req resource.ReadRequest, resp
267
270
data .Email = types .StringValue (user .Email )
268
271
data .Name = types .StringValue (user .Name )
269
272
data .Username = types .StringValue (user .Username )
270
- roles := make ([]attr.Value , 0 , len (user .Roles ))
271
- for _ , role := range user .Roles {
272
- roles = append (roles , types .StringValue (role .Name ))
273
+ if ! data .Roles .IsNull () {
274
+ roles := make ([]attr.Value , 0 , len (user .Roles ))
275
+ for _ , role := range user .Roles {
276
+ roles = append (roles , types .StringValue (role .Name ))
277
+ }
278
+ data .Roles = types .SetValueMust (types .StringType , roles )
273
279
}
274
- data .Roles = types .SetValueMust (types .StringType , roles )
275
280
data .LoginType = types .StringValue (string (user .LoginType ))
276
281
data .Suspended = types .BoolValue (user .Status == codersdk .UserStatusSuspended )
277
282
@@ -344,21 +349,26 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
344
349
data .Name = name
345
350
tflog .Info (ctx , "successfully updated user profile" )
346
351
347
- var roles []string
348
- resp .Diagnostics .Append (
349
- data .Roles .ElementsAs (ctx , & roles , false )... ,
350
- )
351
- tflog .Info (ctx , "updating user roles" , map [string ]any {
352
- "new_roles" : roles ,
353
- })
354
- _ , err = client .UpdateUserRoles (ctx , user .ID .String (), codersdk.UpdateRoles {
355
- Roles : roles ,
356
- })
357
- if err != nil {
358
- resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update user roles, got error: %s" , err ))
359
- return
352
+ if ! data .Roles .IsNull () {
353
+ var roles []string
354
+ resp .Diagnostics .Append (
355
+ data .Roles .ElementsAs (ctx , & roles , false )... ,
356
+ )
357
+ if resp .Diagnostics .HasError () {
358
+ return
359
+ }
360
+ tflog .Info (ctx , "updating user roles" , map [string ]any {
361
+ "new_roles" : roles ,
362
+ })
363
+ _ , err = client .UpdateUserRoles (ctx , user .ID .String (), codersdk.UpdateRoles {
364
+ Roles : roles ,
365
+ })
366
+ if err != nil {
367
+ resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update user roles, got error: %s" , err ))
368
+ return
369
+ }
370
+ tflog .Info (ctx , "successfully updated user roles" )
360
371
}
361
- tflog .Info (ctx , "successfully updated user roles" )
362
372
363
373
if data .LoginType .ValueString () == string (codersdk .LoginTypePassword ) && ! data .Password .IsNull () {
364
374
tflog .Info (ctx , "updating password" )
0 commit comments