@@ -14,7 +14,6 @@ import (
1414 "github.com/hashicorp/terraform-plugin-framework/resource/schema"
1515 "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
1616 "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
17- "github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault"
1817 "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
1918 "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
2019 "github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -88,7 +87,7 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
8887 Required : true ,
8988 },
9089 "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. " ,
9291 Computed : true ,
9392 Optional : true ,
9493 ElementType : types .StringType ,
@@ -97,7 +96,6 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
9796 stringvalidator .OneOf ("owner" , "template-admin" , "user-admin" , "auditor" ),
9897 ),
9998 },
100- Default : setdefault .StaticValue (types .SetValueMust (types .StringType , []attr.Value {})),
10199 },
102100 "login_type" : schema.StringAttribute {
103101 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
209207 tflog .Info (ctx , "successfully updated user profile" )
210208 data .Name = types .StringValue (user .Name )
211209
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" )
225229 }
226- tflog .Info (ctx , "successfully updated user roles" )
227230
228231 if data .Suspended .ValueBool () {
229232 _ , 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
267270 data .Email = types .StringValue (user .Email )
268271 data .Name = types .StringValue (user .Name )
269272 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 )
273279 }
274- data .Roles = types .SetValueMust (types .StringType , roles )
275280 data .LoginType = types .StringValue (string (user .LoginType ))
276281 data .Suspended = types .BoolValue (user .Status == codersdk .UserStatusSuspended )
277282
@@ -344,21 +349,26 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
344349 data .Name = name
345350 tflog .Info (ctx , "successfully updated user profile" )
346351
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" )
360371 }
361- tflog .Info (ctx , "successfully updated user roles" )
362372
363373 if data .LoginType .ValueString () == string (codersdk .LoginTypePassword ) && ! data .Password .IsNull () {
364374 tflog .Info (ctx , "updating password" )
0 commit comments