Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNM: chore!: remove default org state #134

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,5 @@ resource "coderd_template" "example" {

### Optional

- `default_organization_id` (String) Default organization ID to use when creating resources. Defaults to the first organization the token has access to.
- `token` (String) API token for communicating with the deployment. Most resource types require elevated permissions. Defaults to `$CODER_SESSION_TOKEN`.
- `url` (String) URL to the Coder deployment. Defaults to `$CODER_URL`.
2 changes: 1 addition & 1 deletion docs/resources/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ resource "coderd_template" "ubuntu-main" {
- `failure_ttl_ms` (Number) (Enterprise) The max lifetime before Coder stops all resources for failed workspaces created from this template, in milliseconds.
- `icon` (String) Relative path or external URL that specifes an icon to be displayed in the dashboard.
- `max_port_share_level` (String) (Enterprise) The maximum port share level for workspaces created from this template. Defaults to `owner` on an Enterprise deployment, or `public` otherwise.
- `organization_id` (String) The ID of the organization. Defaults to the provider's default organization
- `organization_id` (String) The ID of the organization that this template belongs to.
- `require_active_version` (Boolean) (Enterprise) Whether workspaces must be created from the active version of this template. Defaults to false.
- `time_til_dormant_autodelete_ms` (Number) (Enterprise) The max lifetime before Coder permanently deletes dormant workspaces created from this template.
- `time_til_dormant_ms` (Number) (Enterprise) The max lifetime before Coder locks inactive workspaces created from this template, in milliseconds.
Expand Down
20 changes: 6 additions & 14 deletions internal/provider/group_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func NewGroupDataSource() datasource.DataSource {

// GroupDataSource defines the data source implementation.
type GroupDataSource struct {
data *CoderdProviderData
*CoderdProviderData
}

// GroupDataSourceModel describes the data source data model.
Expand Down Expand Up @@ -155,37 +155,29 @@ func (d *GroupDataSource) Configure(ctx context.Context, req datasource.Configur
return
}

d.data = data
d.CoderdProviderData = data
}

func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data GroupDataSourceModel

// Read Terraform configuration data into the model
var data GroupDataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(CheckGroupEntitlements(ctx, d.data.Features)...)
resp.Diagnostics.Append(CheckGroupEntitlements(ctx, d.Features)...)
if resp.Diagnostics.HasError() {
return
}

client := d.data.Client

if data.OrganizationID.IsNull() {
data.OrganizationID = UUIDValue(d.data.DefaultOrganizationID)
}

var (
group codersdk.Group
err error
)
if !data.ID.IsNull() {
groupID := data.ID.ValueUUID()
group, err = client.Group(ctx, groupID)
group, err = d.Client.Group(ctx, groupID)
if err != nil {
if isNotFound(err) {
resp.Diagnostics.AddWarning("Client Warning", fmt.Sprintf("Group with ID %s not found. Marking as deleted.", groupID.String()))
Expand All @@ -198,7 +190,7 @@ func (d *GroupDataSource) Read(ctx context.Context, req datasource.ReadRequest,
data.Name = types.StringValue(group.Name)
data.OrganizationID = UUIDValue(group.OrganizationID)
} else {
group, err = client.GroupByOrgAndName(ctx, data.OrganizationID.ValueUUID(), data.Name.ValueString())
group, err = d.Client.GroupByOrgAndName(ctx, data.OrganizationID.ValueUUID(), data.Name.ValueString())
if err != nil {
if isNotFound(err) {
resp.Diagnostics.AddWarning("Client Warning", fmt.Sprintf("Group with name %s not found in organization with ID %s. Marking as deleted.", data.Name.ValueString(), data.OrganizationID.ValueString()))
Expand Down
58 changes: 17 additions & 41 deletions internal/provider/group_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewGroupResource() resource.Resource {

// GroupResource defines the resource implementation.
type GroupResource struct {
data *CoderdProviderData
*CoderdProviderData
}

// GroupResourceModel describes the resource data model.
Expand Down Expand Up @@ -137,34 +137,26 @@ func (r *GroupResource) Configure(ctx context.Context, req resource.ConfigureReq
return
}

r.data = data
r.CoderdProviderData = data
}

func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data GroupResourceModel

// Read Terraform plan data into the model
var data GroupResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(CheckGroupEntitlements(ctx, r.data.Features)...)
resp.Diagnostics.Append(CheckGroupEntitlements(ctx, r.Features)...)
if resp.Diagnostics.HasError() {
return
}

client := r.data.Client

if data.OrganizationID.IsUnknown() {
data.OrganizationID = UUIDValue(r.data.DefaultOrganizationID)
}

orgID := data.OrganizationID.ValueUUID()

tflog.Info(ctx, "creating group")
group, err := client.CreateGroup(ctx, orgID, codersdk.CreateGroupRequest{
group, err := r.Client.CreateGroup(ctx, orgID, codersdk.CreateGroupRequest{
Name: data.Name.ValueString(),
DisplayName: data.DisplayName.ValueString(),
AvatarURL: data.AvatarURL.ValueString(),
Expand All @@ -188,7 +180,7 @@ func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest,
if resp.Diagnostics.HasError() {
return
}
group, err = client.PatchGroup(ctx, group.ID, codersdk.PatchGroupRequest{
group, err = r.Client.PatchGroup(ctx, group.ID, codersdk.PatchGroupRequest{
AddUsers: members,
})
if err != nil {
Expand All @@ -202,20 +194,16 @@ func (r *GroupResource) Create(ctx context.Context, req resource.CreateRequest,
}

func (r *GroupResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data GroupResourceModel

// Read Terraform prior state data into the model
var data GroupResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

client := r.data.Client

groupID := data.ID.ValueUUID()

group, err := client.Group(ctx, groupID)
group, err := r.Client.Group(ctx, groupID)
if err != nil {
if isNotFound(err) {
resp.Diagnostics.AddWarning("Client Warning", fmt.Sprintf("Group with ID %s not found. Marking as deleted.", groupID.String()))
Expand Down Expand Up @@ -244,22 +232,16 @@ func (r *GroupResource) Read(ctx context.Context, req resource.ReadRequest, resp
}

func (r *GroupResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data GroupResourceModel

// Read Terraform plan data into the model
var data GroupResourceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

client := r.data.Client
if data.OrganizationID.IsUnknown() {
data.OrganizationID = UUIDValue(r.data.DefaultOrganizationID)
}
groupID := data.ID.ValueUUID()

group, err := client.Group(ctx, groupID)
group, err := r.Client.Group(ctx, groupID)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get group, got error: %s", err))
return
Expand All @@ -268,9 +250,7 @@ func (r *GroupResource) Update(ctx context.Context, req resource.UpdateRequest,
var remove []string
if !data.Members.IsNull() {
var plannedMembers []UUID
resp.Diagnostics.Append(
data.Members.ElementsAs(ctx, &plannedMembers, false)...,
)
resp.Diagnostics.Append(data.Members.ElementsAs(ctx, &plannedMembers, false)...)
if resp.Diagnostics.HasError() {
return
}
Expand All @@ -291,7 +271,7 @@ func (r *GroupResource) Update(ctx context.Context, req resource.UpdateRequest,
})

quotaAllowance := int(data.QuotaAllowance.ValueInt32())
_, err = client.PatchGroup(ctx, group.ID, codersdk.PatchGroupRequest{
_, err = r.Client.PatchGroup(ctx, group.ID, codersdk.PatchGroupRequest{
AddUsers: add,
RemoveUsers: remove,
Name: data.Name.ValueString(),
Expand All @@ -310,22 +290,19 @@ func (r *GroupResource) Update(ctx context.Context, req resource.UpdateRequest,
}

func (r *GroupResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data GroupResourceModel

// Read Terraform prior state data into the model
var data GroupResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

client := r.data.Client
groupID := data.ID.ValueUUID()

tflog.Info(ctx, "deleting group", map[string]any{
"id": groupID,
})
err := client.DeleteGroup(ctx, groupID)
err := r.Client.DeleteGroup(ctx, groupID)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete group, got error: %s", err))
return
Expand All @@ -335,7 +312,6 @@ func (r *GroupResource) Delete(ctx context.Context, req resource.DeleteRequest,

func (r *GroupResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
var groupID uuid.UUID
client := r.data.Client
idParts := strings.Split(req.ID, "/")
if len(idParts) == 1 {
var err error
Expand All @@ -345,12 +321,12 @@ func (r *GroupResource) ImportState(ctx context.Context, req resource.ImportStat
return
}
} else if len(idParts) == 2 {
org, err := client.OrganizationByName(ctx, idParts[0])
org, err := r.Client.OrganizationByName(ctx, idParts[0])
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to get organization with name %s: %s", idParts[0], err))
return
}
group, err := client.GroupByOrgAndName(ctx, org.ID, idParts[1])
group, err := r.Client.GroupByOrgAndName(ctx, org.ID, idParts[1])
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to get group with name %s: %s", idParts[1], err))
return
Expand All @@ -360,7 +336,7 @@ func (r *GroupResource) ImportState(ctx context.Context, req resource.ImportStat
resp.Diagnostics.AddError("Client Error", "Invalid import ID format, expected a single UUID or `<organization-name>/<group-name>`")
return
}
group, err := client.Group(ctx, groupID)
group, err := r.Client.Group(ctx, groupID)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to get imported group, got error: %s", err))
return
Expand Down
28 changes: 4 additions & 24 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"strings"

"cdr.dev/slog"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/function"
"github.com/hashicorp/terraform-plugin-framework/provider"
Expand All @@ -32,17 +31,14 @@ type CoderdProvider struct {
}

type CoderdProviderData struct {
Client *codersdk.Client
DefaultOrganizationID uuid.UUID
Features map[codersdk.FeatureName]codersdk.Feature
Client *codersdk.Client
Features map[codersdk.FeatureName]codersdk.Feature
}

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

DefaultOrganizationID UUID `tfsdk:"default_organization_id"`
}

func (p *CoderdProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
Expand All @@ -67,20 +63,13 @@ This provider is only compatible with Coder version [2.10.1](https://github.com/
MarkdownDescription: "API token for communicating with the deployment. Most resource types require elevated permissions. Defaults to `$CODER_SESSION_TOKEN`.",
Optional: true,
},
"default_organization_id": schema.StringAttribute{
MarkdownDescription: "Default organization ID to use when creating resources. Defaults to the first organization the token has access to.",
CustomType: UUIDType,
Optional: true,
},
},
}
}

func (p *CoderdProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
var data CoderdProviderModel

resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}
Expand Down Expand Up @@ -110,23 +99,14 @@ func (p *CoderdProvider) Configure(ctx context.Context, req provider.ConfigureRe
client := codersdk.New(url)
client.SetLogger(slog.Make(tfslog{}).Leveled(slog.LevelDebug))
client.SetSessionToken(data.Token.ValueString())
if data.DefaultOrganizationID.IsNull() {
user, err := client.User(ctx, codersdk.Me)
if err != nil {
resp.Diagnostics.AddError("default_organization_id", "failed to get default organization ID: "+err.Error())
return
}
data.DefaultOrganizationID = UUIDValue(user.OrganizationIDs[0])
}
entitlements, err := client.Entitlements(ctx)
if err != nil {
resp.Diagnostics.AddError("Client Error", "failed to get deployment entitlements: "+err.Error())
}

providerData := &CoderdProviderData{
Client: client,
DefaultOrganizationID: data.DefaultOrganizationID.ValueUUID(),
Features: entitlements.Features,
Client: client,
Features: entitlements.Features,
}
resp.DataSourceData = providerData
resp.ResourceData = providerData
Expand Down
19 changes: 6 additions & 13 deletions internal/provider/template_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func NewTemplateDataSource() datasource.DataSource {

// TemplateDataSource defines the data source implementation.
type TemplateDataSource struct {
data *CoderdProviderData
*CoderdProviderData
}

// TemplateDataSourceModel describes the data source data model.
Expand Down Expand Up @@ -230,36 +230,29 @@ func (d *TemplateDataSource) Configure(ctx context.Context, req datasource.Confi
return
}

d.data = data
d.CoderdProviderData = data
}

func (d *TemplateDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data TemplateDataSourceModel

// Read Terraform configuration data into the model
var data TemplateDataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

client := d.data.Client

var (
template codersdk.Template
err error
)
if data.ID.ValueUUID() != uuid.Nil {
template, err = client.Template(ctx, data.ID.ValueUUID())
template, err = d.Client.Template(ctx, data.ID.ValueUUID())
} else {
if data.OrganizationID.ValueUUID() == uuid.Nil {
data.OrganizationID = UUIDValue(d.data.DefaultOrganizationID)
}
if data.OrganizationID.ValueUUID() == uuid.Nil {
resp.Diagnostics.AddError("Client Error", "name requires organization_id to be set")
return
}
template, err = client.TemplateByName(ctx, data.OrganizationID.ValueUUID(), data.Name.ValueString())
template, err = d.Client.TemplateByName(ctx, data.OrganizationID.ValueUUID(), data.Name.ValueString())
}
if err != nil {
if isNotFound(err) {
Expand All @@ -283,7 +276,7 @@ func (d *TemplateDataSource) Read(ctx context.Context, req datasource.ReadReques
return
}

acl, err := client.TemplateACL(ctx, template.ID)
acl, err := d.Client.TemplateACL(ctx, template.ID)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to get template ACL: %s", err))
return
Expand Down
Loading
Loading