Skip to content

Commit 224ef67

Browse files
committed
assorted fixes
1 parent d9d25d5 commit 224ef67

File tree

2 files changed

+53
-26
lines changed

2 files changed

+53
-26
lines changed

internal/provider/user_resource.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ package provider
66
import (
77
"context"
88
"fmt"
9+
"strings"
910

1011
"github.com/google/uuid"
11-
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
12+
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
1213
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1314
"github.com/hashicorp/terraform-plugin-framework/attr"
1415
"github.com/hashicorp/terraform-plugin-framework/path"
1516
"github.com/hashicorp/terraform-plugin-framework/resource"
1617
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1718
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
18-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
1919
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
20+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/setdefault"
2021
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
2122
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
2223
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -46,7 +47,7 @@ type UserResourceModel struct {
4647
Username types.String `tfsdk:"username"`
4748
Name types.String `tfsdk:"name"`
4849
Email types.String `tfsdk:"email"`
49-
Roles types.List `tfsdk:"roles"` // owner, template-admin, user-admin, auditor (member is implicit)
50+
Roles types.Set `tfsdk:"roles"` // owner, template-admin, user-admin, auditor (member is implicit)
5051
LoginType types.String `tfsdk:"login_type"` // none, password, github, oidc
5152
Password types.String `tfsdk:"password"` // only when login_type is password
5253
Suspended types.Bool `tfsdk:"suspended"`
@@ -83,19 +84,18 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
8384
MarkdownDescription: "Email address of the user.",
8485
Required: true,
8586
},
86-
"roles": schema.ListAttribute{
87+
"roles": schema.SetAttribute{
8788
MarkdownDescription: "Roles assigned to the user. Valid roles are 'owner', 'template-admin', 'user-admin', and 'auditor'.",
8889
Required: false,
8990
Optional: true,
9091
Computed: true,
9192
ElementType: types.StringType,
92-
Validators: []validator.List{
93-
listvalidator.UniqueValues(),
94-
listvalidator.ValueStringsAre(
93+
Validators: []validator.Set{
94+
setvalidator.ValueStringsAre(
9595
stringvalidator.OneOf("owner", "template-admin", "user-admin", "auditor"),
9696
),
9797
},
98-
Default: listdefault.StaticValue(types.ListValueMust(types.StringType, []attr.Value{})),
98+
Default: setdefault.StaticValue(types.SetValueMust(types.StringType, []attr.Value{})),
9999
},
100100
"login_type": schema.StringAttribute{
101101
MarkdownDescription: "Type of login for the user. Valid types are 'none', 'password', 'github', and 'oidc'.",
@@ -215,6 +215,13 @@ func (r *UserResource) Create(ctx context.Context, req resource.CreateRequest, r
215215
}
216216
tflog.Trace(ctx, "successfully updated user roles")
217217

218+
if data.Suspended.ValueBool() {
219+
_, err = r.client.UpdateUserStatus(ctx, data.ID.ValueString(), codersdk.UserStatus("suspended"))
220+
}
221+
if err != nil {
222+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update user status, got error: %s", err))
223+
return
224+
}
218225
// Save data into Terraform state
219226
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
220227
}
@@ -241,11 +248,12 @@ func (r *UserResource) Read(ctx context.Context, req resource.ReadRequest, resp
241248

242249
data.Email = types.StringValue(user.Email)
243250
data.Name = types.StringValue(user.Name)
251+
data.Username = types.StringValue(user.Username)
244252
roles := make([]attr.Value, 0, len(user.Roles))
245253
for _, role := range user.Roles {
246254
roles = append(roles, types.StringValue(role.Name))
247255
}
248-
data.Roles = types.ListValueMust(types.StringType, roles)
256+
data.Roles = types.SetValueMust(types.StringType, roles)
249257
data.LoginType = types.StringValue(string(user.LoginType))
250258
data.Suspended = types.BoolValue(user.Status == codersdk.UserStatusSuspended)
251259

@@ -307,12 +315,24 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
307315
err = r.client.UpdateUserPassword(ctx, user.ID.String(), codersdk.UpdateUserPasswordRequest{
308316
Password: data.Password.ValueString(),
309317
})
310-
if err != nil {
318+
if err != nil && !strings.Contains(err.Error(), "New password cannot match old password.") {
311319
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update password, got error: %s", err))
312320
return
313321
}
314322
tflog.Trace(ctx, "successfully updated password")
315323

324+
var statusErr error
325+
if data.Suspended.ValueBool() {
326+
_, statusErr = r.client.UpdateUserStatus(ctx, data.ID.ValueString(), codersdk.UserStatus("suspended"))
327+
}
328+
if !data.Suspended.ValueBool() && user.Status == codersdk.UserStatusSuspended {
329+
_, statusErr = r.client.UpdateUserStatus(ctx, data.ID.ValueString(), codersdk.UserStatus("active"))
330+
}
331+
if statusErr != nil {
332+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update user status, got error: %s", err))
333+
return
334+
}
335+
316336
// Save updated data into Terraform state
317337
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
318338
}

internal/provider/user_resource_test.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,23 @@ func TestAccUserResource(t *testing.T) {
2020
// Create and Read testing
2121
{
2222
Config: testAccUserResourceConfig{
23-
Username: "example",
24-
Name: "Example User",
25-
26-
Roles: []string{"owner", "auditor"},
23+
Username: "example",
24+
Name: "Example User",
25+
26+
Roles: []string{"owner", "auditor"},
2727
LoginType: "password",
28-
Password: "example-password",
29-
Suspended: true,
28+
Password: "SomeSecurePassword!",
3029
}.String(),
3130
Check: resource.ComposeAggregateTestCheckFunc(
3231
resource.TestCheckResourceAttr("coderd_user.test", "username", "example"),
3332
resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User"),
3433
resource.TestCheckResourceAttr("coderd_user.test", "email", "[email protected]"),
3534
resource.TestCheckResourceAttr("coderd_user.test", "roles.#", "2"),
36-
resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "owner"),
37-
resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "auditor"),
35+
resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "auditor"),
36+
resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "owner"),
3837
resource.TestCheckResourceAttr("coderd_user.test", "login_type", "password"),
39-
resource.TestCheckResourceAttr("coderd_user.test", "password", "example-password"),
40-
resource.TestCheckResourceAttr("coderd_user.test", "suspended", "true"),
38+
resource.TestCheckResourceAttr("coderd_user.test", "password", "SomeSecurePassword!"),
39+
resource.TestCheckResourceAttr("coderd_user.test", "suspended", "false"),
4140
),
4241
},
4342
// ImportState testing
@@ -49,13 +48,21 @@ func TestAccUserResource(t *testing.T) {
4948
// example code does not have an actual upstream service.
5049
// Once the Read method is able to refresh information from
5150
// the upstream service, this can be removed.
52-
ImportStateVerifyIgnore: []string{"configurable_attribute", "defaulted"},
51+
ImportStateVerifyIgnore: []string{"configurable_attribute", "defaulted", "password"},
5352
},
5453
// Update and Read testing
5554
{
56-
Config: testAccUserResourceConfig{}
55+
Config: testAccUserResourceConfig{
56+
Username: "exampleNew",
57+
Name: "Example User New",
58+
59+
Roles: []string{"owner", "auditor"},
60+
LoginType: "password",
61+
Password: "SomeSecurePassword!",
62+
}.String(),
5763
Check: resource.ComposeAggregateTestCheckFunc(
58-
resource.TestCheckResourceAttr("coderd_example.test", "configurable_attribute", "two"),
64+
resource.TestCheckResourceAttr("coderd_user.test", "username", "exampleNew"),
65+
resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User New"),
5966
),
6067
},
6168
// Delete testing automatically occurs in TestCase
@@ -89,15 +96,15 @@ func (c testAccUserResourceConfig) String() string {
8996
sb.WriteString(fmt.Sprintf(" roles = [%s]\n", strings.Join(rolesQuoted, ", ")))
9097
}
9198
if c.LoginType != "" {
92-
sb.WriteString(fmt.Sprintf(" login_type = %q", c.LoginType))
99+
sb.WriteString(fmt.Sprintf(" login_type = %q\n", c.LoginType))
93100
}
94101
if c.Password != "" {
95-
sb.WriteString(fmt.Sprintf(" password = %q", c.Password))
102+
sb.WriteString(fmt.Sprintf(" password = %q\n", c.Password))
96103
}
97104
if c.Suspended {
98105
sb.WriteString(" suspended = true\n")
99106
}
100107
sb.WriteString(`}`)
101108
return sb.String()
102109
}
103-
*/
110+
*/

0 commit comments

Comments
 (0)