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

Commitdb725c5

Browse files
committed
feat: store coder_ai_task resource state
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
1 parente0cb4f7 commitdb725c5

File tree

4 files changed

+125
-3
lines changed

4 files changed

+125
-3
lines changed

‎coderd/provisionerdserver/provisionerdserver.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
protobuf"google.golang.org/protobuf/proto"
2929

3030
"cdr.dev/slog"
31+
3132
"github.com/coder/coder/v2/coderd/util/slice"
3233

3334
"github.com/coder/coder/v2/codersdk/drpcsdk"
@@ -1654,6 +1655,17 @@ func (s *server) completeTemplateImportJob(ctx context.Context, job database.Pro
16541655
iferr!=nil {
16551656
returnxerrors.Errorf("update template version external auth providers: %w",err)
16561657
}
1658+
err=db.UpdateTemplateVersionAITaskByJobID(ctx, database.UpdateTemplateVersionAITaskByJobIDParams{
1659+
JobID:jobID,
1660+
HasAITask: sql.NullBool{
1661+
Bool:jobType.TemplateImport.HasAiTasks,
1662+
Valid:true,
1663+
},
1664+
UpdatedAt:now,
1665+
})
1666+
iferr!=nil {
1667+
returnxerrors.Errorf("update template version external auth providers: %w",err)
1668+
}
16571669

16581670
// Process terraform values
16591671
plan:=jobType.TemplateImport.Plan
@@ -1866,6 +1878,34 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
18661878
}
18671879
}
18681880

1881+
varsidebarAppID uuid.NullUUID
1882+
iflen(jobType.WorkspaceBuild.AiTasks)==1 {
1883+
task:=jobType.WorkspaceBuild.AiTasks[0]
1884+
iftask.SidebarApp==nil {
1885+
returnxerrors.Errorf("update ai task: sidebar app is nil")
1886+
}
1887+
1888+
id,err:=uuid.Parse(task.SidebarApp.Id)
1889+
iferr!=nil {
1890+
returnxerrors.Errorf("parse sidebar app id: %w",err)
1891+
}
1892+
1893+
sidebarAppID= uuid.NullUUID{UUID:id,Valid:true}
1894+
}
1895+
1896+
err=db.UpdateWorkspaceBuildAITaskByID(ctx, database.UpdateWorkspaceBuildAITaskByIDParams{
1897+
ID:workspaceBuild.ID,
1898+
HasAITask: sql.NullBool{
1899+
Bool:len(jobType.WorkspaceBuild.AiTasks)>0,
1900+
Valid:true,
1901+
},
1902+
SidebarAppID:sidebarAppID,
1903+
UpdatedAt:now,
1904+
})
1905+
iferr!=nil {
1906+
returnxerrors.Errorf("update workspace build ai tasks flag: %w",err)
1907+
}
1908+
18691909
// Insert timings inside the transaction now
18701910
// nolint:exhaustruct // The other fields are set further down.
18711911
params:= database.InsertProvisionerJobTimingsParams{
@@ -2570,8 +2610,13 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
25702610
openIn=database.WorkspaceAppOpenInSlimWindow
25712611
}
25722612

2613+
id,err:=uuid.Parse(app.Id)
2614+
iferr!=nil {
2615+
returnxerrors.Errorf("parse app uuid: %w",err)
2616+
}
2617+
25732618
dbApp,err:=db.InsertWorkspaceApp(ctx, database.InsertWorkspaceAppParams{
2574-
ID:uuid.New(),
2619+
ID:id,
25752620
CreatedAt:dbtime.Now(),
25762621
AgentID:dbAgent.ID,
25772622
Slug:slug,

‎provisioner/terraform/executor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
361361
Plan:planJSON,
362362
ResourceReplacements:resReps,
363363
ModuleFiles:moduleFiles,
364+
HasAiTasks:state.HasAITasks,
365+
AiTasks:state.AITasks,
364366
}
365367

366368
returnmsg,nil
@@ -577,6 +579,7 @@ func (e *executor) apply(
577579
ExternalAuthProviders:state.ExternalAuthProviders,
578580
State:stateContent,
579581
Timings:e.timings.aggregate(),
582+
AiTasks:state.AITasks,
580583
},nil
581584
}
582585

