Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d157e1d

Browse files
authored
Merge pull request #43 from coder/07-25-chore_add_uuid_terraform_type
chore: add uuid terraform type
2 parents 3e8547b + 44c4e1b commit d157e1d

9 files changed

+322
-134
lines changed

internal/provider/group_data_source.go

+14-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66

77
"github.com/coder/coder/v2/codersdk"
8-
"github.com/google/uuid"
98
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
109
"github.com/hashicorp/terraform-plugin-framework/datasource"
1110
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
@@ -29,9 +28,9 @@ type GroupDataSource struct {
2928
// GroupDataSourceModel describes the data source data model.
3029
type GroupDataSourceModel struct {
3130
// ID or name and organization ID must be set
32-
ID types.String `tfsdk:"id"`
31+
ID UUID `tfsdk:"id"`
3332
Name types.String `tfsdk:"name"`
34-
OrganizationID types.String `tfsdk:"organization_id"`
33+
OrganizationID UUID `tfsdk:"organization_id"`
3534

3635
DisplayName types.String `tfsdk:"display_name"`
3736
AvatarURL types.String `tfsdk:"avatar_url"`
@@ -41,7 +40,7 @@ type GroupDataSourceModel struct {
4140
}
4241

4342
type Member struct {
44-
ID types.String `tfsdk:"id"`
43+
ID UUID `tfsdk:"id"`
4544
Username types.String `tfsdk:"username"`
4645
Email types.String `tfsdk:"email"`
4746
CreatedAt types.Int64 `tfsdk:"created_at"`
@@ -64,6 +63,7 @@ func (d *GroupDataSource) Schema(ctx context.Context, req datasource.SchemaReque
6463
MarkdownDescription: "The ID of the group to retrieve. This field will be populated if a name and organization ID is supplied.",
6564
Optional: true,
6665
Computed: true,
66+
CustomType: UUIDType,
6767
Validators: []validator.String{
6868
stringvalidator.AtLeastOneOf(path.Expressions{
6969
path.MatchRoot("name"),
@@ -78,6 +78,7 @@ func (d *GroupDataSource) Schema(ctx context.Context, req datasource.SchemaReque
7878
},
7979
"organization_id": schema.StringAttribute{
8080
MarkdownDescription: "The organization ID that the group belongs to. This field will be populated if an ID is supplied. Defaults to the provider default organization ID.",
81+
CustomType: UUIDType,
8182
Optional: true,
8283
Computed: true,
8384
},
@@ -101,7 +102,8 @@ func (d *GroupDataSource) Schema(ctx context.Context, req datasource.SchemaReque
101102
NestedObject: schema.NestedAttributeObject{
102103
Attributes: map[string]schema.Attribute{
103104
"id": schema.StringAttribute{
104-
Computed: true,
105+
CustomType: UUIDType,
106+
Computed: true,
105107
},
106108
"username": schema.StringAttribute{
107109
Computed: true,
@@ -169,36 +171,27 @@ func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest,
169171
client := d.data.Client
170172

171173
if data.OrganizationID.IsNull() {
172-
data.OrganizationID = types.StringValue(d.data.DefaultOrganizationID)
174+
data.OrganizationID = UUIDValue(d.data.DefaultOrganizationID)
173175
}
174176

175177
var group codersdk.Group
178+
var err error
176179
if !data.ID.IsNull() {
177-
groupID, err := uuid.Parse(data.ID.ValueString())
178-
if err != nil {
179-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied group ID as UUID, got error: %s", err))
180-
return
181-
}
182-
180+
groupID := data.ID.ValueUUID()
183181
group, err = client.Group(ctx, groupID)
184182
if err != nil {
185183
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get group by ID, got error: %s", err))
186184
return
187185
}
188186
data.Name = types.StringValue(group.Name)
189-
data.OrganizationID = types.StringValue(group.OrganizationID.String())
187+
data.OrganizationID = UUIDValue(group.OrganizationID)
190188
} else {
191-
orgID, err := uuid.Parse(data.OrganizationID.ValueString())
192-
if err != nil {
193-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied organization ID as UUID, got error: %s", err))
194-
return
195-
}
196-
group, err = client.GroupByOrgAndName(ctx, orgID, data.Name.ValueString())
189+
group, err = client.GroupByOrgAndName(ctx, data.OrganizationID.ValueUUID(), data.Name.ValueString())
197190
if err != nil {
198191
resp.Diagnostics.AddError("Failed to get group by name and org ID", err.Error())
199192
return
200193
}
201-
data.ID = types.StringValue(group.ID.String())
194+
data.ID = UUIDValue(group.ID)
202195
}
203196

204197
data.DisplayName = types.StringValue(group.DisplayName)
@@ -207,7 +200,7 @@ func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest,
207200
members := make([]Member, 0, len(group.Members))
208201
for _, member := range group.Members {
209202
members = append(members, Member{
210-
ID: types.StringValue(member.ID.String()),
203+
ID: UUIDValue(member.ID),
211204
Username: types.StringValue(member.Username),
212205
Email: types.StringValue(member.Email),
213206
CreatedAt: types.Int64Value(member.CreatedAt.Unix()),

internal/provider/group_resource.go

+16-30
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ type GroupResource struct {
3535

3636
// GroupResourceModel describes the resource data model.
3737
type GroupResourceModel struct {
38-
ID types.String `tfsdk:"id"`
38+
ID UUID `tfsdk:"id"`
3939

4040
Name types.String `tfsdk:"name"`
4141
DisplayName types.String `tfsdk:"display_name"`
4242
AvatarURL types.String `tfsdk:"avatar_url"`
4343
QuotaAllowance types.Int32 `tfsdk:"quota_allowance"`
44-
OrganizationID types.String `tfsdk:"organization_id"`
44+
OrganizationID UUID `tfsdk:"organization_id"`
4545
Members types.Set `tfsdk:"members"`
4646
}
4747

@@ -56,6 +56,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest,
5656
Attributes: map[string]schema.Attribute{
5757
"id": schema.StringAttribute{
5858
MarkdownDescription: "Group ID.",
59+
CustomType: UUIDType,
5960
Computed: true,
6061
PlanModifiers: []planmodifier.String{
6162
stringplanmodifier.UseStateForUnknown(),
@@ -84,6 +85,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest,
8485
},
8586
"organization_id": schema.StringAttribute{
8687
MarkdownDescription: "The organization ID that the group belongs to. Defaults to the provider default organization ID.",
88+
CustomType: UUIDType,
8789
Optional: true,
8890
Computed: true,
8991
PlanModifiers: []planmodifier.String{
@@ -92,7 +94,7 @@ func (r *GroupResource) Schema(ctx context.Context, req resource.SchemaRequest,
9294
},
9395
"members": schema.SetAttribute{
9496
MarkdownDescription: "Members of the group, by ID. If null, members will not be added or removed.",
95-
ElementType: types.StringType,
97+
ElementType: UUIDType,
9698
Optional: true,
9799
},
98100
},
@@ -132,14 +134,10 @@ func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest,
132134
client := r.data.Client
133135

134136
if data.OrganizationID.IsUnknown() {
135-
data.OrganizationID = types.StringValue(r.data.DefaultOrganizationID)
137+
data.OrganizationID = UUIDValue(r.data.DefaultOrganizationID)
136138
}
137139

138-
orgID, err := uuid.Parse(data.OrganizationID.ValueString())
139-
if err != nil {
140-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied organization ID as UUID, got error: %s", err))
141-
return
142-
}
140+
orgID := data.OrganizationID.ValueUUID()
143141

144142
displayName := data.Name.ValueString()
145143
if data.DisplayName.ValueString() != "" {
@@ -160,7 +158,7 @@ func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest,
160158
tflog.Trace(ctx, "successfully created group", map[string]any{
161159
"id": group.ID.String(),
162160
})
163-
data.ID = types.StringValue(group.ID.String())
161+
data.ID = UUIDValue(group.ID)
164162
data.DisplayName = types.StringValue(group.DisplayName)
165163

166164
tflog.Trace(ctx, "setting group members")
@@ -196,11 +194,7 @@ func (r *GroupResource) Read(ctx context.Context, req resource.ReadRequest, resp
196194

197195
client := r.data.Client
198196

199-
groupID, err := uuid.Parse(data.ID.ValueString())
200-
if err != nil {
201-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied group ID as UUID, got error: %s", err))
202-
return
203-
}
197+
groupID := data.ID.ValueUUID()
204198

205199
group, err := client.Group(ctx, groupID)
206200
if err != nil {
@@ -212,13 +206,13 @@ func (r *GroupResource) Read(ctx context.Context, req resource.ReadRequest, resp
212206
data.DisplayName = types.StringValue(group.DisplayName)
213207
data.AvatarURL = types.StringValue(group.AvatarURL)
214208
data.QuotaAllowance = types.Int32Value(int32(group.QuotaAllowance))
215-
data.OrganizationID = types.StringValue(group.OrganizationID.String())
209+
data.OrganizationID = UUIDValue(group.OrganizationID)
216210
if !data.Members.IsNull() {
217211
members := make([]attr.Value, 0, len(group.Members))
218212
for _, member := range group.Members {
219-
members = append(members, types.StringValue(member.ID.String()))
213+
members = append(members, UUIDValue(member.ID))
220214
}
221-
data.Members = types.SetValueMust(types.StringType, members)
215+
data.Members = types.SetValueMust(UUIDType, members)
222216
}
223217

224218
// Save updated data into Terraform state
@@ -237,13 +231,9 @@ func (r *GroupResource) Update(ctx context.Context, req resource.UpdateRequest,
237231

238232
client := r.data.Client
239233
if data.OrganizationID.IsUnknown() {
240-
data.OrganizationID = types.StringValue(r.data.DefaultOrganizationID)
241-
}
242-
groupID, err := uuid.Parse(data.ID.ValueString())
243-
if err != nil {
244-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied group ID as UUID, got error: %s", err))
245-
return
234+
data.OrganizationID = UUIDValue(r.data.DefaultOrganizationID)
246235
}
236+
groupID := data.ID.ValueUUID()
247237

248238
group, err := client.Group(ctx, groupID)
249239
if err != nil {
@@ -301,14 +291,10 @@ func (r *GroupResource) Delete(ctx context.Context, req resource.DeleteRequest,
301291
}
302292

303293
client := r.data.Client
304-
groupID, err := uuid.Parse(data.ID.ValueString())
305-
if err != nil {
306-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied group ID as UUID, got error: %s", err))
307-
return
308-
}
294+
groupID := data.ID.ValueUUID()
309295

310296
tflog.Trace(ctx, "deleting group")
311-
err = client.DeleteGroup(ctx, groupID)
297+
err := client.DeleteGroup(ctx, groupID)
312298
if err != nil {
313299
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete group, got error: %s", err))
314300
return

internal/provider/organization_data_source.go

+9-14
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66

77
"github.com/coder/coder/v2/codersdk"
8-
"github.com/google/uuid"
98
"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
109
"github.com/hashicorp/terraform-plugin-framework/attr"
1110
"github.com/hashicorp/terraform-plugin-framework/datasource"
@@ -30,7 +29,7 @@ type OrganizationDataSource struct {
3029
// OrganizationDataSourceModel describes the data source data model.
3130
type OrganizationDataSourceModel struct {
3231
// Exactly one of ID, IsDefault, or Name must be set.
33-
ID types.String `tfsdk:"id"`
32+
ID UUID `tfsdk:"id"`
3433
IsDefault types.Bool `tfsdk:"is_default"`
3534
Name types.String `tfsdk:"name"`
3635

@@ -52,6 +51,7 @@ func (d *OrganizationDataSource) Schema(ctx context.Context, req datasource.Sche
5251
Attributes: map[string]schema.Attribute{
5352
"id": schema.StringAttribute{
5453
MarkdownDescription: "The ID of the organization to retrieve. This field will be populated if the organization is found by name, or if the default organization is requested.",
54+
CustomType: UUIDType,
5555
Optional: true,
5656
Computed: true,
5757
},
@@ -77,7 +77,7 @@ func (d *OrganizationDataSource) Schema(ctx context.Context, req datasource.Sche
7777
"members": schema.SetAttribute{
7878
MarkdownDescription: "Members of the organization, by ID",
7979
Computed: true,
80-
ElementType: types.StringType,
80+
ElementType: UUIDType,
8181
},
8282
},
8383
}
@@ -116,23 +116,19 @@ func (d *OrganizationDataSource) Read(ctx context.Context, req datasource.ReadRe
116116
client := d.data.Client
117117

118118
var org codersdk.Organization
119+
var err error
119120
if !data.ID.IsNull() { // By ID
120-
orgID, err := uuid.Parse(data.ID.ValueString())
121-
if err != nil {
122-
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied ID as UUID, got error: %s", err))
123-
return
124-
}
121+
orgID := data.ID.ValueUUID()
125122
org, err = client.Organization(ctx, orgID)
126123
if err != nil {
127124
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get organization by ID, got error: %s", err))
128125
return
129126
}
130-
if org.ID.String() != data.ID.ValueString() {
127+
if org.ID != data.ID.ValueUUID() {
131128
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Organization ID %s does not match requested ID %s", org.ID, data.ID))
132129
return
133130
}
134131
} else if data.IsDefault.ValueBool() { // Get Default
135-
var err error
136132
org, err = client.OrganizationByName(ctx, "default")
137133
if err != nil {
138134
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get default organization, got error: %s", err))
@@ -143,7 +139,6 @@ func (d *OrganizationDataSource) Read(ctx context.Context, req datasource.ReadRe
143139
return
144140
}
145141
} else { // By Name
146-
var err error
147142
org, err = client.OrganizationByName(ctx, data.Name.ValueString())
148143
if err != nil {
149144
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get organization by name, got error: %s", err))
@@ -154,7 +149,7 @@ func (d *OrganizationDataSource) Read(ctx context.Context, req datasource.ReadRe
154149
return
155150
}
156151
}
157-
data.ID = types.StringValue(org.ID.String())
152+
data.ID = UUIDValue(org.ID)
158153
data.Name = types.StringValue(org.Name)
159154
data.IsDefault = types.BoolValue(org.IsDefault)
160155
data.CreatedAt = types.Int64Value(org.CreatedAt.Unix())
@@ -166,9 +161,9 @@ func (d *OrganizationDataSource) Read(ctx context.Context, req datasource.ReadRe
166161
}
167162
memberIDs := make([]attr.Value, 0, len(members))
168163
for _, member := range members {
169-
memberIDs = append(memberIDs, types.StringValue(member.UserID.String()))
164+
memberIDs = append(memberIDs, UUIDValue(member.UserID))
170165
}
171-
data.Members = types.SetValueMust(types.StringType, memberIDs)
166+
data.Members = types.SetValueMust(UUIDType, memberIDs)
172167

173168
// Save data into Terraform state
174169
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)

internal/provider/provider.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
"cdr.dev/slog"
10+
"github.com/google/uuid"
1011
"github.com/hashicorp/terraform-plugin-framework/datasource"
1112
"github.com/hashicorp/terraform-plugin-framework/function"
1213
"github.com/hashicorp/terraform-plugin-framework/provider"
@@ -31,18 +32,16 @@ type CoderdProvider struct {
3132
}
3233

3334
type CoderdProviderData struct {
34-
Client *codersdk.Client
35-
// TODO(ethanndickson): We should use a custom TFPF type for UUIDs everywhere
36-
// possible, instead of `string` and `types.String`.
37-
DefaultOrganizationID string
35+
Client *codersdk.Client
36+
DefaultOrganizationID uuid.UUID
3837
}
3938

4039
// CoderdProviderModel describes the provider data model.
4140
type CoderdProviderModel struct {
4241
URL types.String `tfsdk:"url"`
4342
Token types.String `tfsdk:"token"`
4443

45-
DefaultOrganizationID types.String `tfsdk:"default_organization_id"`
44+
DefaultOrganizationID UUID `tfsdk:"default_organization_id"`
4645
}
4746

4847
func (p *CoderdProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
@@ -63,6 +62,7 @@ func (p *CoderdProvider) Schema(ctx context.Context, req provider.SchemaRequest,
6362
},
6463
"default_organization_id": schema.StringAttribute{
6564
MarkdownDescription: "Default organization ID to use when creating resources. Defaults to the first organization the token has access to.",
65+
CustomType: UUIDType,
6666
Optional: true,
6767
},
6868
},
@@ -109,11 +109,11 @@ func (p *CoderdProvider) Configure(ctx context.Context, req provider.ConfigureRe
109109
resp.Diagnostics.AddError("default_organization_id", "failed to get default organization ID: "+err.Error())
110110
return
111111
}
112-
data.DefaultOrganizationID = types.StringValue(user.OrganizationIDs[0].String())
112+
data.DefaultOrganizationID = UUIDValue(user.OrganizationIDs[0])
113113
}
114114
providerData := &CoderdProviderData{
115115
Client: client,
116-
DefaultOrganizationID: data.DefaultOrganizationID.ValueString(),
116+
DefaultOrganizationID: data.DefaultOrganizationID.ValueUUID(),
117117
}
118118
resp.DataSourceData = providerData
119119
resp.ResourceData = providerData

0 commit comments

Comments
 (0)