Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit94f4be2

Browse files
committed
feat: add coderd_workspace_proxy resource
1 parent9b0c900 commit94f4be2

File tree

5 files changed

+355
-4
lines changed

5 files changed

+355
-4
lines changed

‎docs/data-sources/template.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
page_title:"coderd_template Data Source - coderd"
44
subcategory:""
55
description:|-
6-
An existing template on thecoder deployment
6+
An existing template on theCoder deployment.
77
---
88

99
#coderd_template (Data Source)
1010

11-
An existing template on thecoder deployment
11+
An existing template on theCoder deployment.
1212

1313

1414

@@ -19,7 +19,7 @@ An existing template on the coder deployment
1919

2020
-`id` (String) The ID of the template to retrieve. This field will be populated if a template name is supplied.
2121
-`name` (String) The name of the template to retrieve. This field will be populated if an ID is supplied.
22-
-`organization_id` (String) ID of the organization the template is associated with.
22+
-`organization_id` (String) ID of the organization the template is associated with. This field will be populated if an ID is supplied. Defaults to the provider default organization ID.
2323

2424
###Read-Only
2525

@@ -38,7 +38,7 @@ An existing template on the coder deployment
3838
-`display_name` (String) Display name of the template.
3939
-`failure_ttl_ms` (Number) Automatic cleanup TTL for failed workspace builds.
4040
-`icon` (String) URL of the template's icon.
41-
-`require_active_version` (Boolean) Whether workspaces created from the template must be up-to-datae on the latest active version.
41+
-`require_active_version` (Boolean) Whether workspaces created from the template must be up-to-date on the latest active version.
4242
-`time_til_dormant_autodelete_ms` (Number) Duration of inactivity after the workspace becomes dormant before a workspace is automatically deleted.
4343
-`time_til_dormant_ms` (Number) Duration of inactivity before a workspace is considered dormant.
4444
-`updated_at` (Number) Unix timestamp of when the template was last updated.

‎docs/resources/workspace_proxy.md‎

Lines changed: 30 additions & 0 deletions
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_workspace_proxy Resource - coderd"
4+
subcategory:""
5+
description:|-
6+
A Workspace Proxy for the Coder deployment.
7+
---
8+
9+
#coderd_workspace_proxy (Resource)
10+
11+
A Workspace Proxy for the Coder deployment.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs-->
16+
##Schema
17+
18+
###Required
19+
20+
-`icon` (String) Relative path or external URL that specifes an icon to be displayed in the dashboard.
21+
-`name` (String) Name of the workspace proxy.
22+
23+
###Optional
24+
25+
-`display_name` (String) Display name of the workspace proxy.
26+
27+
###Read-Only
28+
29+
-`id` (String) Workspace Proxy ID
30+
-`session_token` (String) Session token for the workspace proxy.

‎internal/provider/provider.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ func (p *CoderdProvider) Resources(ctx context.Context) []func() resource.Resour
124124
NewUserResource,
125125
NewGroupResource,
126126
NewTemplateResource,
127+
NewWorkspaceProxyResource,
127128
}
128129
}
129130

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/coder/coder/v2/codersdk"
8+
"github.com/hashicorp/terraform-plugin-framework/path"
9+
"github.com/hashicorp/terraform-plugin-framework/resource"
10+
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
11+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
12+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
13+
"github.com/hashicorp/terraform-plugin-framework/types"
14+
)
15+
16+
// Ensure provider defined types fully satisfy framework interfaces.
17+
var_ resource.Resource=&WorkspaceProxyResource{}
18+
var_ resource.ResourceWithImportState=&WorkspaceProxyResource{}
19+
20+
funcNewWorkspaceProxyResource() resource.Resource {
21+
return&WorkspaceProxyResource{}
22+
}
23+
24+
// WorkspaceProxyResource defines the resource implementation.
25+
typeWorkspaceProxyResourcestruct {
26+
data*CoderdProviderData
27+
}
28+
29+
// WorkspaceProxyResourceModel describes the resource data model.
30+
typeWorkspaceProxyResourceModelstruct {
31+
IDUUID`tfsdk:"id"`
32+
Name types.String`tfsdk:"name"`
33+
DisplayName types.String`tfsdk:"display_name"`
34+
Icon types.String`tfsdk:"icon"`
35+
SessionToken types.String`tfsdk:"session_token"`
36+
}
37+
38+
func (r*WorkspaceProxyResource)Metadata(ctx context.Context,req resource.MetadataRequest,resp*resource.MetadataResponse) {
39+
resp.TypeName=req.ProviderTypeName+"_workspace_proxy"
40+
}
41+
42+
func (r*WorkspaceProxyResource)Schema(ctx context.Context,req resource.SchemaRequest,resp*resource.SchemaResponse) {
43+
resp.Schema= schema.Schema{
44+
MarkdownDescription:"A Workspace Proxy for the Coder deployment.",
45+
46+
Attributes:map[string]schema.Attribute{
47+
"id": schema.StringAttribute{
48+
CustomType:UUIDType,
49+
Computed:true,
50+
MarkdownDescription:"Workspace Proxy ID",
51+
PlanModifiers: []planmodifier.String{
52+
stringplanmodifier.UseStateForUnknown(),
53+
},
54+
},
55+
"name": schema.StringAttribute{
56+
MarkdownDescription:"Name of the workspace proxy.",
57+
Required:true,
58+
},
59+
"display_name": schema.StringAttribute{
60+
MarkdownDescription:"Display name of the workspace proxy.",
61+
Optional:true,
62+
Computed:true,
63+
},
64+
"icon": schema.StringAttribute{
65+
MarkdownDescription:"Relative path or external URL that specifes an icon to be displayed in the dashboard.",
66+
Required:true,
67+
},
68+
"session_token": schema.StringAttribute{
69+
MarkdownDescription:"Session token for the workspace proxy.",
70+
Computed:true,
71+
},
72+
},
73+
}
74+
}
75+
76+
func (r*WorkspaceProxyResource)Configure(ctx context.Context,req resource.ConfigureRequest,resp*resource.ConfigureResponse) {
77+
// Prevent panic if the provider has not been configured.
78+
ifreq.ProviderData==nil {
79+
return
80+
}
81+
82+
data,ok:=req.ProviderData.(*CoderdProviderData)
83+
84+
if!ok {
85+
resp.Diagnostics.AddError(
86+
"Unexpected Resource Configure Type",
87+
fmt.Sprintf("Expected *CoderdProviderData, got: %T. Please report this issue to the provider developers.",req.ProviderData),
88+
)
89+
90+
return
91+
}
92+
93+
r.data=data
94+
}
95+
96+
func (r*WorkspaceProxyResource)Create(ctx context.Context,req resource.CreateRequest,resp*resource.CreateResponse) {
97+
vardataWorkspaceProxyResourceModel
98+
99+
// Read Terraform plan data into the model
100+
resp.Diagnostics.Append(req.Plan.Get(ctx,&data)...)
101+
ifresp.Diagnostics.HasError() {
102+
return
103+
}
104+
105+
client:=r.data.Client
106+
wsp,err:=client.CreateWorkspaceProxy(ctx, codersdk.CreateWorkspaceProxyRequest{
107+
Name:data.Name.ValueString(),
108+
DisplayName:data.DisplayName.ValueString(),
109+
Icon:data.Icon.ValueString(),
110+
})
111+
iferr!=nil {
112+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to create workspace proxy: %v",err))
113+
return
114+
}
115+
116+
data.ID=UUIDValue(wsp.Proxy.ID)
117+
data.Name=types.StringValue(wsp.Proxy.Name)
118+
data.DisplayName=types.StringValue(wsp.Proxy.DisplayName)
119+
data.Icon=types.StringValue(wsp.Proxy.IconURL)
120+
data.SessionToken=types.StringValue(wsp.ProxyToken)
121+
122+
// Save data into Terraform state
123+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
124+
}
125+
126+
func (r*WorkspaceProxyResource)Read(ctx context.Context,req resource.ReadRequest,resp*resource.ReadResponse) {
127+
vardataWorkspaceProxyResourceModel
128+
129+
// Read Terraform prior state data into the model
130+
resp.Diagnostics.Append(req.State.Get(ctx,&data)...)
131+
132+
ifresp.Diagnostics.HasError() {
133+
return
134+
}
135+
136+
client:=r.data.Client
137+
wsp,err:=client.WorkspaceProxyByID(ctx,data.ID.ValueUUID())
138+
iferr!=nil {
139+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to read workspace proxy: %v",err))
140+
return
141+
}
142+
143+
data.ID=UUIDValue(wsp.ID)
144+
data.Name=types.StringValue(wsp.Name)
145+
data.DisplayName=types.StringValue(wsp.DisplayName)
146+
data.Icon=types.StringValue(wsp.IconURL)
147+
148+
wspUpdate,err:=client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{
149+
ID:data.ID.ValueUUID(),
150+
Name:data.Name.ValueString(),
151+
DisplayName:data.DisplayName.ValueString(),
152+
Icon:data.Icon.ValueString(),
153+
RegenerateToken:true,
154+
})
155+
iferr!=nil {
156+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to refresh workspace proxy token: %v",err))
157+
return
158+
}
159+
data.SessionToken=types.StringValue(wspUpdate.ProxyToken)
160+
161+
// Save updated data into Terraform state
162+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
163+
}
164+
165+
func (r*WorkspaceProxyResource)Update(ctx context.Context,req resource.UpdateRequest,resp*resource.UpdateResponse) {
166+
vardataWorkspaceProxyResourceModel
167+
168+
// Read Terraform plan data into the model
169+
resp.Diagnostics.Append(req.Plan.Get(ctx,&data)...)
170+
171+
ifresp.Diagnostics.HasError() {
172+
return
173+
}
174+
175+
client:=r.data.Client
176+
177+
wsp,err:=client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{
178+
ID:data.ID.ValueUUID(),
179+
Name:data.Name.ValueString(),
180+
DisplayName:data.DisplayName.ValueString(),
181+
Icon:data.Icon.ValueString(),
182+
RegenerateToken:true,
183+
})
184+
iferr!=nil {
185+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to update workspace proxy: %v",err))
186+
return
187+
}
188+
189+
data.Name=types.StringValue(wsp.Proxy.Name)
190+
data.DisplayName=types.StringValue(wsp.Proxy.DisplayName)
191+
data.Icon=types.StringValue(wsp.Proxy.IconURL)
192+
data.SessionToken=types.StringValue(wsp.ProxyToken)
193+
194+
// Save updated data into Terraform state
195+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
196+
}
197+
198+
func (r*WorkspaceProxyResource)Delete(ctx context.Context,req resource.DeleteRequest,resp*resource.DeleteResponse) {
199+
vardataWorkspaceProxyResourceModel
200+
201+
// Read Terraform prior state data into the model
202+
resp.Diagnostics.Append(req.State.Get(ctx,&data)...)
203+
204+
ifresp.Diagnostics.HasError() {
205+
return
206+
}
207+
208+
client:=r.data.Client
209+
err:=client.DeleteWorkspaceProxyByID(ctx,data.ID.ValueUUID())
210+
iferr!=nil {
211+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to delete workspace proxy: %v",err))
212+
return
213+
}
214+
}
215+
216+
func (r*WorkspaceProxyResource)ImportState(ctx context.Context,req resource.ImportStateRequest,resp*resource.ImportStateResponse) {
217+
resource.ImportStatePassthroughID(ctx,path.Root("id"),req,resp)
218+
resp.Diagnostics.Append(resp.State.SetAttribute(ctx,path.Root("session_token"),req.ID)...)
219+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"os"
6+
"strings"
7+
"testing"
8+
"text/template"
9+
10+
"github.com/coder/terraform-provider-coderd/integration"
11+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
funcTestAccWorkspaceProxyResource(t*testing.T) {
16+
ifos.Getenv("TF_ACC")=="" {
17+
t.Skip("Acceptance tests are disabled.")
18+
}
19+
ctx:=context.Background()
20+
client:=integration.StartCoder(ctx,t,"ws_proxy_acc",true)
21+
22+
cfg1:=testAccWorkspaceProxyResourceConfig{
23+
URL:client.URL.String(),
24+
Token:client.SessionToken(),
25+
Name:PtrTo("example"),
26+
DisplayName:PtrTo("Example WS Proxy"),
27+
Icon:PtrTo("/emojis/1f407.png"),
28+
}
29+
30+
cfg2:=cfg1
31+
cfg2.Name=PtrTo("example-new")
32+
cfg2.DisplayName=PtrTo("Example WS Proxy New")
33+
34+
resource.Test(t, resource.TestCase{
35+
IsUnitTest:true,
36+
PreCheck:func() {testAccPreCheck(t) },
37+
ProtoV6ProviderFactories:testAccProtoV6ProviderFactories,
38+
Steps: []resource.TestStep{
39+
// Create and Read testing
40+
{
41+
Config:cfg1.String(t),
42+
Check:resource.ComposeAggregateTestCheckFunc(
43+
resource.TestCheckResourceAttrSet("coderd_workspace_proxy.test","session_token"),
44+
),
45+
},
46+
// ImportState testing
47+
{
48+
ResourceName:"coderd_workspace_proxy.test",
49+
ImportState:true,
50+
ImportStateVerify:true,
51+
// Session token gets refreshed on import
52+
ImportStateVerifyIgnore: []string{"session_token"},
53+
},
54+
// Update and Read testing
55+
{
56+
Config:cfg2.String(t),
57+
Check:resource.ComposeAggregateTestCheckFunc(
58+
resource.TestCheckResourceAttrSet("coderd_workspace_proxy.test","session_token")),
59+
},
60+
// Delete testing automatically occurs in TestCase
61+
},
62+
})
63+
}
64+
65+
typetestAccWorkspaceProxyResourceConfigstruct {
66+
URLstring
67+
Tokenstring
68+
69+
Name*string
70+
DisplayName*string
71+
Icon*string
72+
}
73+
74+
func (ctestAccWorkspaceProxyResourceConfig)String(t*testing.T)string {
75+
t.Helper()
76+
tpl:=`
77+
provider coderd {
78+
url = "{{.URL}}"
79+
token = "{{.Token}}"
80+
}
81+
82+
resource "coderd_workspace_proxy" "test" {
83+
name = {{orNull .Name}}
84+
display_name = {{orNull .DisplayName}}
85+
icon = {{orNull .Icon}}
86+
}
87+
`
88+
// Define template functions
89+
funcMap:= template.FuncMap{
90+
"orNull":PrintOrNull,
91+
}
92+
93+
buf:= strings.Builder{}
94+
tmpl,err:=template.New("test").Funcs(funcMap).Parse(tpl)
95+
require.NoError(t,err)
96+
97+
err=tmpl.Execute(&buf,c)
98+
require.NoError(t,err)
99+
100+
returnbuf.String()
101+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp