feat: Add basic support for rich parameters to coderd and provisionerd (#5710)

This commit is contained in:
Marcin Tojek 2023-01-17 11:22:11 +01:00 committed by GitHub
parent 70fd78673d
commit 6ebadabe4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 2592 additions and 800 deletions

38
coderd/apidoc/docs.go generated
View File

@ -2516,6 +2516,44 @@ const docTemplate = `{
} }
} }
}, },
"/templateversions/{templateversion}/rich-parameters": {
"get": {
"security": [
{
"CoderSessionToken": []
}
],
"produces": [
"application/json"
],
"tags": [
"Templates"
],
"summary": "Get rich parameters by template version",
"operationId": "get-rich-parameters-by-template-version",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Template version ID",
"name": "templateversion",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/parameter.ComputedValue"
}
}
}
}
}
},
"/templateversions/{templateversion}/schema": { "/templateversions/{templateversion}/schema": {
"get": { "get": {
"security": [ "security": [

View File

@ -2216,6 +2216,40 @@
} }
} }
}, },
"/templateversions/{templateversion}/rich-parameters": {
"get": {
"security": [
{
"CoderSessionToken": []
}
],
"produces": ["application/json"],
"tags": ["Templates"],
"summary": "Get rich parameters by template version",
"operationId": "get-rich-parameters-by-template-version",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Template version ID",
"name": "templateversion",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/parameter.ComputedValue"
}
}
}
}
}
},
"/templateversions/{templateversion}/schema": { "/templateversions/{templateversion}/schema": {
"get": { "get": {
"security": [ "security": [

View File

@ -435,6 +435,7 @@ func New(options *Options) *API {
r.Patch("/cancel", api.patchCancelTemplateVersion) r.Patch("/cancel", api.patchCancelTemplateVersion)
r.Get("/schema", api.templateVersionSchema) r.Get("/schema", api.templateVersionSchema)
r.Get("/parameters", api.templateVersionParameters) r.Get("/parameters", api.templateVersionParameters)
r.Get("/rich-parameters", api.templateVersionRichParameters)
r.Get("/resources", api.templateVersionResources) r.Get("/resources", api.templateVersionResources)
r.Get("/logs", api.templateVersionLogs) r.Get("/logs", api.templateVersionLogs)
r.Route("/dry-run", func(r chi.Router) { r.Route("/dry-run", func(r chi.Router) {

View File

@ -177,6 +177,10 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
AssertAction: rbac.ActionRead, AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceTemplate.InOrg(a.Template.OrganizationID), AssertObject: rbac.ResourceTemplate.InOrg(a.Template.OrganizationID),
}, },
"GET:/api/v2/templateversions/{templateversion}/rich-parameters": {
AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceTemplate.InOrg(a.Template.OrganizationID),
},
"GET:/api/v2/templateversions/{templateversion}/resources": { "GET:/api/v2/templateversions/{templateversion}/resources": {
AssertAction: rbac.ActionRead, AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceTemplate.InOrg(a.Template.OrganizationID), AssertObject: rbac.ResourceTemplate.InOrg(a.Template.OrganizationID),

View File

@ -111,10 +111,12 @@ type data struct {
provisionerJobs []database.ProvisionerJob provisionerJobs []database.ProvisionerJob
replicas []database.Replica replicas []database.Replica
templateVersions []database.TemplateVersion templateVersions []database.TemplateVersion
templateVersionParameters []database.TemplateVersionParameter
templates []database.Template templates []database.Template
workspaceAgents []database.WorkspaceAgent workspaceAgents []database.WorkspaceAgent
workspaceApps []database.WorkspaceApp workspaceApps []database.WorkspaceApp
workspaceBuilds []database.WorkspaceBuild workspaceBuilds []database.WorkspaceBuild
workspaceBuildParameters []database.WorkspaceBuildParameter
workspaceResourceMetadata []database.WorkspaceResourceMetadatum workspaceResourceMetadata []database.WorkspaceResourceMetadatum
workspaceResources []database.WorkspaceResource workspaceResources []database.WorkspaceResource
workspaces []database.Workspace workspaces []database.Workspace
@ -1365,6 +1367,20 @@ func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(_ context.Con
return database.WorkspaceBuild{}, sql.ErrNoRows return database.WorkspaceBuild{}, sql.ErrNoRows
} }
func (q *fakeQuerier) GetWorkspaceBuildParameters(_ context.Context, workspaceBuildID uuid.UUID) ([]database.WorkspaceBuildParameter, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
params := make([]database.WorkspaceBuildParameter, 0)
for _, param := range params {
if param.WorkspaceBuildID != workspaceBuildID {
continue
}
params = append(params, param)
}
return params, nil
}
func (q *fakeQuerier) GetWorkspaceBuildsCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceBuild, error) { func (q *fakeQuerier) GetWorkspaceBuildsCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceBuild, error) {
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
@ -1656,6 +1672,20 @@ func (q *fakeQuerier) GetTemplateVersionByTemplateIDAndName(_ context.Context, a
return database.TemplateVersion{}, sql.ErrNoRows return database.TemplateVersion{}, sql.ErrNoRows
} }
func (q *fakeQuerier) GetTemplateVersionParameters(_ context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionParameter, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
parameters := make([]database.TemplateVersionParameter, 0)
for _, param := range q.templateVersionParameters {
if param.TemplateVersionID != templateVersionID {
continue
}
parameters = append(parameters, param)
}
return parameters, nil
}
func (q *fakeQuerier) GetTemplateVersionByOrganizationAndName(_ context.Context, arg database.GetTemplateVersionByOrganizationAndNameParams) (database.TemplateVersion, error) { func (q *fakeQuerier) GetTemplateVersionByOrganizationAndName(_ context.Context, arg database.GetTemplateVersionByOrganizationAndNameParams) (database.TemplateVersion, error) {
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
@ -2398,6 +2428,28 @@ func (q *fakeQuerier) InsertTemplateVersion(_ context.Context, arg database.Inse
return version, nil return version, nil
} }
func (q *fakeQuerier) InsertTemplateVersionParameter(_ context.Context, arg database.InsertTemplateVersionParameterParams) (database.TemplateVersionParameter, error) {
q.mutex.Lock()
defer q.mutex.Unlock()
//nolint:gosimple
param := database.TemplateVersionParameter{
TemplateVersionID: arg.TemplateVersionID,
Name: arg.Name,
Description: arg.Description,
Type: arg.Type,
Mutable: arg.Mutable,
DefaultValue: arg.DefaultValue,
Icon: arg.Icon,
Options: arg.Options,
ValidationRegex: arg.ValidationRegex,
ValidationMin: arg.ValidationMin,
ValidationMax: arg.ValidationMax,
}
q.templateVersionParameters = append(q.templateVersionParameters, param)
return param, nil
}
func (q *fakeQuerier) InsertProvisionerJobLogs(_ context.Context, arg database.InsertProvisionerJobLogsParams) ([]database.ProvisionerJobLog, error) { func (q *fakeQuerier) InsertProvisionerJobLogs(_ context.Context, arg database.InsertProvisionerJobLogsParams) ([]database.ProvisionerJobLog, error) {
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()
@ -2723,6 +2775,20 @@ func (q *fakeQuerier) InsertWorkspaceBuild(_ context.Context, arg database.Inser
return workspaceBuild, nil return workspaceBuild, nil
} }
func (q *fakeQuerier) InsertWorkspaceBuildParameters(_ context.Context, arg database.InsertWorkspaceBuildParametersParams) error {
q.mutex.Lock()
defer q.mutex.Unlock()
for index, name := range arg.Name {
q.workspaceBuildParameters = append(q.workspaceBuildParameters, database.WorkspaceBuildParameter{
WorkspaceBuildID: arg.WorkspaceBuildID,
Name: name,
Value: arg.Value[index],
})
}
return nil
}
func (q *fakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertWorkspaceAppParams) (database.WorkspaceApp, error) { func (q *fakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertWorkspaceAppParams) (database.WorkspaceApp, error) {
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()

View File

@ -331,6 +331,40 @@ CREATE TABLE site_configs (
value character varying(8192) NOT NULL value character varying(8192) NOT NULL
); );
CREATE TABLE template_version_parameters (
template_version_id uuid NOT NULL,
name text NOT NULL,
description text NOT NULL,
type text NOT NULL,
mutable boolean NOT NULL,
default_value text NOT NULL,
icon text NOT NULL,
options jsonb DEFAULT '[]'::jsonb NOT NULL,
validation_regex text NOT NULL,
validation_min integer NOT NULL,
validation_max integer NOT NULL
);
COMMENT ON COLUMN template_version_parameters.name IS 'Parameter name';
COMMENT ON COLUMN template_version_parameters.description IS 'Parameter description';
COMMENT ON COLUMN template_version_parameters.type IS 'Parameter type';
COMMENT ON COLUMN template_version_parameters.mutable IS 'Is parameter mutable?';
COMMENT ON COLUMN template_version_parameters.default_value IS 'Default value';
COMMENT ON COLUMN template_version_parameters.icon IS 'Icon';
COMMENT ON COLUMN template_version_parameters.options IS 'Additional options';
COMMENT ON COLUMN template_version_parameters.validation_regex IS 'Validation: regex pattern';
COMMENT ON COLUMN template_version_parameters.validation_min IS 'Validation: minimum length of value';
COMMENT ON COLUMN template_version_parameters.validation_max IS 'Validation: maximum length of value';
CREATE TABLE template_versions ( CREATE TABLE template_versions (
id uuid NOT NULL, id uuid NOT NULL,
template_id uuid, template_id uuid,
@ -443,6 +477,16 @@ CREATE TABLE workspace_apps (
external boolean DEFAULT false NOT NULL external boolean DEFAULT false NOT NULL
); );
CREATE TABLE workspace_build_parameters (
workspace_build_id uuid NOT NULL,
name text NOT NULL,
value text NOT NULL
);
COMMENT ON COLUMN workspace_build_parameters.name IS 'Parameter name';
COMMENT ON COLUMN workspace_build_parameters.value IS 'Parameter value';
CREATE TABLE workspace_builds ( CREATE TABLE workspace_builds (
id uuid NOT NULL, id uuid NOT NULL,
created_at timestamp with time zone NOT NULL, created_at timestamp with time zone NOT NULL,
@ -578,6 +622,9 @@ ALTER TABLE ONLY provisioner_jobs
ALTER TABLE ONLY site_configs ALTER TABLE ONLY site_configs
ADD CONSTRAINT site_configs_key_key UNIQUE (key); ADD CONSTRAINT site_configs_key_key UNIQUE (key);
ALTER TABLE ONLY template_version_parameters
ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
ALTER TABLE ONLY template_versions ALTER TABLE ONLY template_versions
ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id); ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id);
@ -602,6 +649,9 @@ ALTER TABLE ONLY workspace_apps
ALTER TABLE ONLY workspace_apps ALTER TABLE ONLY workspace_apps
ADD CONSTRAINT workspace_apps_pkey PRIMARY KEY (id); ADD CONSTRAINT workspace_apps_pkey PRIMARY KEY (id);
ALTER TABLE ONLY workspace_build_parameters
ADD CONSTRAINT workspace_build_parameters_workspace_build_id_name_key UNIQUE (workspace_build_id, name);
ALTER TABLE ONLY workspace_builds ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id); ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id);
@ -697,6 +747,9 @@ ALTER TABLE ONLY provisioner_job_logs
ALTER TABLE ONLY provisioner_jobs ALTER TABLE ONLY provisioner_jobs
ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
ALTER TABLE ONLY template_version_parameters
ADD CONSTRAINT template_version_parameters_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
ALTER TABLE ONLY template_versions ALTER TABLE ONLY template_versions
ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT; ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
@ -721,6 +774,9 @@ ALTER TABLE ONLY workspace_agents
ALTER TABLE ONLY workspace_apps ALTER TABLE ONLY workspace_apps
ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE; ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_build_parameters
ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_builds ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE; ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;

View File

@ -0,0 +1,3 @@
DROP TABLE template_version_parameters;
DROP TABLE workspace_build_parameters;

View File

@ -0,0 +1,35 @@
CREATE TABLE IF NOT EXISTS template_version_parameters (
template_version_id uuid not null references template_versions (id) on delete cascade,
name text not null,
description text not null,
type text not null,
mutable boolean not null,
default_value text not null,
icon text not null,
options jsonb not null default '[]'::jsonb,
validation_regex text not null,
validation_min integer not null,
validation_max integer not null,
unique (template_version_id, name)
);
COMMENT ON COLUMN template_version_parameters.name IS 'Parameter name';
COMMENT ON COLUMN template_version_parameters.description IS 'Parameter description';
COMMENT ON COLUMN template_version_parameters.type IS 'Parameter type';
COMMENT ON COLUMN template_version_parameters.mutable IS 'Is parameter mutable?';
COMMENT ON COLUMN template_version_parameters.default_value IS 'Default value';
COMMENT ON COLUMN template_version_parameters.icon IS 'Icon';
COMMENT ON COLUMN template_version_parameters.options IS 'Additional options';
COMMENT ON COLUMN template_version_parameters.validation_regex IS 'Validation: regex pattern';
COMMENT ON COLUMN template_version_parameters.validation_min IS 'Validation: minimum length of value';
COMMENT ON COLUMN template_version_parameters.validation_max IS 'Validation: maximum length of value';
CREATE TABLE IF NOT EXISTS workspace_build_parameters (
workspace_build_id uuid not null references workspace_builds (id) on delete cascade,
name text not null,
value text not null,
unique (workspace_build_id, name)
);
COMMENT ON COLUMN workspace_build_parameters.name IS 'Parameter name';
COMMENT ON COLUMN workspace_build_parameters.value IS 'Parameter value';

View File

@ -239,6 +239,8 @@ func TestMigrateUpWithFixtures(t *testing.T) {
"group_members", "group_members",
"licenses", "licenses",
"replicas", "replicas",
"template_version_parameters",
"workspace_build_parameters",
} }
s := &tableStats{s: make(map[string]int)} s := &tableStats{s: make(map[string]int)}

View File

@ -612,6 +612,30 @@ type TemplateVersion struct {
CreatedBy uuid.UUID `db:"created_by" json:"created_by"` CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
} }
type TemplateVersionParameter struct {
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
// Parameter name
Name string `db:"name" json:"name"`
// Parameter description
Description string `db:"description" json:"description"`
// Parameter type
Type string `db:"type" json:"type"`
// Is parameter mutable?
Mutable bool `db:"mutable" json:"mutable"`
// Default value
DefaultValue string `db:"default_value" json:"default_value"`
// Icon
Icon string `db:"icon" json:"icon"`
// Additional options
Options json.RawMessage `db:"options" json:"options"`
// Validation: regex pattern
ValidationRegex string `db:"validation_regex" json:"validation_regex"`
// Validation: minimum length of value
ValidationMin int32 `db:"validation_min" json:"validation_min"`
// Validation: maximum length of value
ValidationMax int32 `db:"validation_max" json:"validation_max"`
}
type User struct { type User struct {
ID uuid.UUID `db:"id" json:"id"` ID uuid.UUID `db:"id" json:"id"`
Email string `db:"email" json:"email"` Email string `db:"email" json:"email"`
@ -713,6 +737,14 @@ type WorkspaceBuild struct {
DailyCost int32 `db:"daily_cost" json:"daily_cost"` DailyCost int32 `db:"daily_cost" json:"daily_cost"`
} }
type WorkspaceBuildParameter struct {
WorkspaceBuildID uuid.UUID `db:"workspace_build_id" json:"workspace_build_id"`
// Parameter name
Name string `db:"name" json:"name"`
// Parameter value
Value string `db:"value" json:"value"`
}
type WorkspaceResource struct { type WorkspaceResource struct {
ID uuid.UUID `db:"id" json:"id"` ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`

View File

@ -87,6 +87,7 @@ type sqlcQuerier interface {
GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID) (TemplateVersion, error) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID) (TemplateVersion, error)
GetTemplateVersionByOrganizationAndName(ctx context.Context, arg GetTemplateVersionByOrganizationAndNameParams) (TemplateVersion, error) GetTemplateVersionByOrganizationAndName(ctx context.Context, arg GetTemplateVersionByOrganizationAndNameParams) (TemplateVersion, error)
GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg GetTemplateVersionByTemplateIDAndNameParams) (TemplateVersion, error) GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg GetTemplateVersionByTemplateIDAndNameParams) (TemplateVersion, error)
GetTemplateVersionParameters(ctx context.Context, templateVersionID uuid.UUID) ([]TemplateVersionParameter, error)
GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UUID) ([]TemplateVersion, error) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UUID) ([]TemplateVersion, error)
GetTemplateVersionsByTemplateID(ctx context.Context, arg GetTemplateVersionsByTemplateIDParams) ([]TemplateVersion, error) GetTemplateVersionsByTemplateID(ctx context.Context, arg GetTemplateVersionsByTemplateIDParams) ([]TemplateVersion, error)
GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error)
@ -117,6 +118,7 @@ type sqlcQuerier interface {
GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error)
GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UUID) (WorkspaceBuild, error) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UUID) (WorkspaceBuild, error)
GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Context, arg GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams) (WorkspaceBuild, error) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Context, arg GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams) (WorkspaceBuild, error)
GetWorkspaceBuildParameters(ctx context.Context, workspaceBuildID uuid.UUID) ([]WorkspaceBuildParameter, error)
GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildsByWorkspaceIDParams) ([]WorkspaceBuild, error) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildsByWorkspaceIDParams) ([]WorkspaceBuild, error)
GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error)
GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (Workspace, error) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (Workspace, error)
@ -159,12 +161,14 @@ type sqlcQuerier interface {
InsertReplica(ctx context.Context, arg InsertReplicaParams) (Replica, error) InsertReplica(ctx context.Context, arg InsertReplicaParams) (Replica, error)
InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error) InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error)
InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error) InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error)
InsertTemplateVersionParameter(ctx context.Context, arg InsertTemplateVersionParameterParams) (TemplateVersionParameter, error)
InsertUser(ctx context.Context, arg InsertUserParams) (User, error) InsertUser(ctx context.Context, arg InsertUserParams) (User, error)
InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error) InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error)
InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error) InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error)
InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error)
InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error)
InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) (WorkspaceBuild, error) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) (WorkspaceBuild, error)
InsertWorkspaceBuildParameters(ctx context.Context, arg InsertWorkspaceBuildParametersParams) error
InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error) InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error)
InsertWorkspaceResourceMetadata(ctx context.Context, arg InsertWorkspaceResourceMetadataParams) ([]WorkspaceResourceMetadatum, error) InsertWorkspaceResourceMetadata(ctx context.Context, arg InsertWorkspaceResourceMetadataParams) ([]WorkspaceResourceMetadatum, error)
ParameterValue(ctx context.Context, id uuid.UUID) (ParameterValue, error) ParameterValue(ctx context.Context, id uuid.UUID) (ParameterValue, error)

View File

@ -3542,6 +3542,121 @@ func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTempl
return i, err return i, err
} }
const getTemplateVersionParameters = `-- name: GetTemplateVersionParameters :many
SELECT template_version_id, name, description, type, mutable, default_value, icon, options, validation_regex, validation_min, validation_max FROM template_version_parameters WHERE template_version_id = $1
`
func (q *sqlQuerier) GetTemplateVersionParameters(ctx context.Context, templateVersionID uuid.UUID) ([]TemplateVersionParameter, error) {
rows, err := q.db.QueryContext(ctx, getTemplateVersionParameters, templateVersionID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TemplateVersionParameter
for rows.Next() {
var i TemplateVersionParameter
if err := rows.Scan(
&i.TemplateVersionID,
&i.Name,
&i.Description,
&i.Type,
&i.Mutable,
&i.DefaultValue,
&i.Icon,
&i.Options,
&i.ValidationRegex,
&i.ValidationMin,
&i.ValidationMax,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertTemplateVersionParameter = `-- name: InsertTemplateVersionParameter :one
INSERT INTO
template_version_parameters (
template_version_id,
name,
description,
type,
mutable,
default_value,
icon,
options,
validation_regex,
validation_min,
validation_max
)
VALUES
(
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10,
$11
) RETURNING template_version_id, name, description, type, mutable, default_value, icon, options, validation_regex, validation_min, validation_max
`
type InsertTemplateVersionParameterParams struct {
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
Name string `db:"name" json:"name"`
Description string `db:"description" json:"description"`
Type string `db:"type" json:"type"`
Mutable bool `db:"mutable" json:"mutable"`
DefaultValue string `db:"default_value" json:"default_value"`
Icon string `db:"icon" json:"icon"`
Options json.RawMessage `db:"options" json:"options"`
ValidationRegex string `db:"validation_regex" json:"validation_regex"`
ValidationMin int32 `db:"validation_min" json:"validation_min"`
ValidationMax int32 `db:"validation_max" json:"validation_max"`
}
func (q *sqlQuerier) InsertTemplateVersionParameter(ctx context.Context, arg InsertTemplateVersionParameterParams) (TemplateVersionParameter, error) {
row := q.db.QueryRowContext(ctx, insertTemplateVersionParameter,
arg.TemplateVersionID,
arg.Name,
arg.Description,
arg.Type,
arg.Mutable,
arg.DefaultValue,
arg.Icon,
arg.Options,
arg.ValidationRegex,
arg.ValidationMin,
arg.ValidationMax,
)
var i TemplateVersionParameter
err := row.Scan(
&i.TemplateVersionID,
&i.Name,
&i.Description,
&i.Type,
&i.Mutable,
&i.DefaultValue,
&i.Icon,
&i.Options,
&i.ValidationRegex,
&i.ValidationMin,
&i.ValidationMax,
)
return i, err
}
const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one
SELECT SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
@ -5384,6 +5499,59 @@ func (q *sqlQuerier) UpdateWorkspaceAppHealthByID(ctx context.Context, arg Updat
return err return err
} }
const getWorkspaceBuildParameters = `-- name: GetWorkspaceBuildParameters :many
SELECT
workspace_build_id, name, value
FROM
workspace_build_parameters
WHERE
workspace_build_id = $1
`
func (q *sqlQuerier) GetWorkspaceBuildParameters(ctx context.Context, workspaceBuildID uuid.UUID) ([]WorkspaceBuildParameter, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceBuildParameters, workspaceBuildID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceBuildParameter
for rows.Next() {
var i WorkspaceBuildParameter
if err := rows.Scan(&i.WorkspaceBuildID, &i.Name, &i.Value); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertWorkspaceBuildParameters = `-- name: InsertWorkspaceBuildParameters :exec
INSERT INTO
workspace_build_parameters (workspace_build_id, name, value)
SELECT
$1 :: uuid AS workspace_build_id,
unnest($2 :: text[]) AS name,
unnest($3 :: text[]) AS value
RETURNING workspace_build_id, name, value
`
type InsertWorkspaceBuildParametersParams struct {
WorkspaceBuildID uuid.UUID `db:"workspace_build_id" json:"workspace_build_id"`
Name []string `db:"name" json:"name"`
Value []string `db:"value" json:"value"`
}
func (q *sqlQuerier) InsertWorkspaceBuildParameters(ctx context.Context, arg InsertWorkspaceBuildParametersParams) error {
_, err := q.db.ExecContext(ctx, insertWorkspaceBuildParameters, arg.WorkspaceBuildID, pq.Array(arg.Name), pq.Array(arg.Value))
return err
}
const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one
SELECT SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost

View File

@ -0,0 +1,32 @@
-- name: InsertTemplateVersionParameter :one
INSERT INTO
template_version_parameters (
template_version_id,
name,
description,
type,
mutable,
default_value,
icon,
options,
validation_regex,
validation_min,
validation_max
)
VALUES
(
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10,
$11
) RETURNING *;
-- name: GetTemplateVersionParameters :many
SELECT * FROM template_version_parameters WHERE template_version_id = $1;

View File

@ -0,0 +1,16 @@
-- name: InsertWorkspaceBuildParameters :exec
INSERT INTO
workspace_build_parameters (workspace_build_id, name, value)
SELECT
@workspace_build_id :: uuid AS workspace_build_id,
unnest(@name :: text[]) AS name,
unnest(@value :: text[]) AS value
RETURNING *;
-- name: GetWorkspaceBuildParameters :many
SELECT
*
FROM
workspace_build_parameters
WHERE
workspace_build_id = $1;

View File

@ -6,26 +6,28 @@ type UniqueConstraint string
// UniqueConstraint enums. // UniqueConstraint enums.
const ( const (
UniqueFilesHashCreatedByKey UniqueConstraint = "files_hash_created_by_key" // ALTER TABLE ONLY files ADD CONSTRAINT files_hash_created_by_key UNIQUE (hash, created_by); UniqueFilesHashCreatedByKey UniqueConstraint = "files_hash_created_by_key" // ALTER TABLE ONLY files ADD CONSTRAINT files_hash_created_by_key UNIQUE (hash, created_by);
UniqueGitAuthLinksProviderIDUserIDKey UniqueConstraint = "git_auth_links_provider_id_user_id_key" // ALTER TABLE ONLY git_auth_links ADD CONSTRAINT git_auth_links_provider_id_user_id_key UNIQUE (provider_id, user_id); UniqueGitAuthLinksProviderIDUserIDKey UniqueConstraint = "git_auth_links_provider_id_user_id_key" // ALTER TABLE ONLY git_auth_links ADD CONSTRAINT git_auth_links_provider_id_user_id_key UNIQUE (provider_id, user_id);
UniqueGroupMembersUserIDGroupIDKey UniqueConstraint = "group_members_user_id_group_id_key" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_group_id_key UNIQUE (user_id, group_id); UniqueGroupMembersUserIDGroupIDKey UniqueConstraint = "group_members_user_id_group_id_key" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_group_id_key UNIQUE (user_id, group_id);
UniqueGroupsNameOrganizationIDKey UniqueConstraint = "groups_name_organization_id_key" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_name_organization_id_key UNIQUE (name, organization_id); UniqueGroupsNameOrganizationIDKey UniqueConstraint = "groups_name_organization_id_key" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_name_organization_id_key UNIQUE (name, organization_id);
UniqueLicensesJWTKey UniqueConstraint = "licenses_jwt_key" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_jwt_key UNIQUE (jwt); UniqueLicensesJWTKey UniqueConstraint = "licenses_jwt_key" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_jwt_key UNIQUE (jwt);
UniqueParameterSchemasJobIDNameKey UniqueConstraint = "parameter_schemas_job_id_name_key" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_name_key UNIQUE (job_id, name); UniqueParameterSchemasJobIDNameKey UniqueConstraint = "parameter_schemas_job_id_name_key" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_name_key UNIQUE (job_id, name);
UniqueParameterValuesScopeIDNameKey UniqueConstraint = "parameter_values_scope_id_name_key" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_scope_id_name_key UNIQUE (scope_id, name); UniqueParameterValuesScopeIDNameKey UniqueConstraint = "parameter_values_scope_id_name_key" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_scope_id_name_key UNIQUE (scope_id, name);
UniqueProvisionerDaemonsNameKey UniqueConstraint = "provisioner_daemons_name_key" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_name_key UNIQUE (name); UniqueProvisionerDaemonsNameKey UniqueConstraint = "provisioner_daemons_name_key" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_name_key UNIQUE (name);
UniqueSiteConfigsKeyKey UniqueConstraint = "site_configs_key_key" // ALTER TABLE ONLY site_configs ADD CONSTRAINT site_configs_key_key UNIQUE (key); UniqueSiteConfigsKeyKey UniqueConstraint = "site_configs_key_key" // ALTER TABLE ONLY site_configs ADD CONSTRAINT site_configs_key_key UNIQUE (key);
UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name); UniqueTemplateVersionParametersTemplateVersionIDNameKey UniqueConstraint = "template_version_parameters_template_version_id_name_key" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
UniqueWorkspaceAppsAgentIDSlugIndex UniqueConstraint = "workspace_apps_agent_id_slug_idx" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_slug_idx UNIQUE (agent_id, slug); UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name);
UniqueWorkspaceBuildsJobIDKey UniqueConstraint = "workspace_builds_job_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id); UniqueWorkspaceAppsAgentIDSlugIndex UniqueConstraint = "workspace_apps_agent_id_slug_idx" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_slug_idx UNIQUE (agent_id, slug);
UniqueWorkspaceBuildsWorkspaceIDBuildNumberKey UniqueConstraint = "workspace_builds_workspace_id_build_number_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_build_number_key UNIQUE (workspace_id, build_number); UniqueWorkspaceBuildParametersWorkspaceBuildIDNameKey UniqueConstraint = "workspace_build_parameters_workspace_build_id_name_key" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_name_key UNIQUE (workspace_build_id, name);
UniqueWorkspaceResourceMetadataName UniqueConstraint = "workspace_resource_metadata_name" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_name UNIQUE (workspace_resource_id, key); UniqueWorkspaceBuildsJobIDKey UniqueConstraint = "workspace_builds_job_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id);
UniqueIndexOrganizationName UniqueConstraint = "idx_organization_name" // CREATE UNIQUE INDEX idx_organization_name ON organizations USING btree (name); UniqueWorkspaceBuildsWorkspaceIDBuildNumberKey UniqueConstraint = "workspace_builds_workspace_id_build_number_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_build_number_key UNIQUE (workspace_id, build_number);
UniqueIndexOrganizationNameLower UniqueConstraint = "idx_organization_name_lower" // CREATE UNIQUE INDEX idx_organization_name_lower ON organizations USING btree (lower(name)); UniqueWorkspaceResourceMetadataName UniqueConstraint = "workspace_resource_metadata_name" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_name UNIQUE (workspace_resource_id, key);
UniqueIndexUsersEmail UniqueConstraint = "idx_users_email" // CREATE UNIQUE INDEX idx_users_email ON users USING btree (email) WHERE (deleted = false); UniqueIndexOrganizationName UniqueConstraint = "idx_organization_name" // CREATE UNIQUE INDEX idx_organization_name ON organizations USING btree (name);
UniqueIndexUsersUsername UniqueConstraint = "idx_users_username" // CREATE UNIQUE INDEX idx_users_username ON users USING btree (username) WHERE (deleted = false); UniqueIndexOrganizationNameLower UniqueConstraint = "idx_organization_name_lower" // CREATE UNIQUE INDEX idx_organization_name_lower ON organizations USING btree (lower(name));
UniqueTemplatesOrganizationIDNameIndex UniqueConstraint = "templates_organization_id_name_idx" // CREATE UNIQUE INDEX templates_organization_id_name_idx ON templates USING btree (organization_id, lower((name)::text)) WHERE (deleted = false); UniqueIndexUsersEmail UniqueConstraint = "idx_users_email" // CREATE UNIQUE INDEX idx_users_email ON users USING btree (email) WHERE (deleted = false);
UniqueUsersEmailLowerIndex UniqueConstraint = "users_email_lower_idx" // CREATE UNIQUE INDEX users_email_lower_idx ON users USING btree (lower(email)) WHERE (deleted = false); UniqueIndexUsersUsername UniqueConstraint = "idx_users_username" // CREATE UNIQUE INDEX idx_users_username ON users USING btree (username) WHERE (deleted = false);
UniqueUsersUsernameLowerIndex UniqueConstraint = "users_username_lower_idx" // CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username)) WHERE (deleted = false); UniqueTemplatesOrganizationIDNameIndex UniqueConstraint = "templates_organization_id_name_idx" // CREATE UNIQUE INDEX templates_organization_id_name_idx ON templates USING btree (organization_id, lower((name)::text)) WHERE (deleted = false);
UniqueWorkspacesOwnerIDLowerIndex UniqueConstraint = "workspaces_owner_id_lower_idx" // CREATE UNIQUE INDEX workspaces_owner_id_lower_idx ON workspaces USING btree (owner_id, lower((name)::text)) WHERE (deleted = false); UniqueUsersEmailLowerIndex UniqueConstraint = "users_email_lower_idx" // CREATE UNIQUE INDEX users_email_lower_idx ON users USING btree (lower(email)) WHERE (deleted = false);
UniqueUsersUsernameLowerIndex UniqueConstraint = "users_username_lower_idx" // CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username)) WHERE (deleted = false);
UniqueWorkspacesOwnerIDLowerIndex UniqueConstraint = "workspaces_owner_id_lower_idx" // CREATE UNIQUE INDEX workspaces_owner_id_lower_idx ON workspaces USING btree (owner_id, lower((name)::text)) WHERE (deleted = false);
) )

View File

@ -181,12 +181,18 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
return nil, failJob(fmt.Sprintf("convert workspace transition: %s", err)) return nil, failJob(fmt.Sprintf("convert workspace transition: %s", err))
} }
workspaceBuildParameters, err := server.Database.GetWorkspaceBuildParameters(ctx, workspaceBuild.ID)
if err != nil {
return nil, failJob(fmt.Sprintf("get workspace build parameters: %s", err))
}
protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{ protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{
WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{ WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{
WorkspaceBuildId: workspaceBuild.ID.String(), WorkspaceBuildId: workspaceBuild.ID.String(),
WorkspaceName: workspace.Name, WorkspaceName: workspace.Name,
State: workspaceBuild.ProvisionerState, State: workspaceBuild.ProvisionerState,
ParameterValues: protoParameters, ParameterValues: protoParameters,
RichParameterValues: convertRichParameterValues(workspaceBuildParameters),
Metadata: &sdkproto.Provision_Metadata{ Metadata: &sdkproto.Provision_Metadata{
CoderUrl: server.AccessURL.String(), CoderUrl: server.AccessURL.String(),
WorkspaceTransition: transition, WorkspaceTransition: transition,
@ -597,6 +603,12 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
switch jobType := completed.Type.(type) { switch jobType := completed.Type.(type) {
case *proto.CompletedJob_TemplateImport_: case *proto.CompletedJob_TemplateImport_:
var input TemplateVersionImportJob
err = json.Unmarshal(job.Input, &input)
if err != nil {
return nil, xerrors.Errorf("template version ID is expected: %w", err)
}
for transition, resources := range map[database.WorkspaceTransition][]*sdkproto.Resource{ for transition, resources := range map[database.WorkspaceTransition][]*sdkproto.Resource{
database.WorkspaceTransitionStart: jobType.TemplateImport.StartResources, database.WorkspaceTransitionStart: jobType.TemplateImport.StartResources,
database.WorkspaceTransitionStop: jobType.TemplateImport.StopResources, database.WorkspaceTransitionStop: jobType.TemplateImport.StopResources,
@ -615,6 +627,33 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
} }
} }
for _, richParameter := range jobType.TemplateImport.RichParameters {
server.Logger.Info(ctx, "inserting template import job parameter",
slog.F("job_id", job.ID.String()),
slog.F("parameter_name", richParameter.Name),
)
options, err := json.Marshal(richParameter.Options)
if err != nil {
return nil, xerrors.Errorf("marshal parameter options: %w", err)
}
_, err = server.Database.InsertTemplateVersionParameter(ctx, database.InsertTemplateVersionParameterParams{
TemplateVersionID: input.TemplateVersionID,
Name: richParameter.Name,
Description: richParameter.Description,
Type: richParameter.Type,
Mutable: richParameter.Mutable,
DefaultValue: richParameter.DefaultValue,
Icon: richParameter.Icon,
Options: options,
ValidationRegex: richParameter.ValidationRegex,
ValidationMin: richParameter.ValidationMin,
ValidationMax: richParameter.ValidationMax,
})
if err != nil {
return nil, xerrors.Errorf("insert parameter: %w", err)
}
}
err = server.Database.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{ err = server.Database.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{
ID: jobID, ID: jobID,
UpdatedAt: database.Now(), UpdatedAt: database.Now(),
@ -1056,6 +1095,17 @@ func convertLogSource(logSource proto.LogSource) (database.LogSource, error) {
} }
} }
func convertRichParameterValues(workspaceBuildParameters []database.WorkspaceBuildParameter) []*sdkproto.RichParameterValue {
protoParameters := make([]*sdkproto.RichParameterValue, len(workspaceBuildParameters))
for i, buildParameter := range workspaceBuildParameters {
protoParameters[i] = &sdkproto.RichParameterValue{
Name: buildParameter.Name,
Value: buildParameter.Value,
}
}
return protoParameters
}
func convertComputedParameterValues(parameters []parameter.ComputedValue) ([]*sdkproto.ParameterValue, error) { func convertComputedParameterValues(parameters []parameter.ComputedValue) ([]*sdkproto.ParameterValue, error) {
protoParameters := make([]*sdkproto.ParameterValue, len(parameters)) protoParameters := make([]*sdkproto.ParameterValue, len(parameters))
for i, computedParameter := range parameters { for i, computedParameter := range parameters {
@ -1113,6 +1163,10 @@ func auditActionFromTransition(transition database.WorkspaceTransition) database
} }
} }
type TemplateVersionImportJob struct {
TemplateVersionID uuid.UUID `json:"template_version_id"`
}
// WorkspaceProvisionJob is the payload for the "workspace_provision" job type. // WorkspaceProvisionJob is the payload for the "workspace_provision" job type.
type WorkspaceProvisionJob struct { type WorkspaceProvisionJob struct {
WorkspaceBuildID uuid.UUID `json:"workspace_build_id"` WorkspaceBuildID uuid.UUID `json:"workspace_build_id"`

View File

@ -580,6 +580,7 @@ func TestCompleteJob(t *testing.T) {
job, err := srv.Database.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ job, err := srv.Database.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
ID: uuid.New(), ID: uuid.New(),
Provisioner: database.ProvisionerTypeEcho, Provisioner: database.ProvisionerTypeEcho,
Input: []byte(`{"template_version_id": "` + uuid.NewString() + `"}`),
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = srv.Database.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ _, err = srv.Database.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{

View File

@ -26,6 +26,7 @@ import (
"github.com/coder/coder/coderd/rbac" "github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk" "github.com/coder/coder/codersdk"
"github.com/coder/coder/examples" "github.com/coder/coder/examples"
sdkproto "github.com/coder/coder/provisionersdk/proto"
) )
// @Summary Get template version by ID // @Summary Get template version by ID
@ -192,6 +193,59 @@ func (api *API) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, apiSchemas) httpapi.Write(ctx, rw, http.StatusOK, apiSchemas)
} }
// @Summary Get rich parameters by template version
// @ID get-rich-parameters-by-template-version
// @Security CoderSessionToken
// @Produce json
// @Tags Templates
// @Param templateversion path string true "Template version ID" format(uuid)
// @Success 200 {array} parameter.ComputedValue
// @Router /templateversions/{templateversion}/rich-parameters [get]
func (api *API) templateVersionRichParameters(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
templateVersion := httpmw.TemplateVersionParam(r)
template := httpmw.TemplateParam(r)
if !api.Authorize(r, rbac.ActionRead, templateVersion.RBACObject(template)) {
httpapi.ResourceNotFound(rw)
return
}
job, err := api.Database.GetProvisionerJobByID(ctx, templateVersion.JobID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.",
Detail: err.Error(),
})
return
}
if !job.CompletedAt.Valid {
httpapi.Write(ctx, rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job hasn't completed!",
})
return
}
dbParameters, err := api.Database.GetTemplateVersionParameters(ctx, templateVersion.ID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version parameters.",
Detail: err.Error(),
})
return
}
params := make([]codersdk.TemplateVersionParameter, 0)
for _, dbParameter := range dbParameters {
param, err := convertTemplateVersionParameter(dbParameter)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting template version parameter.",
Detail: err.Error(),
})
return
}
params = append(params, param)
}
httpapi.Write(ctx, rw, http.StatusOK, params)
}
// @Summary Get parameters by template version // @Summary Get parameters by template version
// @ID get-parameters-by-template-version // @ID get-parameters-by-template-version
// @Security CoderSessionToken // @Security CoderSessionToken
@ -1142,6 +1196,14 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
} }
} }
templateVersionID := uuid.New()
jobInput, err := json.Marshal(provisionerdserver.TemplateVersionImportJob{
TemplateVersionID: templateVersionID,
})
if err != nil {
return xerrors.Errorf("marshal job input: %w", err)
}
provisionerJob, err = tx.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ provisionerJob, err = tx.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
ID: jobID, ID: jobID,
CreatedAt: database.Now(), CreatedAt: database.Now(),
@ -1152,7 +1214,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
StorageMethod: database.ProvisionerStorageMethodFile, StorageMethod: database.ProvisionerStorageMethodFile,
FileID: file.ID, FileID: file.ID,
Type: database.ProvisionerJobTypeTemplateVersionImport, Type: database.ProvisionerJobTypeTemplateVersionImport,
Input: []byte{'{', '}'}, Input: jobInput,
Tags: tags, Tags: tags,
}) })
if err != nil { if err != nil {
@ -1172,7 +1234,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
} }
templateVersion, err = tx.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{ templateVersion, err = tx.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{
ID: uuid.New(), ID: templateVersionID,
TemplateID: templateID, TemplateID: templateID,
OrganizationID: organization.ID, OrganizationID: organization.ID,
CreatedAt: database.Now(), CreatedAt: database.Now(),
@ -1307,6 +1369,35 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi
} }
} }
func convertTemplateVersionParameter(param database.TemplateVersionParameter) (codersdk.TemplateVersionParameter, error) {
var protoOptions []*sdkproto.RichParameterOption
err := json.Unmarshal(param.Options, &protoOptions)
if err != nil {
return codersdk.TemplateVersionParameter{}, err
}
options := make([]codersdk.TemplateVersionParameterOption, 0)
for _, option := range protoOptions {
options = append(options, codersdk.TemplateVersionParameterOption{
Name: option.Name,
Description: option.Description,
Value: option.Value,
Icon: option.Icon,
})
}
return codersdk.TemplateVersionParameter{
Name: param.Name,
Description: param.Description,
Type: param.Type,
Mutable: param.Mutable,
DefaultValue: param.DefaultValue,
Icon: param.Icon,
Options: options,
ValidationRegex: param.ValidationRegex,
ValidationMin: param.ValidationMin,
ValidationMax: param.ValidationMax,
}, nil
}
func watchTemplateChannel(id uuid.UUID) string { func watchTemplateChannel(id uuid.UUID) string {
return fmt.Sprintf("template:%s", id) return fmt.Sprintf("template:%s", id)
} }

View File

@ -632,3 +632,56 @@ func TestWorkspaceBuildStatus(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, codersdk.WorkspaceStatusDeleted, workspace.LatestBuild.Status) require.EqualValues(t, codersdk.WorkspaceStatusDeleted, workspace.LatestBuild.Status)
} }
func TestWorkspaceBuildWithRichParameters(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionPlan: []*proto.Provision_Response{
{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
Parameters: []*proto.RichParameter{
{
Name: "first_parameter",
Description: "This is first parameter",
},
{
Name: "second_parameter",
Description: "This is second parameter",
},
},
},
},
}},
})
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
richParameters, err := client.TemplateVersionRichParameters(ctx, version.ID)
require.NoError(t, err)
require.Len(t, richParameters, 2)
require.Equal(t, richParameters[0].Name, "first_parameter")
require.Equal(t, richParameters[1].Name, "second_parameter")
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
cwr.RichParameterValues = []codersdk.WorkspaceBuildParameter{
{
Name: "first_parameter",
Value: "1",
},
{
Name: "second_parameter",
Value: "2",
},
}
})
_, err = client.WorkspaceBuild(ctx, workspace.LatestBuild.ID)
require.NoError(t, err)
}

View File

@ -87,7 +87,8 @@ type CreateWorkspaceRequest struct {
TTLMillis *int64 `json:"ttl_ms,omitempty"` TTLMillis *int64 `json:"ttl_ms,omitempty"`
// ParameterValues allows for additional parameters to be provided // ParameterValues allows for additional parameters to be provided
// during the initial provision. // during the initial provision.
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"` ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
RichParameterValues []WorkspaceBuildParameter `json:"rich_parameter_values,omitempty"`
} }
func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) { func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) {

View File

@ -24,6 +24,29 @@ type TemplateVersion struct {
CreatedBy User `json:"created_by"` CreatedBy User `json:"created_by"`
} }
// TemplateVersionParameter represents a parameter for a template version.
type TemplateVersionParameter struct {
Name string `json:"name"`
Description string `json:"description"`
Type string `json:"type"`
Mutable bool `json:"mutable"`
DefaultValue string `json:"default_value"`
Icon string `json:"icon"`
Options []TemplateVersionParameterOption `json:"options"`
ValidationError string `json:"validation_error"`
ValidationRegex string `json:"validation_regex"`
ValidationMin int32 `json:"validation_min"`
ValidationMax int32 `json:"validation_max"`
}
// TemplateVersionParameterOption represents a selectable option for a template parameter.
type TemplateVersionParameterOption struct {
Name string `json:"name"`
Description string `json:"description"`
Value string `json:"value"`
Icon string `json:"icon"`
}
// TemplateVersion returns a template version by ID. // TemplateVersion returns a template version by ID.
func (c *Client) TemplateVersion(ctx context.Context, id uuid.UUID) (TemplateVersion, error) { func (c *Client) TemplateVersion(ctx context.Context, id uuid.UUID) (TemplateVersion, error) {
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s", id), nil) res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s", id), nil)
@ -51,6 +74,20 @@ func (c *Client) CancelTemplateVersion(ctx context.Context, version uuid.UUID) e
return nil return nil
} }
// TemplateVersionParameters returns parameters a template version exposes.
func (c *Client) TemplateVersionRichParameters(ctx context.Context, version uuid.UUID) ([]TemplateVersionParameter, error) {
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/rich-parameters", version), nil)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, readBodyAsError(res)
}
var params []TemplateVersionParameter
return params, json.NewDecoder(res.Body).Decode(&params)
}
// TemplateVersionSchema returns schemas for a template version by ID. // TemplateVersionSchema returns schemas for a template version by ID.
func (c *Client) TemplateVersionSchema(ctx context.Context, version uuid.UUID) ([]ParameterSchema, error) { func (c *Client) TemplateVersionSchema(ctx context.Context, version uuid.UUID) ([]ParameterSchema, error) {
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/schema", version), nil) res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/schema", version), nil)

View File

@ -95,6 +95,12 @@ type WorkspaceResourceMetadata struct {
Sensitive bool `json:"sensitive"` Sensitive bool `json:"sensitive"`
} }
// WorkspaceBuildParameter represents a parameter specific for a workspace build.
type WorkspaceBuildParameter struct {
Name string `json:"name"`
Value string `json:"value"`
}
// WorkspaceBuild returns a single workspace build for a workspace. // WorkspaceBuild returns a single workspace build for a workspace.
// If history is "", the latest version is returned. // If history is "", the latest version is returned.
func (c *Client) WorkspaceBuild(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error) { func (c *Client) WorkspaceBuild(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error) {

View File

@ -2032,6 +2032,87 @@ Status Code **200**
To perform this operation, you must be authenticated. [Learn more](authentication.md). To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get rich parameters by template version
### Code samples
```shell
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/rich-parameters \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /templateversions/{templateversion}/rich-parameters`
### Parameters
| Name | In | Type | Required | Description |
| ----------------- | ---- | ------------ | -------- | ------------------- |
| `templateversion` | path | string(uuid) | true | Template version ID |
### Example responses
> 200 Response
```json
[
{
"created_at": "string",
"default_source_value": true,
"destination_scheme": "none",
"id": "string",
"name": "string",
"schema_id": "string",
"scope": "template",
"scope_id": "string",
"source_scheme": "none",
"source_value": "string",
"updated_at": "string"
}
]
```
### Responses
| Status | Meaning | Description | Schema |
| ------ | ------------------------------------------------------- | ----------- | --------------------------------------------------------------------- |
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [parameter.ComputedValue](schemas.md#parametercomputedvalue) |
<h3 id="get-rich-parameters-by-template-version-responseschema">Response Schema</h3>
Status Code **200**
| Name | Type | Required | Restrictions | Description |
| ------------------------ | ------------------------------------------------------------------------------------ | -------- | ------------ | ----------- |
| `[array item]` | array | false | | |
| `» created_at` | string | false | | |
| `» default_source_value` | boolean | false | | |
| `» destination_scheme` | [database.ParameterDestinationScheme](schemas.md#databaseparameterdestinationscheme) | false | | |
| `» id` | string | false | | |
| `» name` | string | false | | |
| `» schema_id` | string | false | | |
| `» scope` | [database.ParameterScope](schemas.md#databaseparameterscope) | false | | |
| `» scope_id` | string | false | | |
| `» source_scheme` | [database.ParameterSourceScheme](schemas.md#databaseparametersourcescheme) | false | | |
| `» source_value` | string | false | | |
| `» updated_at` | string | false | | |
#### Enumerated Values
| Property | Value |
| -------------------- | ---------------------- |
| `destination_scheme` | `none` |
| `destination_scheme` | `environment_variable` |
| `destination_scheme` | `provisioner_variable` |
| `scope` | `template` |
| `scope` | `import_job` |
| `scope` | `workspace` |
| `source_scheme` | `none` |
| `source_scheme` | `data` |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get schema by template version ## Get schema by template version
### Code samples ### Code samples

18
go.mod
View File

@ -167,7 +167,23 @@ require (
tailscale.com v1.32.2 tailscale.com v1.32.2
) )
require cloud.google.com/go/longrunning v0.1.1 // indirect require (
cloud.google.com/go/longrunning v0.1.1 // indirect
github.com/coder/terraform-provider-coder v0.6.6 // indirect
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-hclog v1.2.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
)
require ( require (
cloud.google.com/go/compute v1.12.1 // indirect cloud.google.com/go/compute v1.12.1 // indirect

25
go.sum
View File

@ -204,6 +204,7 @@ github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2q
github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
@ -361,6 +362,8 @@ github.com/coder/ssh v0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHui
github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3 h1:lq8GmpE5bn8A36uxq1h+TWnaQKPugtRkxKrYZA78O9c= github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3 h1:lq8GmpE5bn8A36uxq1h+TWnaQKPugtRkxKrYZA78O9c=
github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3/go.mod h1:lkCb74eSJwxeNq8YwyILoHD5vtHktiZnTOxBxo3tbNc= github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3/go.mod h1:lkCb74eSJwxeNq8YwyILoHD5vtHktiZnTOxBxo3tbNc=
github.com/coder/terraform-provider-coder v0.6.6 h1:ZAYvERlgjQPHyDdemXEuVcwdCFGfk9v5zQARegWL6nQ=
github.com/coder/terraform-provider-coder v0.6.6/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
@ -984,7 +987,11 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw=
github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
@ -1000,6 +1007,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
@ -1016,6 +1025,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc= github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc=
github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
@ -1025,6 +1035,12 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM=
github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw=
github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs=
github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 h1:+KxZULPsbjpAVoP0WNj/8aVW6EqpcX5JcUcQ5wl7Da4=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0/go.mod h1:DwGJG3KNxIPluVk6hexvDfYR/MS/eKGpiztJoT3Bbbw=
github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce h1:7FO+LmZwiG/eDsBWo50ZeqV5PoH0gwiM1mxFajXAkas= github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce h1:7FO+LmZwiG/eDsBWo50ZeqV5PoH0gwiM1mxFajXAkas=
github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU=
@ -1342,12 +1358,15 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
@ -1364,6 +1383,7 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby v20.10.21+incompatible h1:LfdCNzNpDYtOTtlO5wxLcUEk0nyM3KqPyeIyXVdvl/U= github.com/moby/moby v20.10.21+incompatible h1:LfdCNzNpDYtOTtlO5wxLcUEk0nyM3KqPyeIyXVdvl/U=
@ -1723,6 +1743,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
@ -1817,7 +1838,11 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=

View File

@ -223,7 +223,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
if err != nil { if err != nil {
return nil, xerrors.Errorf("terraform plan: %w", err) return nil, xerrors.Errorf("terraform plan: %w", err)
} }
resources, err := e.planResources(ctx, killCtx, planfilePath) resources, parameters, err := e.planResources(ctx, killCtx, planfilePath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -234,25 +234,31 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
return &proto.Provision_Response{ return &proto.Provision_Response{
Type: &proto.Provision_Response_Complete{ Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{ Complete: &proto.Provision_Complete{
Resources: resources, Parameters: parameters,
Plan: planFileByt, Resources: resources,
Plan: planFileByt,
}, },
}, },
}, nil }, nil
} }
// planResources must only be called while the lock is held. // planResources must only be called while the lock is held.
func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) ([]*proto.Resource, error) { func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) ([]*proto.Resource, []*proto.RichParameter, error) {
plan, err := e.showPlan(ctx, killCtx, planfilePath) plan, err := e.showPlan(ctx, killCtx, planfilePath)
if err != nil { if err != nil {
return nil, xerrors.Errorf("show terraform plan file: %w", err) return nil, nil, xerrors.Errorf("show terraform plan file: %w", err)
} }
rawGraph, err := e.graph(ctx, killCtx) rawGraph, err := e.graph(ctx, killCtx)
if err != nil { if err != nil {
return nil, xerrors.Errorf("graph: %w", err) return nil, nil, xerrors.Errorf("graph: %w", err)
} }
return ConvertResources(plan.PlannedValues.RootModule, rawGraph) modules := []*tfjson.StateModule{}
if plan.PriorState != nil {
modules = append(modules, plan.PriorState.Values.RootModule)
}
modules = append(modules, plan.PlannedValues.RootModule)
return ConvertResourcesAndParameters(modules, rawGraph)
} }
// showPlan must only be called while the lock is held. // showPlan must only be called while the lock is held.
@ -326,7 +332,7 @@ func (e *executor) apply(
if err != nil { if err != nil {
return nil, xerrors.Errorf("terraform apply: %w", err) return nil, xerrors.Errorf("terraform apply: %w", err)
} }
resources, err := e.stateResources(ctx, killCtx) resources, parameters, err := e.stateResources(ctx, killCtx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -338,31 +344,35 @@ func (e *executor) apply(
return &proto.Provision_Response{ return &proto.Provision_Response{
Type: &proto.Provision_Response_Complete{ Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{ Complete: &proto.Provision_Complete{
Resources: resources, Parameters: parameters,
State: stateContent, Resources: resources,
State: stateContent,
}, },
}, },
}, nil }, nil
} }
// stateResources must only be called while the lock is held. // stateResources must only be called while the lock is held.
func (e *executor) stateResources(ctx, killCtx context.Context) ([]*proto.Resource, error) { func (e *executor) stateResources(ctx, killCtx context.Context) ([]*proto.Resource, []*proto.RichParameter, error) {
state, err := e.state(ctx, killCtx) state, err := e.state(ctx, killCtx)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
rawGraph, err := e.graph(ctx, killCtx) rawGraph, err := e.graph(ctx, killCtx)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get terraform graph: %w", err) return nil, nil, xerrors.Errorf("get terraform graph: %w", err)
} }
var resources []*proto.Resource var resources []*proto.Resource
var parameters []*proto.RichParameter
if state.Values != nil { if state.Values != nil {
resources, err = ConvertResources(state.Values.RootModule, rawGraph) resources, parameters, err = ConvertResourcesAndParameters([]*tfjson.StateModule{
state.Values.RootModule,
}, rawGraph)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
} }
return resources, nil return resources, parameters, nil
} }
// state must only be called while the lock is held. // state must only be called while the lock is held.

View File

@ -8,6 +8,8 @@ import (
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/coder/terraform-provider-coder/provider"
"github.com/coder/coder/provisioner" "github.com/coder/coder/provisioner"
"github.com/coder/coder/provisionersdk/proto" "github.com/coder/coder/provisionersdk/proto"
) )
@ -68,17 +70,17 @@ type metadataItem struct {
IsNull bool `mapstructure:"is_null"` IsNull bool `mapstructure:"is_null"`
} }
// ConvertResources consumes Terraform state and a GraphViz representation // ConvertResourcesAndParameters consumes Terraform state and a GraphViz representation
// produced by `terraform graph` to produce resources consumable by Coder. // produced by `terraform graph` to produce resources consumable by Coder.
// nolint:gocyclo // nolint:gocyclo
func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) { func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph string) ([]*proto.Resource, []*proto.RichParameter, error) {
parsedGraph, err := gographviz.ParseString(rawGraph) parsedGraph, err := gographviz.ParseString(rawGraph)
if err != nil { if err != nil {
return nil, xerrors.Errorf("parse graph: %w", err) return nil, nil, xerrors.Errorf("parse graph: %w", err)
} }
graph, err := gographviz.NewAnalysedGraph(parsedGraph) graph, err := gographviz.NewAnalysedGraph(parsedGraph)
if err != nil { if err != nil {
return nil, xerrors.Errorf("analyze graph: %w", err) return nil, nil, xerrors.Errorf("analyze graph: %w", err)
} }
resources := make([]*proto.Resource, 0) resources := make([]*proto.Resource, 0)
@ -98,7 +100,9 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
tfResourceByLabel[label] = resource tfResourceByLabel[label] = resource
} }
} }
findTerraformResources(module) for _, module := range modules {
findTerraformResources(module)
}
// Find all agents! // Find all agents!
agentNames := map[string]struct{}{} agentNames := map[string]struct{}{}
@ -109,11 +113,11 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
var attrs agentAttributes var attrs agentAttributes
err = mapstructure.Decode(tfResource.AttributeValues, &attrs) err = mapstructure.Decode(tfResource.AttributeValues, &attrs)
if err != nil { if err != nil {
return nil, xerrors.Errorf("decode agent attributes: %w", err) return nil, nil, xerrors.Errorf("decode agent attributes: %w", err)
} }
if _, ok := agentNames[tfResource.Name]; ok { if _, ok := agentNames[tfResource.Name]; ok {
return nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name) return nil, nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name)
} }
agentNames[tfResource.Name] = struct{}{} agentNames[tfResource.Name] = struct{}{}
@ -154,7 +158,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
break break
} }
if agentNode == nil { if agentNode == nil {
return nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel) return nil, nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel)
} }
var agentResource *graphResource var agentResource *graphResource
@ -239,7 +243,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
var attrs agentAppAttributes var attrs agentAppAttributes
err = mapstructure.Decode(resource.AttributeValues, &attrs) err = mapstructure.Decode(resource.AttributeValues, &attrs)
if err != nil { if err != nil {
return nil, xerrors.Errorf("decode app attributes: %w", err) return nil, nil, xerrors.Errorf("decode app attributes: %w", err)
} }
// Default to the resource name if none is set! // Default to the resource name if none is set!
@ -256,11 +260,11 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
} }
if !provisioner.AppSlugRegex.MatchString(attrs.Slug) { if !provisioner.AppSlugRegex.MatchString(attrs.Slug) {
return nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug) return nil, nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
} }
if _, exists := appSlugs[attrs.Slug]; exists { if _, exists := appSlugs[attrs.Slug]; exists {
return nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug) return nil, nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
} }
appSlugs[attrs.Slug] = struct{}{} appSlugs[attrs.Slug] = struct{}{}
@ -318,7 +322,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
var attrs metadataAttributes var attrs metadataAttributes
err = mapstructure.Decode(resource.AttributeValues, &attrs) err = mapstructure.Decode(resource.AttributeValues, &attrs)
if err != nil { if err != nil {
return nil, xerrors.Errorf("decode metadata attributes: %w", err) return nil, nil, xerrors.Errorf("decode metadata attributes: %w", err)
} }
resourceLabel := convertAddressToLabel(resource.Address) resourceLabel := convertAddressToLabel(resource.Address)
@ -397,7 +401,44 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
}) })
} }
return resources, nil parameters := make([]*proto.RichParameter, 0)
for _, resource := range tfResourceByLabel {
if resource.Type != "coder_parameter" {
continue
}
var param provider.Parameter
err = mapstructure.Decode(resource.AttributeValues, &param)
if err != nil {
return nil, nil, xerrors.Errorf("decode map values for coder_parameter.%s: %w", resource.Name, err)
}
protoParam := &proto.RichParameter{
Name: param.Name,
Description: param.Description,
Type: param.Type,
Mutable: param.Mutable,
DefaultValue: param.Default,
Icon: param.Icon,
}
if len(param.Validation) == 1 {
protoParam.ValidationRegex = param.Validation[0].Regex
protoParam.ValidationMax = int32(param.Validation[0].Max)
protoParam.ValidationMin = int32(param.Validation[0].Min)
}
if len(param.Option) > 0 {
protoParam.Options = make([]*proto.RichParameterOption, 0, len(param.Option))
for _, option := range param.Option {
protoParam.Options = append(protoParam.Options, &proto.RichParameterOption{
Name: option.Name,
Description: option.Description,
Value: option.Value,
Icon: option.Icon,
})
}
}
parameters = append(parameters, protoParam)
}
return resources, parameters, nil
} }
// convertAddressToLabel returns the Terraform address without the count // convertAddressToLabel returns the Terraform address without the count

View File

@ -11,7 +11,6 @@ import (
protobuf "github.com/golang/protobuf/proto" protobuf "github.com/golang/protobuf/proto"
tfjson "github.com/hashicorp/terraform-json" tfjson "github.com/hashicorp/terraform-json"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/exp/slices"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
"github.com/coder/coder/provisioner/terraform" "github.com/coder/coder/provisioner/terraform"
@ -22,196 +21,241 @@ func TestConvertResources(t *testing.T) {
t.Parallel() t.Parallel()
// nolint:dogsled // nolint:dogsled
_, filename, _, _ := runtime.Caller(0) _, filename, _, _ := runtime.Caller(0)
type testCase struct {
resources []*proto.Resource
parameters []*proto.RichParameter
}
// nolint:paralleltest // nolint:paralleltest
for folderName, expected := range map[string][]*proto.Resource{ for folderName, expected := range map[string]testCase{
// When a resource depends on another, the shortest route // When a resource depends on another, the shortest route
// to a resource should always be chosen for the agent. // to a resource should always be chosen for the agent.
"chaining-resources": {{ "chaining-resources": {
Name: "a", resources: []*proto.Resource{{
Type: "null_resource", Name: "a",
}, { Type: "null_resource",
Name: "b", }, {
Type: "null_resource", Name: "b",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "main", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "main",
Architecture: "amd64", OperatingSystem: "linux",
Auth: &proto.Agent_Token{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}},
}}, }},
}}, },
// This can happen when resources hierarchically conflict. // This can happen when resources hierarchically conflict.
// When multiple resources exist at the same level, the first // When multiple resources exist at the same level, the first
// listed in state will be chosen. // listed in state will be chosen.
"conflicting-resources": {{ "conflicting-resources": {
Name: "first", resources: []*proto.Resource{{
Type: "null_resource", Name: "first",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "main", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "main",
Architecture: "amd64", OperatingSystem: "linux",
Auth: &proto.Agent_Token{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}},
}, {
Name: "second",
Type: "null_resource",
}}, }},
}, { },
Name: "second",
Type: "null_resource",
}},
// Ensures the instance ID authentication type surfaces. // Ensures the instance ID authentication type surfaces.
"instance-id": {{ "instance-id": {
Name: "main", resources: []*proto.Resource{{
Type: "null_resource", Name: "main",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "main", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "main",
Architecture: "amd64", OperatingSystem: "linux",
Auth: &proto.Agent_InstanceId{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_InstanceId{},
ConnectionTimeoutSeconds: 120,
}},
}}, }},
}}, },
// Ensures that calls to resources through modules work // Ensures that calls to resources through modules work
// as expected. // as expected.
"calling-module": {{ "calling-module": {
Name: "example", resources: []*proto.Resource{{
Type: "null_resource", Name: "example",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "main", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "main",
Architecture: "amd64", OperatingSystem: "linux",
Auth: &proto.Agent_Token{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}},
}}, }},
}}, },
// Ensures the attachment of multiple agents to a single // Ensures the attachment of multiple agents to a single
// resource is successful. // resource is successful.
"multiple-agents": {{ "multiple-agents": {
Name: "dev", resources: []*proto.Resource{{
Type: "null_resource", Name: "dev",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "dev1", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "dev1",
Architecture: "amd64", OperatingSystem: "linux",
Auth: &proto.Agent_Token{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_Token{},
}, { ConnectionTimeoutSeconds: 120,
Name: "dev2", }, {
OperatingSystem: "darwin", Name: "dev2",
Architecture: "amd64", OperatingSystem: "darwin",
Auth: &proto.Agent_Token{}, Architecture: "amd64",
ConnectionTimeoutSeconds: 1, Auth: &proto.Agent_Token{},
MotdFile: "/etc/motd", ConnectionTimeoutSeconds: 1,
}, { MotdFile: "/etc/motd",
Name: "dev3", }, {
OperatingSystem: "windows", Name: "dev3",
Architecture: "arm64", OperatingSystem: "windows",
Auth: &proto.Agent_Token{}, Architecture: "arm64",
ConnectionTimeoutSeconds: 120, Auth: &proto.Agent_Token{},
TroubleshootingUrl: "https://coder.com/troubleshoot", ConnectionTimeoutSeconds: 120,
TroubleshootingUrl: "https://coder.com/troubleshoot",
}},
}}, }},
}}, },
// Ensures multiple applications can be set for a single agent. // Ensures multiple applications can be set for a single agent.
"multiple-apps": {{ "multiple-apps": {
Name: "dev", resources: []*proto.Resource{{
Type: "null_resource", Name: "dev",
Agents: []*proto.Agent{{ Type: "null_resource",
Name: "dev1", Agents: []*proto.Agent{{
OperatingSystem: "linux", Name: "dev1",
Architecture: "amd64", OperatingSystem: "linux",
Apps: []*proto.App{ Architecture: "amd64",
{ Apps: []*proto.App{
Slug: "app1", {
DisplayName: "app1", Slug: "app1",
// Subdomain defaults to false if unspecified. DisplayName: "app1",
Subdomain: false, // Subdomain defaults to false if unspecified.
}, Subdomain: false,
{ },
Slug: "app2", {
DisplayName: "app2", Slug: "app2",
Subdomain: true, DisplayName: "app2",
Healthcheck: &proto.Healthcheck{ Subdomain: true,
Url: "http://localhost:13337/healthz", Healthcheck: &proto.Healthcheck{
Interval: 5, Url: "http://localhost:13337/healthz",
Threshold: 6, Interval: 5,
Threshold: 6,
},
},
{
Slug: "app3",
DisplayName: "app3",
Subdomain: false,
}, },
}, },
{ Auth: &proto.Agent_Token{},
Slug: "app3", ConnectionTimeoutSeconds: 120,
DisplayName: "app3", }},
Subdomain: false,
},
},
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}}, }},
}}, },
// Tests fetching metadata about workspace resources. // Tests fetching metadata about workspace resources.
"resource-metadata": {{ "resource-metadata": {
Name: "about", resources: []*proto.Resource{{
Type: "null_resource", Name: "about",
Hide: true, Type: "null_resource",
Icon: "/icon/server.svg", Hide: true,
DailyCost: 29, Icon: "/icon/server.svg",
Metadata: []*proto.Resource_Metadata{{ DailyCost: 29,
Key: "hello", Metadata: []*proto.Resource_Metadata{{
Value: "world", Key: "hello",
}, { Value: "world",
Key: "null", }, {
IsNull: true, Key: "null",
}, { IsNull: true,
Key: "empty", }, {
}, { Key: "empty",
Key: "secret", }, {
Value: "squirrel", Key: "secret",
Sensitive: true, Value: "squirrel",
Sensitive: true,
}},
}}, }},
}}, },
// Tests that resources with the same id correctly get metadata applied // Tests that resources with the same id correctly get metadata applied
// to them. // to them.
"kubernetes-metadata": {{ "kubernetes-metadata": {
Name: "coder_workspace", resources: []*proto.Resource{
Type: "kubernetes_service_account", {
}, { Name: "coder_workspace",
Name: "coder_workspace", Type: "kubernetes_config_map",
Type: "kubernetes_config_map", }, {
}, { Name: "coder_workspace",
Name: "coder_workspace", Type: "kubernetes_role",
Type: "kubernetes_role", }, {
}, { Name: "coder_workspace",
Name: "coder_workspace", Type: "kubernetes_role_binding",
Type: "kubernetes_role_binding", }, {
}, { Name: "coder_workspace",
Name: "coder_workspace", Type: "kubernetes_secret",
Type: "kubernetes_secret", }, {
}, { Name: "coder_workspace",
Name: "main", Type: "kubernetes_service_account",
Type: "kubernetes_pod", }, {
Metadata: []*proto.Resource_Metadata{{ Name: "main",
Key: "cpu", Type: "kubernetes_pod",
Value: "1", Metadata: []*proto.Resource_Metadata{{
}, { Key: "cpu",
Key: "memory", Value: "1",
Value: "1Gi", }, {
}, { Key: "memory",
Key: "gpu", Value: "1Gi",
Value: "1", }, {
}}, Key: "gpu",
Agents: []*proto.Agent{{ Value: "1",
Name: "main", }},
OperatingSystem: "linux", Agents: []*proto.Agent{{
Architecture: "amd64", Name: "main",
StartupScript: " #!/bin/bash\n # home folder can be empty, so copying default bash settings\n if [ ! -f ~/.profile ]; then\n cp /etc/skel/.profile $HOME\n fi\n if [ ! -f ~/.bashrc ]; then\n cp /etc/skel/.bashrc $HOME\n fi\n # install and start code-server\n curl -fsSL https://code-server.dev/install.sh | sh | tee code-server-install.log\n code-server --auth none --port 13337 | tee code-server-install.log &\n", OperatingSystem: "linux",
Apps: []*proto.App{ Architecture: "amd64",
{ StartupScript: " #!/bin/bash\n # home folder can be empty, so copying default bash settings\n if [ ! -f ~/.profile ]; then\n cp /etc/skel/.profile $HOME\n fi\n if [ ! -f ~/.bashrc ]; then\n cp /etc/skel/.bashrc $HOME\n fi\n # install and start code-server\n curl -fsSL https://code-server.dev/install.sh | sh | tee code-server-install.log\n code-server --auth none --port 13337 | tee code-server-install.log &\n",
Icon: "/icon/code.svg", Apps: []*proto.App{
Slug: "code-server", {
DisplayName: "code-server", Icon: "/icon/code.svg",
Url: "http://localhost:13337?folder=/home/coder", Slug: "code-server",
}, DisplayName: "code-server",
Url: "http://localhost:13337?folder=/home/coder",
},
},
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}},
}, },
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}}, }},
}}, "rich-parameters": {
resources: []*proto.Resource{{
Name: "dev",
Type: "null_resource",
Agents: []*proto.Agent{{
Name: "dev",
OperatingSystem: "windows",
Architecture: "arm64",
Auth: &proto.Agent_Token{},
ConnectionTimeoutSeconds: 120,
}},
}},
parameters: []*proto.RichParameter{{
Name: "Example",
Type: "string",
Options: []*proto.RichParameterOption{{
Name: "First Option",
Value: "first",
}, {
Name: "Second Option",
Value: "second",
}},
}},
},
} { } {
folderName := folderName folderName := folderName
expected := expected expected := expected
@ -229,12 +273,18 @@ func TestConvertResources(t *testing.T) {
tfPlanGraph, err := os.ReadFile(filepath.Join(dir, folderName+".tfplan.dot")) tfPlanGraph, err := os.ReadFile(filepath.Join(dir, folderName+".tfplan.dot"))
require.NoError(t, err) require.NoError(t, err)
resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph)) modules := []*tfjson.StateModule{}
if tfPlan.PriorState != nil {
modules = append(modules, tfPlan.PriorState.Values.RootModule)
}
modules = append(modules, tfPlan.PlannedValues.RootModule)
resources, parameters, err := terraform.ConvertResourcesAndParameters(modules, string(tfPlanGraph))
require.NoError(t, err) require.NoError(t, err)
sortResources(resources) sortResources(resources)
sortParameters(parameters)
var expectedNoMetadata []*proto.Resource expectedNoMetadata := make([]*proto.Resource, 0)
for _, resource := range expected { for _, resource := range expected.resources {
resourceCopy, _ := protobuf.Clone(resource).(*proto.Resource) resourceCopy, _ := protobuf.Clone(resource).(*proto.Resource)
// plan cannot know whether values are null or not // plan cannot know whether values are null or not
for _, metadata := range resourceCopy.Metadata { for _, metadata := range resourceCopy.Metadata {
@ -256,18 +306,16 @@ func TestConvertResources(t *testing.T) {
var resourcesMap []map[string]interface{} var resourcesMap []map[string]interface{}
err = json.Unmarshal(data, &resourcesMap) err = json.Unmarshal(data, &resourcesMap)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expectedNoMetadataMap, resourcesMap)
slices.SortFunc(expectedNoMetadataMap, func(a, b map[string]interface{}) bool { if expected.parameters == nil {
//nolint:forcetypeassert expected.parameters = []*proto.RichParameter{}
return a["name"].(string)+a["type"].(string) < }
b["name"].(string)+b["type"].(string) parametersWant, err := json.Marshal(expected.parameters)
}) require.NoError(t, err)
slices.SortFunc(resourcesMap, func(a, b map[string]interface{}) bool { parametersGot, err := json.Marshal(parameters)
//nolint:forcetypeassert require.NoError(t, err)
return a["name"].(string)+a["type"].(string) < require.Equal(t, string(parametersWant), string(parametersGot))
b["name"].(string)+b["type"].(string)
})
require.Equal(t, expectedNoMetadataMap, resourcesMap) require.Equal(t, expectedNoMetadataMap, resourcesMap)
}) })
@ -281,9 +329,10 @@ func TestConvertResources(t *testing.T) {
tfStateGraph, err := os.ReadFile(filepath.Join(dir, folderName+".tfstate.dot")) tfStateGraph, err := os.ReadFile(filepath.Join(dir, folderName+".tfstate.dot"))
require.NoError(t, err) require.NoError(t, err)
resources, err := terraform.ConvertResources(tfState.Values.RootModule, string(tfStateGraph)) resources, parameters, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph))
require.NoError(t, err) require.NoError(t, err)
sortResources(resources) sortResources(resources)
sortParameters(parameters)
for _, resource := range resources { for _, resource := range resources {
for _, agent := range resource.Agents { for _, agent := range resource.Agents {
agent.Id = "" agent.Id = ""
@ -297,7 +346,7 @@ func TestConvertResources(t *testing.T) {
} }
// Convert expectedNoMetadata and resources into a // Convert expectedNoMetadata and resources into a
// []map[string]interface{} so they can be compared easily. // []map[string]interface{} so they can be compared easily.
data, err := json.Marshal(expected) data, err := json.Marshal(expected.resources)
require.NoError(t, err) require.NoError(t, err)
var expectedMap []map[string]interface{} var expectedMap []map[string]interface{}
err = json.Unmarshal(data, &expectedMap) err = json.Unmarshal(data, &expectedMap)
@ -309,17 +358,6 @@ func TestConvertResources(t *testing.T) {
err = json.Unmarshal(data, &resourcesMap) err = json.Unmarshal(data, &resourcesMap)
require.NoError(t, err) require.NoError(t, err)
slices.SortFunc(expectedMap, func(a, b map[string]interface{}) bool {
//nolint:forcetypeassert
return a["name"].(string)+a["type"].(string) <
b["name"].(string)+b["type"].(string)
})
slices.SortFunc(resourcesMap, func(a, b map[string]interface{}) bool {
//nolint:forcetypeassert
return a["name"].(string)+a["type"].(string) <
b["name"].(string)+b["type"].(string)
})
require.Equal(t, expectedMap, resourcesMap) require.Equal(t, expectedMap, resourcesMap)
}) })
}) })
@ -349,7 +387,7 @@ func TestAppSlugValidation(t *testing.T) {
} }
} }
resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph)) resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
require.Nil(t, resources) require.Nil(t, resources)
require.Error(t, err) require.Error(t, err)
require.ErrorContains(t, err, "invalid app slug") require.ErrorContains(t, err, "invalid app slug")
@ -361,7 +399,7 @@ func TestAppSlugValidation(t *testing.T) {
} }
} }
resources, err = terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph)) resources, _, err = terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{tfPlan.PlannedValues.RootModule}, string(tfPlanGraph))
require.Nil(t, resources) require.Nil(t, resources)
require.Error(t, err) require.Error(t, err)
require.ErrorContains(t, err, "duplicate app slug") require.ErrorContains(t, err, "duplicate app slug")
@ -394,7 +432,7 @@ func TestInstanceTypeAssociation(t *testing.T) {
t.Parallel() t.Parallel()
instanceType, err := cryptorand.String(12) instanceType, err := cryptorand.String(12)
require.NoError(t, err) require.NoError(t, err)
resources, err := terraform.ConvertResources(&tfjson.StateModule{ resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{{
Resources: []*tfjson.StateResource{{ Resources: []*tfjson.StateResource{{
Address: tc.ResourceType + ".dev", Address: tc.ResourceType + ".dev",
Type: tc.ResourceType, Type: tc.ResourceType,
@ -405,7 +443,7 @@ func TestInstanceTypeAssociation(t *testing.T) {
}, },
}}, }},
// This is manually created to join the edges. // This is manually created to join the edges.
}, `digraph { }}, `digraph {
compound = "true" compound = "true"
newrank = "true" newrank = "true"
subgraph "root" { subgraph "root" {
@ -452,7 +490,7 @@ func TestInstanceIDAssociation(t *testing.T) {
t.Parallel() t.Parallel()
instanceID, err := cryptorand.String(12) instanceID, err := cryptorand.String(12)
require.NoError(t, err) require.NoError(t, err)
resources, err := terraform.ConvertResources(&tfjson.StateModule{ resources, _, err := terraform.ConvertResourcesAndParameters([]*tfjson.StateModule{{
Resources: []*tfjson.StateResource{{ Resources: []*tfjson.StateResource{{
Address: "coder_agent.dev", Address: "coder_agent.dev",
Type: "coder_agent", Type: "coder_agent",
@ -473,7 +511,7 @@ func TestInstanceIDAssociation(t *testing.T) {
}, },
}}, }},
// This is manually created to join the edges. // This is manually created to join the edges.
}, `digraph { }}, `digraph {
compound = "true" compound = "true"
newrank = "true" newrank = "true"
subgraph "root" { subgraph "root" {
@ -495,7 +533,10 @@ func TestInstanceIDAssociation(t *testing.T) {
// to prevent tests from flaking. // to prevent tests from flaking.
func sortResources(resources []*proto.Resource) { func sortResources(resources []*proto.Resource) {
sort.Slice(resources, func(i, j int) bool { sort.Slice(resources, func(i, j int) bool {
return resources[i].Name < resources[j].Name if resources[i].Name != resources[j].Name {
return resources[i].Name < resources[j].Name
}
return resources[i].Type < resources[j].Type
}) })
for _, resource := range resources { for _, resource := range resources {
for _, agent := range resource.Agents { for _, agent := range resource.Agents {
@ -508,3 +549,14 @@ func sortResources(resources []*proto.Resource) {
}) })
} }
} }
func sortParameters(parameters []*proto.RichParameter) {
sort.Slice(parameters, func(i, j int) bool {
return parameters[i].Name < parameters[j].Name
})
for _, parameter := range parameters {
sort.Slice(parameter.Options, func(i, j int) bool {
return parameter.Options[i].Name < parameter.Options[j].Name
})
}
}

View File

@ -0,0 +1,30 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = "0.6.6"
}
}
}
data "coder_parameter" "example" {
name = "Example"
type = "string"
option {
name = "First Option"
value = "first"
}
option {
name = "Second Option"
value = "second"
}
}
resource "coder_agent" "dev" {
os = "windows"
arch = "arm64"
}
resource "null_resource" "dev" {
depends_on = [coder_agent.dev]
}

View File

@ -0,0 +1,21 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"]
"[root] data.coder_parameter.example (expand)" [label = "data.coder_parameter.example", shape = "box"]
"[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_parameter.example (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.dev (expand)" -> "[root] coder_agent.dev (expand)"
"[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_parameter.example (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}

View File

@ -0,0 +1,227 @@
{
"format_version": "1.1",
"terraform_version": "1.2.6",
"planned_values": {
"root_module": {
"resources": [
{
"address": "coder_agent.dev",
"mode": "managed",
"type": "coder_agent",
"name": "dev",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "arm64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"motd_file": null,
"os": "windows",
"shutdown_script": null,
"startup_script": null,
"troubleshooting_url": null
},
"sensitive_values": {}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"triggers": null
},
"sensitive_values": {}
}
]
}
},
"resource_changes": [
{
"address": "coder_agent.dev",
"mode": "managed",
"type": "coder_agent",
"name": "dev",
"provider_name": "registry.terraform.io/coder/coder",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"arch": "arm64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"motd_file": null,
"os": "windows",
"shutdown_script": null,
"startup_script": null,
"troubleshooting_url": null
},
"after_unknown": {
"id": true,
"init_script": true,
"token": true
},
"before_sensitive": false,
"after_sensitive": {
"token": true
}
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"triggers": null
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.2.6",
"values": {
"root_module": {
"resources": [
{
"address": "data.coder_parameter.example",
"mode": "data",
"type": "coder_parameter",
"name": "example",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"default": null,
"description": null,
"icon": null,
"id": "80782610-71f2-45a2-97ea-6029ddbf7ae8",
"mutable": false,
"name": "Example",
"option": [
{
"description": "",
"icon": "",
"name": "First Option",
"value": "first"
},
{
"description": "",
"icon": "",
"name": "Second Option",
"value": "second"
}
],
"type": "string",
"validation": null,
"value": ""
},
"sensitive_values": {
"option": [
{},
{}
]
}
}
]
}
}
},
"configuration": {
"provider_config": {
"coder": {
"name": "coder",
"full_name": "registry.terraform.io/coder/coder",
"version_constraint": "0.6.6"
},
"null": {
"name": "null",
"full_name": "registry.terraform.io/hashicorp/null"
}
},
"root_module": {
"resources": [
{
"address": "coder_agent.dev",
"mode": "managed",
"type": "coder_agent",
"name": "dev",
"provider_config_key": "coder",
"expressions": {
"arch": {
"constant_value": "arm64"
},
"os": {
"constant_value": "windows"
}
},
"schema_version": 0
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_config_key": "null",
"schema_version": 0,
"depends_on": [
"coder_agent.dev"
]
},
{
"address": "data.coder_parameter.example",
"mode": "data",
"type": "coder_parameter",
"name": "example",
"provider_config_key": "coder",
"expressions": {
"name": {
"constant_value": "Example"
},
"option": [
{
"name": {
"constant_value": "First Option"
},
"value": {
"constant_value": "first"
}
},
{
"name": {
"constant_value": "Second Option"
},
"value": {
"constant_value": "second"
}
}
],
"type": {
"constant_value": "string"
}
},
"schema_version": 0
}
]
}
}
}

View File

@ -0,0 +1,21 @@
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"]
"[root] data.coder_parameter.example (expand)" [label = "data.coder_parameter.example", shape = "box"]
"[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"]
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
"[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"]
"[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] data.coder_parameter.example (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
"[root] null_resource.dev (expand)" -> "[root] coder_agent.dev (expand)"
"[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)"
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] data.coder_parameter.example (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)"
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)"
}
}

View File

@ -0,0 +1,89 @@
{
"format_version": "1.0",
"terraform_version": "1.2.6",
"values": {
"root_module": {
"resources": [
{
"address": "coder_agent.dev",
"mode": "managed",
"type": "coder_agent",
"name": "dev",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"arch": "arm64",
"auth": "token",
"connection_timeout": 120,
"dir": null,
"env": null,
"id": "c816f258-9140-44e9-8f9c-c67b6561106c",
"init_script": "",
"motd_file": null,
"os": "windows",
"shutdown_script": null,
"startup_script": null,
"token": "d8353b78-99d1-4ae0-b895-3dbf08df2a9a",
"troubleshooting_url": null
},
"sensitive_values": {}
},
{
"address": "data.coder_parameter.example",
"mode": "data",
"type": "coder_parameter",
"name": "example",
"provider_name": "registry.terraform.io/coder/coder",
"schema_version": 0,
"values": {
"default": null,
"description": null,
"icon": null,
"id": "7f0e325e-0016-4213-8239-c52c678a6a3c",
"mutable": false,
"name": "Example",
"option": [
{
"description": "",
"icon": "",
"name": "First Option",
"value": "first"
},
{
"description": "",
"icon": "",
"name": "Second Option",
"value": "second"
}
],
"type": "string",
"validation": null,
"value": ""
},
"sensitive_values": {
"option": [
{},
{}
]
}
},
{
"address": "null_resource.dev",
"mode": "managed",
"type": "null_resource",
"name": "dev",
"provider_name": "registry.terraform.io/hashicorp/null",
"schema_version": 0,
"values": {
"id": "8669777619875370025",
"triggers": null
},
"sensitive_values": {},
"depends_on": [
"coder_agent.dev"
]
}
]
}
}
}

View File

@ -790,11 +790,12 @@ type AcquiredJob_WorkspaceBuild struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
WorkspaceBuildId string `protobuf:"bytes,1,opt,name=workspace_build_id,json=workspaceBuildId,proto3" json:"workspace_build_id,omitempty"` WorkspaceBuildId string `protobuf:"bytes,1,opt,name=workspace_build_id,json=workspaceBuildId,proto3" json:"workspace_build_id,omitempty"`
WorkspaceName string `protobuf:"bytes,2,opt,name=workspace_name,json=workspaceName,proto3" json:"workspace_name,omitempty"` WorkspaceName string `protobuf:"bytes,2,opt,name=workspace_name,json=workspaceName,proto3" json:"workspace_name,omitempty"`
ParameterValues []*proto.ParameterValue `protobuf:"bytes,3,rep,name=parameter_values,json=parameterValues,proto3" json:"parameter_values,omitempty"` ParameterValues []*proto.ParameterValue `protobuf:"bytes,3,rep,name=parameter_values,json=parameterValues,proto3" json:"parameter_values,omitempty"`
Metadata *proto.Provision_Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` RichParameterValues []*proto.RichParameterValue `protobuf:"bytes,4,rep,name=rich_parameter_values,json=richParameterValues,proto3" json:"rich_parameter_values,omitempty"`
State []byte `protobuf:"bytes,5,opt,name=state,proto3" json:"state,omitempty"` Metadata *proto.Provision_Metadata `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata,omitempty"`
State []byte `protobuf:"bytes,6,opt,name=state,proto3" json:"state,omitempty"`
} }
func (x *AcquiredJob_WorkspaceBuild) Reset() { func (x *AcquiredJob_WorkspaceBuild) Reset() {
@ -850,6 +851,13 @@ func (x *AcquiredJob_WorkspaceBuild) GetParameterValues() []*proto.ParameterValu
return nil return nil
} }
func (x *AcquiredJob_WorkspaceBuild) GetRichParameterValues() []*proto.RichParameterValue {
if x != nil {
return x.RichParameterValues
}
return nil
}
func (x *AcquiredJob_WorkspaceBuild) GetMetadata() *proto.Provision_Metadata { func (x *AcquiredJob_WorkspaceBuild) GetMetadata() *proto.Provision_Metadata {
if x != nil { if x != nil {
return x.Metadata return x.Metadata
@ -1149,8 +1157,9 @@ type CompletedJob_TemplateImport struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
StartResources []*proto.Resource `protobuf:"bytes,1,rep,name=start_resources,json=startResources,proto3" json:"start_resources,omitempty"` StartResources []*proto.Resource `protobuf:"bytes,1,rep,name=start_resources,json=startResources,proto3" json:"start_resources,omitempty"`
StopResources []*proto.Resource `protobuf:"bytes,2,rep,name=stop_resources,json=stopResources,proto3" json:"stop_resources,omitempty"` StopResources []*proto.Resource `protobuf:"bytes,2,rep,name=stop_resources,json=stopResources,proto3" json:"stop_resources,omitempty"`
RichParameters []*proto.RichParameter `protobuf:"bytes,3,rep,name=rich_parameters,json=richParameters,proto3" json:"rich_parameters,omitempty"`
} }
func (x *CompletedJob_TemplateImport) Reset() { func (x *CompletedJob_TemplateImport) Reset() {
@ -1199,6 +1208,13 @@ func (x *CompletedJob_TemplateImport) GetStopResources() []*proto.Resource {
return nil return nil
} }
func (x *CompletedJob_TemplateImport) GetRichParameters() []*proto.RichParameter {
if x != nil {
return x.RichParameters
}
return nil
}
type CompletedJob_TemplateDryRun struct { type CompletedJob_TemplateDryRun struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -1255,7 +1271,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x6f, 0x6e, 0x65, 0x72, 0x64, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x07, 0x0a, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x07, 0x0a,
0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xac, 0x07, 0x0a, 0x0b, 0x41, 0x63, 0x71, 0x75, 0x69, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x81, 0x08, 0x0a, 0x0b, 0x41, 0x63, 0x71, 0x75, 0x69,
0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a,
0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
@ -1283,7 +1299,7 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a,
0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75,
0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79,
0x52, 0x75, 0x6e, 0x1a, 0x80, 0x02, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x52, 0x75, 0x6e, 0x1a, 0xd5, 0x02, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69,
@ -1294,161 +1310,171 @@ var file_provisionerd_proto_provisionerd_proto_rawDesc = []byte{
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x75, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x4d, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61,
0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f,
0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74,
0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x95, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06,
0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x4d, 0x0a, 0x0e, 0x54,
0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3b, 0x0a,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72,
0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x95, 0x01, 0x0a, 0x0e, 0x54,
0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x46, 0x0a,
0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x86, 0x03, 0x0a, 0x09, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56,
0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56,
0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x12, 0x51, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x86, 0x03, 0x0a, 0x09, 0x46,
0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
0x69, 0x6c, 0x64, 0x12, 0x51, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x51, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61,
0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63,
0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70,
0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x51, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70,
0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x26, 0x0a, 0x0e, 0x57, 0x6f, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d,
0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x74,
0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18,
0x74, 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x70, 0x6f, 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54,
0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xe5, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52,
0x04, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a,
0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x26, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c,
0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x10, 0x0a, 0x0e, 0x54, 0x65, 0x6d,
0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74,
0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x79, 0x70, 0x65, 0x22, 0xaa, 0x05, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65,
0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x77,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x02,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62,
0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x48,
0x72, 0x74, 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x00, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c,
0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x64, 0x12, 0x54, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6d,
0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49,
0x6d, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x55, 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c,
0x61, 0x74, 0x65, 0x5f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65,
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e,
0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x5b,
0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0xd3, 0x01, 0x0a, 0x0e,
0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e,
0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0e,
0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c,
0x0a, 0x0e, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0d, 0x73,
0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f,
0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
0x72, 0x52, 0x0e, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
0x73, 0x1a, 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x72, 0x79,
0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76,
0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52,
0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f,
0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x22, 0xb3, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f,
0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67,
0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65,
0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52,
0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61,
0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x22, 0x77, 0x0a, 0x11, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a,
0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x10, 0x70, 0x61,
0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x73, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74,
0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x68,
0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73,
0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x2a, 0x34, 0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49,
0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a,
0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x32, 0xec,
0x02, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61,
0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4a,
0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4a,
0x6f, 0x62, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74,
0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12,
0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46,
0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a,
0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x2b, 0x5a,
0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x1a, 0x5b, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65,
0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x65, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x6f, 0x33,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x8e, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
0x61, 0x74, 0x65, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x74, 0x61,
0x72, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74,
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0e, 0x73, 0x74, 0x6f,
0x70, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x45, 0x0a, 0x0e, 0x54, 0x65, 0x6d, 0x70, 0x6c,
0x61, 0x74, 0x65, 0x44, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70,
0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x06,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f,
0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x4c, 0x6f,
0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
0x2b, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67,
0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73,
0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67,
0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0xb3, 0x01, 0x0a, 0x10, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15,
0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x11,
0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x53,
0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x65, 0x22,
0x77, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64,
0x12, 0x46, 0x0a, 0x10, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f,
0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15,
0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63,
0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79,
0x43, 0x6f, 0x73, 0x74, 0x22, 0x68, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75,
0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f,
0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x63,
0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x43, 0x6f,
0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x2a, 0x34,
0x0a, 0x09, 0x4c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50,
0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f,
0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x53, 0x49, 0x4f, 0x4e,
0x45, 0x52, 0x10, 0x01, 0x32, 0xec, 0x02, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69,
0x6f, 0x6e, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x41, 0x63,
0x71, 0x75, 0x69, 0x72, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x41, 0x63, 0x71,
0x75, 0x69, 0x72, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x52, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73,
0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51, 0x75, 0x6f,
0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x51,
0x75, 0x6f, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a,
0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a,
0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x46, 0x61,
0x69, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4a,
0x6f, 0x62, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4a, 0x6f, 0x62, 0x1a, 0x13,
0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72,
0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -1488,8 +1514,10 @@ var file_provisionerd_proto_provisionerd_proto_goTypes = []interface{}{
(proto.LogLevel)(0), // 19: provisioner.LogLevel (proto.LogLevel)(0), // 19: provisioner.LogLevel
(*proto.ParameterSchema)(nil), // 20: provisioner.ParameterSchema (*proto.ParameterSchema)(nil), // 20: provisioner.ParameterSchema
(*proto.ParameterValue)(nil), // 21: provisioner.ParameterValue (*proto.ParameterValue)(nil), // 21: provisioner.ParameterValue
(*proto.Provision_Metadata)(nil), // 22: provisioner.Provision.Metadata (*proto.RichParameterValue)(nil), // 22: provisioner.RichParameterValue
(*proto.Resource)(nil), // 23: provisioner.Resource (*proto.Provision_Metadata)(nil), // 23: provisioner.Provision.Metadata
(*proto.Resource)(nil), // 24: provisioner.Resource
(*proto.RichParameter)(nil), // 25: provisioner.RichParameter
} }
var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{
10, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild 10, // 0: provisionerd.AcquiredJob.workspace_build:type_name -> provisionerd.AcquiredJob.WorkspaceBuild
@ -1507,29 +1535,31 @@ var file_provisionerd_proto_provisionerd_proto_depIdxs = []int32{
20, // 12: provisionerd.UpdateJobRequest.parameter_schemas:type_name -> provisioner.ParameterSchema 20, // 12: provisionerd.UpdateJobRequest.parameter_schemas:type_name -> provisioner.ParameterSchema
21, // 13: provisionerd.UpdateJobResponse.parameter_values:type_name -> provisioner.ParameterValue 21, // 13: provisionerd.UpdateJobResponse.parameter_values:type_name -> provisioner.ParameterValue
21, // 14: provisionerd.AcquiredJob.WorkspaceBuild.parameter_values:type_name -> provisioner.ParameterValue 21, // 14: provisionerd.AcquiredJob.WorkspaceBuild.parameter_values:type_name -> provisioner.ParameterValue
22, // 15: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Provision.Metadata 22, // 15: provisionerd.AcquiredJob.WorkspaceBuild.rich_parameter_values:type_name -> provisioner.RichParameterValue
22, // 16: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Provision.Metadata 23, // 16: provisionerd.AcquiredJob.WorkspaceBuild.metadata:type_name -> provisioner.Provision.Metadata
21, // 17: provisionerd.AcquiredJob.TemplateDryRun.parameter_values:type_name -> provisioner.ParameterValue 23, // 17: provisionerd.AcquiredJob.TemplateImport.metadata:type_name -> provisioner.Provision.Metadata
22, // 18: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Provision.Metadata 21, // 18: provisionerd.AcquiredJob.TemplateDryRun.parameter_values:type_name -> provisioner.ParameterValue
23, // 19: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource 23, // 19: provisionerd.AcquiredJob.TemplateDryRun.metadata:type_name -> provisioner.Provision.Metadata
23, // 20: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource 24, // 20: provisionerd.CompletedJob.WorkspaceBuild.resources:type_name -> provisioner.Resource
23, // 21: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource 24, // 21: provisionerd.CompletedJob.TemplateImport.start_resources:type_name -> provisioner.Resource
23, // 22: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource 24, // 22: provisionerd.CompletedJob.TemplateImport.stop_resources:type_name -> provisioner.Resource
1, // 23: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty 25, // 23: provisionerd.CompletedJob.TemplateImport.rich_parameters:type_name -> provisioner.RichParameter
8, // 24: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest 24, // 24: provisionerd.CompletedJob.TemplateDryRun.resources:type_name -> provisioner.Resource
6, // 25: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest 1, // 25: provisionerd.ProvisionerDaemon.AcquireJob:input_type -> provisionerd.Empty
3, // 26: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob 8, // 26: provisionerd.ProvisionerDaemon.CommitQuota:input_type -> provisionerd.CommitQuotaRequest
4, // 27: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob 6, // 27: provisionerd.ProvisionerDaemon.UpdateJob:input_type -> provisionerd.UpdateJobRequest
2, // 28: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob 3, // 28: provisionerd.ProvisionerDaemon.FailJob:input_type -> provisionerd.FailedJob
9, // 29: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse 4, // 29: provisionerd.ProvisionerDaemon.CompleteJob:input_type -> provisionerd.CompletedJob
7, // 30: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse 2, // 30: provisionerd.ProvisionerDaemon.AcquireJob:output_type -> provisionerd.AcquiredJob
1, // 31: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty 9, // 31: provisionerd.ProvisionerDaemon.CommitQuota:output_type -> provisionerd.CommitQuotaResponse
1, // 32: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty 7, // 32: provisionerd.ProvisionerDaemon.UpdateJob:output_type -> provisionerd.UpdateJobResponse
28, // [28:33] is the sub-list for method output_type 1, // 33: provisionerd.ProvisionerDaemon.FailJob:output_type -> provisionerd.Empty
23, // [23:28] is the sub-list for method input_type 1, // 34: provisionerd.ProvisionerDaemon.CompleteJob:output_type -> provisionerd.Empty
23, // [23:23] is the sub-list for extension type_name 30, // [30:35] is the sub-list for method output_type
23, // [23:23] is the sub-list for extension extendee 25, // [25:30] is the sub-list for method input_type
0, // [0:23] is the sub-list for field type_name 25, // [25:25] is the sub-list for extension type_name
25, // [25:25] is the sub-list for extension extendee
0, // [0:25] is the sub-list for field type_name
} }
func init() { file_provisionerd_proto_provisionerd_proto_init() } func init() { file_provisionerd_proto_provisionerd_proto_init() }

View File

@ -15,8 +15,9 @@ message AcquiredJob {
string workspace_build_id = 1; string workspace_build_id = 1;
string workspace_name = 2; string workspace_name = 2;
repeated provisioner.ParameterValue parameter_values = 3; repeated provisioner.ParameterValue parameter_values = 3;
provisioner.Provision.Metadata metadata = 4; repeated provisioner.RichParameterValue rich_parameter_values = 4;
bytes state = 5; provisioner.Provision.Metadata metadata = 5;
bytes state = 6;
} }
message TemplateImport { message TemplateImport {
provisioner.Provision.Metadata metadata = 1; provisioner.Provision.Metadata metadata = 1;
@ -63,6 +64,7 @@ message CompletedJob {
message TemplateImport { message TemplateImport {
repeated provisioner.Resource start_resources = 1; repeated provisioner.Resource start_resources = 1;
repeated provisioner.Resource stop_resources = 2; repeated provisioner.Resource stop_resources = 2;
repeated provisioner.RichParameter rich_parameters = 3;
} }
message TemplateDryRun { message TemplateDryRun {
repeated provisioner.Resource resources = 1; repeated provisioner.Resource resources = 1;

View File

@ -434,6 +434,7 @@ func (r *Runner) do(ctx context.Context) (*proto.CompletedJob, *proto.FailedJob)
slog.F("workspace_name", jobType.WorkspaceBuild.WorkspaceName), slog.F("workspace_name", jobType.WorkspaceBuild.WorkspaceName),
slog.F("state_length", len(jobType.WorkspaceBuild.State)), slog.F("state_length", len(jobType.WorkspaceBuild.State)),
slog.F("parameters", jobType.WorkspaceBuild.ParameterValues), slog.F("parameters", jobType.WorkspaceBuild.ParameterValues),
slog.F("rich_parameter_values", jobType.WorkspaceBuild.RichParameterValues),
) )
return r.runWorkspaceBuild(ctx) return r.runWorkspaceBuild(ctx)
default: default:
@ -566,7 +567,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
Stage: "Detecting persistent resources", Stage: "Detecting persistent resources",
CreatedAt: time.Now().UnixMilli(), CreatedAt: time.Now().UnixMilli(),
}) })
startResources, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, &sdkproto.Provision_Metadata{ startResources, parameters, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, &sdkproto.Provision_Metadata{
CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl,
WorkspaceTransition: sdkproto.WorkspaceTransition_START, WorkspaceTransition: sdkproto.WorkspaceTransition_START,
}) })
@ -581,7 +582,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
Stage: "Detecting ephemeral resources", Stage: "Detecting ephemeral resources",
CreatedAt: time.Now().UnixMilli(), CreatedAt: time.Now().UnixMilli(),
}) })
stopResources, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, &sdkproto.Provision_Metadata{ stopResources, _, err := r.runTemplateImportProvision(ctx, updateResponse.ParameterValues, &sdkproto.Provision_Metadata{
CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl, CoderUrl: r.job.GetTemplateImport().Metadata.CoderUrl,
WorkspaceTransition: sdkproto.WorkspaceTransition_STOP, WorkspaceTransition: sdkproto.WorkspaceTransition_STOP,
}) })
@ -595,6 +596,7 @@ func (r *Runner) runTemplateImport(ctx context.Context) (*proto.CompletedJob, *p
TemplateImport: &proto.CompletedJob_TemplateImport{ TemplateImport: &proto.CompletedJob_TemplateImport{
StartResources: startResources, StartResources: startResources,
StopResources: stopResources, StopResources: stopResources,
RichParameters: parameters,
}, },
}, },
}, nil }, nil
@ -646,7 +648,7 @@ func (r *Runner) runTemplateImportParse(ctx context.Context) ([]*sdkproto.Parame
// Performs a dry-run provision when importing a template. // Performs a dry-run provision when importing a template.
// This is used to detect resources that would be provisioned // This is used to detect resources that would be provisioned
// for a workspace in various states. // for a workspace in various states.
func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkproto.ParameterValue, metadata *sdkproto.Provision_Metadata) ([]*sdkproto.Resource, error) { func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkproto.ParameterValue, metadata *sdkproto.Provision_Metadata) ([]*sdkproto.Resource, []*sdkproto.RichParameter, error) {
ctx, span := r.startTrace(ctx, tracing.FuncName()) ctx, span := r.startTrace(ctx, tracing.FuncName())
defer span.End() defer span.End()
@ -661,7 +663,7 @@ func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkpr
// to send the cancel to the provisioner // to send the cancel to the provisioner
stream, err := r.provisioner.Provision(ctx) stream, err := r.provisioner.Provision(ctx)
if err != nil { if err != nil {
return nil, xerrors.Errorf("provision: %w", err) return nil, nil, xerrors.Errorf("provision: %w", err)
} }
defer stream.Close() defer stream.Close()
go func() { go func() {
@ -688,13 +690,13 @@ func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkpr
}, },
}) })
if err != nil { if err != nil {
return nil, xerrors.Errorf("start provision: %w", err) return nil, nil, xerrors.Errorf("start provision: %w", err)
} }
for { for {
msg, err := stream.Recv() msg, err := stream.Recv()
if err != nil { if err != nil {
return nil, xerrors.Errorf("recv import provision: %w", err) return nil, nil, xerrors.Errorf("recv import provision: %w", err)
} }
switch msgType := msg.Type.(type) { switch msgType := msg.Type.(type) {
case *sdkproto.Provision_Response_Log: case *sdkproto.Provision_Response_Log:
@ -715,7 +717,7 @@ func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkpr
slog.F("error", msgType.Complete.Error), slog.F("error", msgType.Complete.Error),
) )
return nil, xerrors.New(msgType.Complete.Error) return nil, nil, xerrors.New(msgType.Complete.Error)
} }
r.logger.Info(context.Background(), "parse dry-run provision successful", r.logger.Info(context.Background(), "parse dry-run provision successful",
@ -724,9 +726,9 @@ func (r *Runner) runTemplateImportProvision(ctx context.Context, values []*sdkpr
slog.F("state_length", len(msgType.Complete.State)), slog.F("state_length", len(msgType.Complete.State)),
) )
return msgType.Complete.Resources, nil return msgType.Complete.Resources, msgType.Complete.Parameters, nil
default: default:
return nil, xerrors.Errorf("invalid message type %q received from provisioner", return nil, nil, xerrors.Errorf("invalid message type %q received from provisioner",
reflect.TypeOf(msg.Type).String()) reflect.TypeOf(msg.Type).String())
} }
} }
@ -765,7 +767,7 @@ func (r *Runner) runTemplateDryRun(ctx context.Context) (*proto.CompletedJob, *p
} }
// Run the template import provision task since it's already a dry run. // Run the template import provision task since it's already a dry run.
resources, err := r.runTemplateImportProvision(ctx, resources, _, err := r.runTemplateImportProvision(ctx,
r.job.GetTemplateDryRun().GetParameterValues(), r.job.GetTemplateDryRun().GetParameterValues(),
metadata, metadata,
) )

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,34 @@ message ParameterSchema {
string validation_condition = 11; string validation_condition = 11;
} }
// RichParameterOption represents a singular option that a parameter may expose.
message RichParameterOption {
string name = 1;
string description = 2;
string value = 3;
string icon = 4;
}
// RichParameter represents a variable that is exposed.
message RichParameter {
string name = 1;
string description = 2;
string type = 3;
bool mutable = 4;
string default_value = 5;
string icon = 6;
repeated RichParameterOption options = 7;
string validation_regex = 8;
int32 validation_min = 9;
int32 validation_max = 10;
}
// RichParameterValue holds the key/value mapping of a parameter.
message RichParameterValue {
string name = 1;
string value = 2;
}
// LogLevel represents severity of the log. // LogLevel represents severity of the log.
enum LogLevel { enum LogLevel {
TRACE = 0; TRACE = 0;
@ -183,6 +211,7 @@ message Provision {
message Plan { message Plan {
Config config = 1; Config config = 1;
repeated ParameterValue parameter_values = 2; repeated ParameterValue parameter_values = 2;
repeated RichParameterValue rich_parameter_values = 3;
} }
message Apply { message Apply {
@ -201,8 +230,9 @@ message Provision {
message Complete { message Complete {
bytes state = 1; bytes state = 1;
string error = 2; string error = 2;
bytes plan = 4;
repeated Resource resources = 3; repeated Resource resources = 3;
repeated RichParameter parameters = 4;
bytes plan = 5;
} }
message Response { message Response {
oneof type { oneof type {

View File

@ -242,6 +242,7 @@ export interface CreateWorkspaceRequest {
readonly autostart_schedule?: string readonly autostart_schedule?: string
readonly ttl_ms?: number readonly ttl_ms?: number
readonly parameter_values?: CreateParameterRequest[] readonly parameter_values?: CreateParameterRequest[]
readonly rich_parameter_values?: WorkspaceBuildParameter[]
} }
// From codersdk/templates.go // From codersdk/templates.go
@ -735,6 +736,29 @@ export interface TemplateVersion {
readonly created_by: User readonly created_by: User
} }
// From codersdk/templateversions.go
export interface TemplateVersionParameter {
readonly name: string
readonly description: string
readonly type: string
readonly mutable: boolean
readonly default_value: string
readonly icon: string
readonly options: TemplateVersionParameterOption[]
readonly validation_error: string
readonly validation_regex: string
readonly validation_min: number
readonly validation_max: number
}
// From codersdk/templateversions.go
export interface TemplateVersionParameterOption {
readonly name: string
readonly description: string
readonly value: string
readonly icon: string
}
// From codersdk/templates.go // From codersdk/templates.go
export interface TemplateVersionsByTemplateRequest extends Pagination { export interface TemplateVersionsByTemplateRequest extends Pagination {
readonly template_id: string readonly template_id: string
@ -963,6 +987,12 @@ export interface WorkspaceBuild {
readonly daily_cost: number readonly daily_cost: number
} }
// From codersdk/workspacebuilds.go
export interface WorkspaceBuildParameter {
readonly name: string
readonly value: string
}
// From codersdk/workspaces.go // From codersdk/workspaces.go
export interface WorkspaceBuildsRequest extends Pagination { export interface WorkspaceBuildsRequest extends Pagination {
readonly WorkspaceID: string readonly WorkspaceID: string