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

Skip to content

Commit a00ba07

Browse files
feat: add coderd_group data source (#32)
1 parent b3458c7 commit a00ba07

File tree

4 files changed

+470
-0
lines changed

4 files changed

+470
-0
lines changed

docs/data-sources/group.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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 organization 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)
27+
- `display_name` (String)
28+
- `members` (Attributes Set) Members of the group. (see [below for nested schema](#nestedatt--members))
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'.
31+
32+
<a id="nestedatt--members"></a>
33+
### Nested Schema for `members`
34+
35+
Read-Only:
36+
37+
- `created_at` (Number) Unix timestamp of when the member was created.
38+
- `email` (String)
39+
- `id` (String)
40+
- `last_seen_at` (Number) Unix timestamp of when the member was last seen.
41+
- `login_type` (String) The login type of the member. Can be 'oidc', 'token', 'password', 'github' or 'none'.
42+
- `status` (String) The status of the member. Can be 'active', 'dormant' or 'suspended'.
43+
- `theme_preference` (String)
44+
- `username` (String)
+225
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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/datasource"
11+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
12+
"github.com/hashicorp/terraform-plugin-framework/path"
13+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
14+
"github.com/hashicorp/terraform-plugin-framework/types"
15+
)
16+
17+
// Ensure provider defined types fully satisfy framework interfaces.
18+
var _ datasource.DataSource = &GroupDataSource{}
19+
20+
func NewGroupDataSource() datasource.DataSource {
21+
return &GroupDataSource{}
22+
}
23+
24+
// GroupDataSource defines the data source implementation.
25+
type GroupDataSource struct {
26+
data *CoderdProviderData
27+
}
28+
29+
// GroupDataSourceModel describes the data source data model.
30+
type GroupDataSourceModel struct {
31+
// ID or name and organization ID must be set
32+
ID types.String `tfsdk:"id"`
33+
Name types.String `tfsdk:"name"`
34+
OrganizationID types.String `tfsdk:"organization_id"`
35+
36+
DisplayName types.String `tfsdk:"display_name"`
37+
AvatarURL types.String `tfsdk:"avatar_url"`
38+
QuotaAllowance types.Int32 `tfsdk:"quota_allowance"`
39+
Source types.String `tfsdk:"source"`
40+
Members []Member `tfsdk:"members"`
41+
}
42+
43+
type Member struct {
44+
ID types.String `tfsdk:"id"`
45+
Username types.String `tfsdk:"username"`
46+
Email types.String `tfsdk:"email"`
47+
CreatedAt types.Int64 `tfsdk:"created_at"`
48+
LastSeenAt types.Int64 `tfsdk:"last_seen_at"`
49+
Status types.String `tfsdk:"status"`
50+
LoginType types.String `tfsdk:"login_type"`
51+
ThemePreference types.String `tfsdk:"theme_preference"`
52+
}
53+
54+
func (d *GroupDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
55+
resp.TypeName = req.ProviderTypeName + "_group"
56+
}
57+
58+
func (d *GroupDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
59+
resp.Schema = schema.Schema{
60+
MarkdownDescription: "An existing group on the coder deployment.",
61+
62+
Attributes: map[string]schema.Attribute{
63+
"id": schema.StringAttribute{
64+
MarkdownDescription: "The ID of the group to retrieve. This field will be populated if a name and organization ID is supplied.",
65+
Optional: true,
66+
Computed: true,
67+
Validators: []validator.String{
68+
stringvalidator.AtLeastOneOf(path.Expressions{
69+
path.MatchRoot("name"),
70+
}...),
71+
},
72+
},
73+
"name": schema.StringAttribute{
74+
MarkdownDescription: "The name of the group to retrieve. This field will be populated if an ID is supplied.",
75+
Optional: true,
76+
Computed: true,
77+
Validators: []validator.String{},
78+
},
79+
"organization_id": schema.StringAttribute{
80+
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+
Optional: true,
82+
Computed: true,
83+
},
84+
"display_name": schema.StringAttribute{
85+
Computed: true,
86+
},
87+
"avatar_url": schema.StringAttribute{
88+
Computed: true,
89+
},
90+
"quota_allowance": schema.Int32Attribute{
91+
MarkdownDescription: "The number of quota credits to allocate to each user in the group.",
92+
Computed: true,
93+
},
94+
"source": schema.StringAttribute{
95+
MarkdownDescription: "The source of the group. Either 'oidc' or 'user'.",
96+
Computed: true,
97+
},
98+
"members": schema.SetNestedAttribute{
99+
MarkdownDescription: "Members of the group.",
100+
Computed: true,
101+
NestedObject: schema.NestedAttributeObject{
102+
Attributes: map[string]schema.Attribute{
103+
"id": schema.StringAttribute{
104+
Computed: true,
105+
},
106+
"username": schema.StringAttribute{
107+
Computed: true,
108+
},
109+
"email": schema.StringAttribute{
110+
Computed: true,
111+
},
112+
"created_at": schema.Int64Attribute{
113+
MarkdownDescription: "Unix timestamp of when the member was created.",
114+
Computed: true,
115+
},
116+
"last_seen_at": schema.Int64Attribute{
117+
MarkdownDescription: "Unix timestamp of when the member was last seen.",
118+
Computed: true,
119+
},
120+
"status": schema.StringAttribute{
121+
MarkdownDescription: "The status of the member. Can be 'active', 'dormant' or 'suspended'.",
122+
Computed: true,
123+
},
124+
"login_type": schema.StringAttribute{
125+
MarkdownDescription: "The login type of the member. Can be 'oidc', 'token', 'password', 'github' or 'none'.",
126+
Computed: true,
127+
},
128+
"theme_preference": schema.StringAttribute{
129+
Computed: true,
130+
},
131+
// TODO: Upgrade requested user type if required
132+
},
133+
},
134+
},
135+
},
136+
}
137+
}
138+
139+
func (d *GroupDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
140+
// Prevent panic if the provider has not been configured.
141+
if req.ProviderData == nil {
142+
return
143+
}
144+
145+
data, ok := req.ProviderData.(*CoderdProviderData)
146+
147+
if !ok {
148+
resp.Diagnostics.AddError(
149+
"Unexpected Data Source Configure Type",
150+
fmt.Sprintf("Expected *CoderdProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
151+
)
152+
153+
return
154+
}
155+
156+
d.data = data
157+
}
158+
159+
func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
160+
var data GroupDataSourceModel
161+
162+
// Read Terraform configuration data into the model
163+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
164+
165+
if resp.Diagnostics.HasError() {
166+
return
167+
}
168+
169+
client := d.data.Client
170+
171+
if data.OrganizationID.IsNull() {
172+
data.OrganizationID = types.StringValue(d.data.DefaultOrganizationID)
173+
}
174+
175+
var group codersdk.Group
176+
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+
183+
group, err = client.Group(ctx, groupID)
184+
if err != nil {
185+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get group by ID, got error: %s", err))
186+
return
187+
}
188+
data.Name = types.StringValue(group.Name)
189+
data.OrganizationID = types.StringValue(group.OrganizationID.String())
190+
} 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())
197+
if err != nil {
198+
resp.Diagnostics.AddError("Failed to get group by name and org ID", err.Error())
199+
return
200+
}
201+
data.ID = types.StringValue(group.ID.String())
202+
}
203+
204+
data.DisplayName = types.StringValue(group.DisplayName)
205+
data.AvatarURL = types.StringValue(group.AvatarURL)
206+
data.QuotaAllowance = types.Int32Value(int32(group.QuotaAllowance))
207+
members := make([]Member, 0, len(group.Members))
208+
for _, member := range group.Members {
209+
members = append(members, Member{
210+
ID: types.StringValue(member.ID.String()),
211+
Username: types.StringValue(member.Username),
212+
Email: types.StringValue(member.Email),
213+
CreatedAt: types.Int64Value(member.CreatedAt.Unix()),
214+
LastSeenAt: types.Int64Value(member.LastSeenAt.Unix()),
215+
Status: types.StringValue(string(member.Status)),
216+
LoginType: types.StringValue(string(member.LoginType)),
217+
ThemePreference: types.StringValue(member.ThemePreference),
218+
})
219+
}
220+
data.Members = members
221+
data.Source = types.StringValue(string(group.Source))
222+
223+
// Save data into Terraform state
224+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
225+
}

0 commit comments

Comments
 (0)