Skip to content

Commit 393c5a9

Browse files
committed
feat: add coderd_group data source
1 parent 0d1743d commit 393c5a9

File tree

4 files changed

+405
-0
lines changed

4 files changed

+405
-0
lines changed

docs/data-sources/group.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "coderd_group Data Source - coderd"
4+
subcategory: ""
5+
description: |-
6+
An existing group on the coder deployment.
7+
---
8+
9+
# coderd_group (Data Source)
10+
11+
An existing group on the coder deployment.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Optional
19+
20+
- `id` (String) The ID of the group to retrieve. This field will be populated if a name and organisation ID is supplied.
21+
- `name` (String) The name of the group to retrieve. This field will be populated if an ID is supplied.
22+
- `organization_id` (String) The organization ID that the group belongs to. This field will be populated if an ID is supplied.
23+
24+
### Read-Only
25+
26+
- `avatar_url` (String) The URL of the group's avatar.
27+
- `display_name` (String) The display name of the group.
28+
- `members` (Set of String) Members of the group, by ID.
29+
- `quota_allowance` (Number) The number of quota credits to allocate to each user in the group.
30+
- `source` (String) The source of the group. Either 'oidc' or 'user'.
+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/coder/coder/v2/codersdk"
8+
"github.com/google/uuid"
9+
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
10+
"github.com/hashicorp/terraform-plugin-framework/attr"
11+
"github.com/hashicorp/terraform-plugin-framework/datasource"
12+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
13+
"github.com/hashicorp/terraform-plugin-framework/path"
14+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
15+
"github.com/hashicorp/terraform-plugin-framework/types"
16+
)
17+
18+
// Ensure provider defined types fully satisfy framework interfaces.
19+
var _ datasource.DataSource = &GroupDataSource{}
20+
21+
func NewGroupDataSource() datasource.DataSource {
22+
return &GroupDataSource{}
23+
}
24+
25+
// GroupDataSource defines the data source implementation.
26+
type GroupDataSource struct {
27+
data *CoderdProviderData
28+
}
29+
30+
// GroupDataSourceModel describes the data source data model.
31+
type GroupDataSourceModel struct {
32+
// ID or name and organization ID must be set
33+
ID types.String `tfsdk:"id"`
34+
Name types.String `tfsdk:"name"`
35+
OrganizationID types.String `tfsdk:"organization_id"`
36+
37+
DisplayName types.String `tfsdk:"display_name"`
38+
AvatarURL types.String `tfsdk:"avatar_url"`
39+
QuotaAllowance types.Int32 `tfsdk:"quota_allowance"`
40+
Members types.Set `tfsdk:"members"`
41+
Source types.String `tfsdk:"source"`
42+
}
43+
44+
func (d *GroupDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
45+
resp.TypeName = req.ProviderTypeName + "_group"
46+
}
47+
48+
func (d *GroupDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
49+
resp.Schema = schema.Schema{
50+
MarkdownDescription: "An existing group on the coder deployment.",
51+
52+
Attributes: map[string]schema.Attribute{
53+
"id": schema.StringAttribute{
54+
MarkdownDescription: "The ID of the group to retrieve. This field will be populated if a name and organisation ID is supplied.",
55+
Optional: true,
56+
Computed: true,
57+
Validators: []validator.String{
58+
stringvalidator.AtLeastOneOf(path.Expressions{
59+
path.MatchRoot("name"),
60+
}...),
61+
},
62+
},
63+
"name": schema.StringAttribute{
64+
MarkdownDescription: "The name of the group to retrieve. This field will be populated if an ID is supplied.",
65+
Optional: true,
66+
Computed: true,
67+
Validators: []validator.String{
68+
stringvalidator.AlsoRequires(path.Expressions{
69+
path.MatchRoot("organization_id"),
70+
}...),
71+
},
72+
},
73+
"organization_id": schema.StringAttribute{
74+
MarkdownDescription: "The organization ID that the group belongs to. This field will be populated if an ID is supplied.",
75+
Optional: true,
76+
Computed: true,
77+
},
78+
"display_name": schema.StringAttribute{
79+
MarkdownDescription: "The display name of the group.",
80+
Computed: true,
81+
},
82+
"avatar_url": schema.StringAttribute{
83+
MarkdownDescription: "The URL of the group's avatar.",
84+
Computed: true,
85+
},
86+
"quota_allowance": schema.Int32Attribute{
87+
MarkdownDescription: "The number of quota credits to allocate to each user in the group.",
88+
Computed: true,
89+
},
90+
"members": schema.SetAttribute{
91+
MarkdownDescription: "Members of the group, by ID.",
92+
ElementType: types.StringType,
93+
Computed: true,
94+
},
95+
"source": schema.StringAttribute{
96+
MarkdownDescription: "The source of the group. Either 'oidc' or 'user'.",
97+
Computed: true,
98+
},
99+
},
100+
}
101+
}
102+
103+
func (d *GroupDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
104+
// Prevent panic if the provider has not been configured.
105+
if req.ProviderData == nil {
106+
return
107+
}
108+
109+
data, ok := req.ProviderData.(*CoderdProviderData)
110+
111+
if !ok {
112+
resp.Diagnostics.AddError(
113+
"Unexpected Data Source Configure Type",
114+
fmt.Sprintf("Expected *CoderdProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
115+
)
116+
117+
return
118+
}
119+
120+
d.data = data
121+
}
122+
123+
func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
124+
var data GroupDataSourceModel
125+
126+
// Read Terraform configuration data into the model
127+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
128+
129+
if resp.Diagnostics.HasError() {
130+
return
131+
}
132+
133+
client := d.data.Client
134+
135+
var group codersdk.Group
136+
if !data.ID.IsNull() {
137+
138+
groupID, err := uuid.Parse(data.ID.ValueString())
139+
if err != nil {
140+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied group ID as UUID, got error: %s", err))
141+
return
142+
}
143+
144+
group, err = client.Group(ctx, groupID)
145+
if err != nil {
146+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get group by ID, got error: %s", err))
147+
return
148+
}
149+
data.Name = types.StringValue(group.Name)
150+
data.OrganizationID = types.StringValue(group.OrganizationID.String())
151+
} else {
152+
orgID, err := uuid.Parse(data.OrganizationID.ValueString())
153+
if err != nil {
154+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied organization ID as UUID, got error: %s", err))
155+
return
156+
}
157+
group, err = client.GroupByOrgAndName(ctx, orgID, data.Name.ValueString())
158+
if err != nil {
159+
resp.Diagnostics.AddError("Failed to get group by name and org ID", err.Error())
160+
return
161+
}
162+
data.ID = types.StringValue(group.ID.String())
163+
}
164+
165+
data.DisplayName = types.StringValue(group.DisplayName)
166+
data.AvatarURL = types.StringValue(group.AvatarURL)
167+
data.QuotaAllowance = types.Int32Value(int32(group.QuotaAllowance))
168+
members := make([]attr.Value, 0, len(group.Members))
169+
for _, member := range group.Members {
170+
members = append(members, types.StringValue(member.ID.String()))
171+
}
172+
data.Members = types.SetValueMust(types.StringType, members)
173+
data.Source = types.StringValue(string(group.Source))
174+
175+
// Save data into Terraform state
176+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
177+
}

0 commit comments

Comments
 (0)