‎provisioner/terraform/resources.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
"github.com/awalterschulze/gographviz"
10+
"github.com/google/uuid"
1011
tfjson"github.com/hashicorp/terraform-json"
1112
"github.com/mitchellh/mapstructure"
1213
"golang.org/x/xerrors"
@@ -93,6 +94,7 @@ type agentDisplayAppsAttributes struct {
9394

9495
// A mapping of attributes on the "coder_app" resource.
9596
typeagentAppAttributesstruct {
97+
IDstring`mapstructure:"id"`
9698
AgentIDstring`mapstructure:"agent_id"`
9799
// Slug is required in terraform, but to avoid breaking existing users we
98100
// will default to the resource name if it is not specified.
@@ -160,10 +162,29 @@ type State struct {
160162
Parameters []*proto.RichParameter
161163
Presets []*proto.Preset
162164
ExternalAuthProviders []*proto.ExternalAuthProviderResource
165+
AITasks []*proto.AITask
166+
HasAITasksbool
163167
}
164168

165169
varErrInvalidTerraformAddr=xerrors.New("invalid terraform address")
166170

171+
// hasAITaskResources is used to determine if a template has *any* `coder_ai_task` resources defined. During template
172+
// import, it's possible that none of these have `count=1` since count may be dependent on the value of a `coder_parameter`
173+
// or something else.
174+
// We need to know at template import if these resources exist to inform the frontend of their existence.
175+
funchasAITaskResources(graph*gographviz.Graph)bool {
176+
for_,node:=rangegraph.Nodes.Lookup {
177+
// Check if this node is a coder_ai_task resource
178+
iflabel,exists:=node.Attrs["label"];exists {
179+
labelValue:=strings.Trim(label,`"`)
180+
ifstrings.Contains(labelValue,"coder_ai_task.") {
181+
returntrue
182+
}
183+
}
184+
}
185+
returnfalse
186+
}
187+
167188
// ConvertState consumes Terraform state and a GraphViz representation
168189
// produced by `terraform graph` to produce resources consumable by Coder.
169190
// nolint:gocognit // This function makes more sense being large for now, until refactored.
@@ -187,6 +208,7 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
187208
// Extra array to preserve the order of rich parameters.
188209
tfResourcesRichParameters:=make([]*tfjson.StateResource,0)
189210
tfResourcesPresets:=make([]*tfjson.StateResource,0)
211+
tfResourcesAITasks:=make([]*tfjson.StateResource,0)
190212
varfindTerraformResourcesfunc(mod*tfjson.StateModule)
191213
findTerraformResources=func(mod*tfjson.StateModule) {
192214
for_,module:=rangemod.ChildModules {
@@ -199,6 +221,9 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
199221
ifresource.Type=="coder_workspace_preset" {
200222
tfResourcesPresets=append(tfResourcesPresets,resource)
201223
}
224+
ifresource.Type=="coder_ai_task" {
225+
tfResourcesAITasks=append(tfResourcesAITasks,resource)
226+
}
202227

203228
label:=convertAddressToLabel(resource.Address)
204229
iftfResourcesByLabel[label]==nil {
@@ -522,7 +547,17 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
522547
continue
523548
}
524549

550+
id:=attrs.ID
551+
ifid=="" {
552+
// This should never happen since the "id" attribute is set on creation:
553+
// https://github.com/coder/terraform-provider-coder/blob/cfa101df4635e405e66094fa7779f9a89d92f400/provider/app.go#L37
554+
logger.Warn(ctx,"coder_app's id was unexpectedly empty",slog.F("name",attrs.Name))
555+
556+
id=uuid.NewString()
557+
}
558+
525559
agent.Apps=append(agent.Apps,&proto.App{
560+
Id:id,
526561
Slug:attrs.Slug,
527562
DisplayName:attrs.DisplayName,
528563
Command:attrs.Command,
@@ -940,6 +975,27 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
940975
)
941976
}
942977

978+
// This will only pick up resources which will actually be created.
979+
aiTasks:=make([]*proto.AITask,0,len(tfResourcesAITasks))
980+
for_,resource:=rangetfResourcesAITasks {
981+
vartask provider.AITask
982+
err=mapstructure.Decode(resource.AttributeValues,&task)
983+
iferr!=nil {
984+
returnnil,xerrors.Errorf("decode coder_ai_task attributes: %w",err)
985+
}
986+
987+
iflen(task.SidebarApp)<1 {
988+
returnnil,xerrors.Errorf("coder_ai_task has no sidebar_app defined")
989+
}
990+
991+
aiTasks=append(aiTasks,&proto.AITask{
992+
Id:task.ID,
993+
SidebarApp:&proto.AITaskSidebarApp{
994+
Id:task.SidebarApp[0].ID,
995+
},
996+
})
997+
}
998+
943999
// A map is used to ensure we don't have duplicates!
9441000
externalAuthProvidersMap:=map[string]*proto.ExternalAuthProviderResource{}
9451001
for_,tfResources:=rangetfResourcesByLabel {
@@ -975,6 +1031,8 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
9751031
Parameters:parameters,
9761032
Presets:presets,
9771033
ExternalAuthProviders:externalAuthProviders,
1034+
HasAITasks:hasAITaskResources(graph),
1035+
AITasks:aiTasks,
9781036
},nil
9791037
}
9801038

‎provisionerd/runner/runner.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import (
77
"errors"
88
"fmt"
99
"reflect"
10+
"slices"
1011
"strings"
1112
"sync"
1213
"sync/atomic"
1314
"time"
1415

16+
"github.com/coder/terraform-provider-coder/v2/provider"
1517
"github.com/google/uuid"
1618
"github.com/prometheus/client_golang/prometheus"
1719
"go.opentelemetry.io/otel/attribute"
@@ -584,8 +586,6 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
584586
externalAuthProviderNames=append(externalAuthProviderNames,it.Id)
585587
}
586588

587-
// fmt.Println("completed job: template import: graph:", startProvision.Graph)
588-
589589
return&proto.CompletedJob{
590590
JobId:r.job.JobId,
591591
Type:&proto.CompletedJob_TemplateImport_{
@@ -603,6 +603,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
603603
ModuleFiles:startProvision.ModuleFiles,
604604
// ModuleFileHash will be populated if the file is uploaded async
605605
ModuleFilesHash: []byte{},
606+
HasAiTasks:startProvision.HasAITasks,
606607
},
607608
},
608609
},nil
@@ -666,6 +667,7 @@ type templateImportProvision struct {
666667
Presets []*sdkproto.Preset
667668
Plan json.RawMessage
668669
ModuleFiles []byte
670+
HasAITasksbool
669671
}
670672

671673
// Performs a dry-run provision when importing a template.
@@ -799,6 +801,15 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(
799801
}
800802
}
801803

804+
ifc.HasAiTasks {
805+
hasPromptParam:=slices.ContainsFunc(c.Parameters,func(param*sdkproto.RichParameter)bool {
806+
returnparam.Name==provider.TaskPromptParameterName
807+
})
808+
if!hasPromptParam {
809+
returnnil,xerrors.Errorf("coder_parameter named '%s' is required when 'coder_ai_task' resource is defined",provider.TaskPromptParameterName)
810+
}
811+
}
812+
802813
return&templateImportProvision{
803814
Resources:c.Resources,
804815
Parameters:c.Parameters,
@@ -807,6 +818,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters(
807818
Presets:c.Presets,
808819
Plan:c.Plan,
809820
ModuleFiles:moduleFilesData,
821+
HasAITasks:c.HasAiTasks,
810822
},nil
811823
default:
812824
returnnil,xerrors.Errorf("invalid message type %q received from provisioner",
@@ -1047,6 +1059,9 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p
10471059
},
10481060
}
10491061
}
1062+
iflen(planComplete.AiTasks)>1 {
1063+
returnnil,r.failedWorkspaceBuildf("only one 'coder_ai_task' resource can be provisioned per template")
1064+
}
10501065

10511066
r.logger.Info(context.Background(),"plan request successful",
10521067
slog.F("resource_count",len(planComplete.Resources)),
@@ -1124,6 +1139,7 @@ func (r *Runner) runWorkspaceBuild(ctx context.Context) (*proto.CompletedJob, *p
11241139
Modules:planComplete.Modules,
11251140
// Resource replacements are discovered at plan time, only.
11261141
ResourceReplacements:planComplete.ResourceReplacements,
1142+
AiTasks:applyComplete.AiTasks,
11271143
},
11281144
},
11291145
},nil

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp