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

Commit3237486

Browse files
committed
feat: add coderd_template resource
1 parent3e749a6 commit3237486

File tree

8 files changed

+384
-0
lines changed

8 files changed

+384
-0
lines changed

‎docs/resources/template.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title:"coderd_template Resource - coderd"
4+
subcategory:""
5+
description:|-
6+
A Coder template
7+
---
8+
9+
#coderd_template (Resource)
10+
11+
A Coder template
12+
13+
14+
15+
<!-- schema generated by tfplugindocs-->
16+
##Schema
17+
18+
###Required
19+
20+
-`name` (String) The name of the template.
21+
22+
###Optional
23+
24+
-`description` (String) A description of the template.
25+
-`display_name` (String) The display name of the template. Defaults to the template name.
26+
-`organization_id` (String) The ID of the organization. Defaults to the provider's default organization
27+
-`version` (Block List) (see[below for nested schema](#nestedblock--version))
28+
29+
###Read-Only
30+
31+
-`id` (String) The ID of the template.
32+
33+
<aid="nestedblock--version"></a>
34+
###Nested Schema for`version`
35+
36+
Required:
37+
38+
-`directory` (String) A path to the directory to create the template version from. Changes in the directory contents will trigger the creation of a new template version.
39+
40+
Optional:
41+
42+
-`active` (Boolean) Whether this version is the active version of the template. Only one version can be active at a time.
43+
-`message` (String) A message describing the changes in this version of the template. Messages longer than 72 characters will be truncated..
44+
-`name` (String) The name of the template version. Automatically generated if not provided.
45+
46+
Read-Only:
47+
48+
-`directory_hash` (String)

‎integration/integration_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ func TestIntegration(t *testing.T) {
101101
assert.Equal(t,group.QuotaAllowance,100)
102102
},
103103
},
104+
{
105+
name:"template-test",
106+
preF:func(t testing.TB,c*codersdk.Client) {},
107+
assertF:func(t testing.TB,c*codersdk.Client) {},
108+
},
104109
} {
105110
t.Run(tt.name,func(t*testing.T) {
106111
client:=StartCoder(ctx,t,tt.name,true)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a

‎integration/template-test/main.tf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
terraform {
2+
required_providers {
3+
coderd={
4+
source="coder/coderd"
5+
version=">=0.0.0"
6+
}
7+
}
8+
}
9+
10+
resource"coderd_template""sample" {
11+
name="example-template"
12+
version {
13+
name="v1"
14+
directory="./example-template"
15+
}
16+
version {
17+
name="v2"
18+
directory="./example-template-2"
19+
}
20+
}

‎internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ func (p *CoderdProvider) Resources(ctx context.Context) []func() resource.Resour
123123
return []func() resource.Resource{
124124
NewUserResource,
125125
NewGroupResource,
126+
NewTemplateResource,
126127
}
127128
}
128129

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/google/uuid"
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/types"
13+
)
14+
15+
// Ensure provider defined types fully satisfy framework interfaces.
16+
var_ resource.Resource=&TemplateResource{}
17+
var_ resource.ResourceWithImportState=&TemplateResource{}
18+
19+
funcNewTemplateResource() resource.Resource {
20+
return&TemplateResource{}
21+
}
22+
23+
// TemplateResource defines the resource implementation.
24+
typeTemplateResourcestruct {
25+
data*CoderdProviderData
26+
}
27+
28+
// TemplateResourceModel describes the resource data model.
29+
typeTemplateResourceModelstruct {
30+
ID types.String`tfsdk:"id"`
31+
32+
Name types.String`tfsdk:"name"`
33+
DisplayName types.String`tfsdk:"display_name"`
34+
Description types.String`tfsdk:"description"`
35+
OrganizationID types.String`tfsdk:"organization_id"`
36+
37+
Version []TemplateVersion`tfsdk:"version"`
38+
}
39+
40+
typeTemplateVersionstruct {
41+
Name types.String`tfsdk:"name"`
42+
Message types.String`tfsdk:"message"`
43+
Directory types.String`tfsdk:"directory"`
44+
DirectoryHash types.String`tfsdk:"directory_hash"`
45+
Active types.Bool`tfsdk:"active"`
46+
}
47+
48+
func (r*TemplateResource)Metadata(ctx context.Context,req resource.MetadataRequest,resp*resource.MetadataResponse) {
49+
resp.TypeName=req.ProviderTypeName+"_template"
50+
}
51+
52+
func (r*TemplateResource)Schema(ctx context.Context,req resource.SchemaRequest,resp*resource.SchemaResponse) {
53+
resp.Schema= schema.Schema{
54+
MarkdownDescription:"A Coder template",
55+
56+
Blocks:map[string]schema.Block{
57+
"version": schema.ListNestedBlock{
58+
NestedObject: schema.NestedBlockObject{
59+
Attributes:map[string]schema.Attribute{
60+
"name": schema.StringAttribute{
61+
MarkdownDescription:"The name of the template version. Automatically generated if not provided.",
62+
Optional:true,
63+
},
64+
"message": schema.StringAttribute{
65+
MarkdownDescription:"A message describing the changes in this version of the template. Messages longer than 72 characters will be truncated..",
66+
Optional:true,
67+
},
68+
"directory": schema.StringAttribute{
69+
MarkdownDescription:"A path to the directory to create the template version from. Changes in the directory contents will trigger the creation of a new template version.",
70+
Required:true,
71+
},
72+
"directory_hash": schema.StringAttribute{
73+
Computed:true,
74+
PlanModifiers: []planmodifier.String{
75+
NewDirectoryHashPlanModifier(),
76+
},
77+
},
78+
"active": schema.BoolAttribute{
79+
MarkdownDescription:"Whether this version is the active version of the template. Only one version can be active at a time.",
80+
Optional:true,
81+
},
82+
},
83+
},
84+
},
85+
},
86+
87+
Attributes:map[string]schema.Attribute{
88+
"id": schema.StringAttribute{
89+
MarkdownDescription:"The ID of the template.",
90+
Computed:true,
91+
},
92+
"name": schema.StringAttribute{
93+
MarkdownDescription:"The name of the template.",
94+
Required:true,
95+
},
96+
"display_name": schema.StringAttribute{
97+
MarkdownDescription:"The display name of the template. Defaults to the template name.",
98+
Optional:true,
99+
},
100+
"description": schema.StringAttribute{
101+
MarkdownDescription:"A description of the template.",
102+
Optional:true,
103+
},
104+
// TODO: Rest of the fields
105+
"organization_id": schema.StringAttribute{
106+
MarkdownDescription:"The ID of the organization. Defaults to the provider's default organization",
107+
Optional:true,
108+
},
109+
},
110+
}
111+
}
112+
113+
func (r*TemplateResource)Configure(ctx context.Context,req resource.ConfigureRequest,resp*resource.ConfigureResponse) {
114+
// Prevent panic if the provider has not been configured.
115+
ifreq.ProviderData==nil {
116+
return
117+
}
118+
119+
data,ok:=req.ProviderData.(*CoderdProviderData)
120+
121+
if!ok {
122+
resp.Diagnostics.AddError(
123+
"Unexpected Resource Configure Type",
124+
fmt.Sprintf("Expected *CoderdProviderData, got: %T. Please report this issue to the provider developers.",req.ProviderData),
125+
)
126+
127+
return
128+
}
129+
130+
r.data=data
131+
}
132+
133+
func (r*TemplateResource)Create(ctx context.Context,req resource.CreateRequest,resp*resource.CreateResponse) {
134+
vardataTemplateResourceModel
135+
136+
// Read Terraform plan data into the model
137+
resp.Diagnostics.Append(req.Plan.Get(ctx,&data)...)
138+
ifresp.Diagnostics.HasError() {
139+
return
140+
}
141+
142+
// TODO: Placeholder
143+
data.ID=types.StringValue(uuid.New().String())
144+
// client := r.data.Client
145+
// orgID, err := uuid.Parse(data.OrganizationID.ValueString())
146+
// if err != nil {
147+
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse supplied organization ID as UUID, got error: %s", err))
148+
// return
149+
// }
150+
151+
// Save data into Terraform state
152+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
153+
}
154+
155+
func (r*TemplateResource)Read(ctx context.Context,req resource.ReadRequest,resp*resource.ReadResponse) {
156+
vardataTemplateResourceModel
157+
158+
// Read Terraform prior state data into the model
159+
resp.Diagnostics.Append(req.State.Get(ctx,&data)...)
160+
161+
ifresp.Diagnostics.HasError() {
162+
return
163+
}
164+
165+
// client := r.data.Client
166+
167+
// Save updated data into Terraform state
168+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
169+
}
170+
171+
func (r*TemplateResource)Update(ctx context.Context,req resource.UpdateRequest,resp*resource.UpdateResponse) {
172+
vardataTemplateResourceModel
173+
174+
// Read Terraform plan data into the model
175+
resp.Diagnostics.Append(req.Plan.Get(ctx,&data)...)
176+
177+
ifresp.Diagnostics.HasError() {
178+
return
179+
}
180+
181+
// client := r.data.Client
182+
183+
// Save updated data into Terraform state
184+
resp.Diagnostics.Append(resp.State.Set(ctx,&data)...)
185+
}
186+
187+
func (r*TemplateResource)Delete(ctx context.Context,req resource.DeleteRequest,resp*resource.DeleteResponse) {
188+
vardataTemplateResourceModel
189+
190+
// Read Terraform prior state data into the model
191+
resp.Diagnostics.Append(req.State.Get(ctx,&data)...)
192+
193+
ifresp.Diagnostics.HasError() {
194+
return
195+
}
196+
197+
// client := r.data.Client
198+
}
199+
200+
func (r*TemplateResource)ImportState(ctx context.Context,req resource.ImportStateRequest,resp*resource.ImportStateResponse) {
201+
resource.ImportStatePassthroughID(ctx,path.Root("id"),req,resp)
202+
}
203+
204+
typedirectoryHashPlanModifierstruct{}
205+
206+
funcNewDirectoryHashPlanModifier() planmodifier.String {
207+
return&directoryHashPlanModifier{}
208+
}
209+
210+
// Description implements planmodifier.String.
211+
func (m*directoryHashPlanModifier)Description(context.Context)string {
212+
return"Recomputes the directory hash if the directory has changed."
213+
}
214+
215+
// MarkdownDescription implements planmodifier.String.
216+
func (m*directoryHashPlanModifier)MarkdownDescription(ctx context.Context)string {
217+
returnm.Description(ctx)
218+
}
219+
220+
// PlanModifyString implements planmodifier.String.
221+
func (m*directoryHashPlanModifier)PlanModifyString(ctx context.Context,req planmodifier.StringRequest,resp*planmodifier.StringResponse) {
222+
vardirectory types.String
223+
diags:=req.Config.GetAttribute(ctx,req.Path.ParentPath().AtName("directory"),&directory)
224+
resp.Diagnostics.Append(diags...)
225+
ifresp.Diagnostics.HasError() {
226+
return
227+
}
228+
229+
hash,err:=computeDirectoryHash(directory.ValueString())
230+
iferr!=nil {
231+
resp.Diagnostics.AddError("Client Error",fmt.Sprintf("Failed to compute directory hash: %s",err))
232+
return
233+
}
234+
235+
resp.PlanValue=types.StringValue(hash)
236+
}
237+
238+
var_ planmodifier.String=&directoryHashPlanModifier{}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package provider
2+
3+
import (
4+
"strings"
5+
"testing"
6+
"text/template"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
funcTestAccTemplateVersionResource(t*testing.T) {}
12+
13+
typetestAccTemplateVersionResourceConfigstruct {
14+
URLstring
15+
Tokenstring
16+
}
17+
18+
func (ctestAccTemplateVersionResourceConfig)String(t*testing.T)string {
19+
t.Helper()
20+
tpl:=`
21+
provider coderd {
22+
url = "{{.URL}}"
23+
token = "{{.Token}}"
24+
}
25+
26+
resource "coderd_template_version" "test" {}
27+
`
28+
29+
funcMap:= template.FuncMap{
30+
"orNull":PrintOrNull(t),
31+
}
32+
33+
buf:= strings.Builder{}
34+
tmpl,err:=template.New("test").Funcs(funcMap).Parse(tpl)
35+
require.NoError(t,err)
36+
37+
err=tmpl.Execute(&buf,c)
38+
require.NoError(t,err)
39+
40+
returnbuf.String()
41+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp