mirror of
https://github.com/coder/coder.git
synced 2025-07-18 14:17:22 +00:00
feat: evaluate provisioner tags (#13333)
This commit is contained in:
@ -10,6 +10,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/hcl/v2"
|
||||||
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||||
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
|
||||||
"github.com/coder/coder/v2/coderd/rbac/policy"
|
"github.com/coder/coder/v2/coderd/rbac/policy"
|
||||||
"github.com/coder/coder/v2/provisionersdk"
|
"github.com/coder/coder/v2/provisionersdk"
|
||||||
|
|
||||||
@ -55,14 +59,17 @@ type Builder struct {
|
|||||||
store database.Store
|
store database.Store
|
||||||
|
|
||||||
// cache of objects, so we only fetch once
|
// cache of objects, so we only fetch once
|
||||||
template *database.Template
|
template *database.Template
|
||||||
templateVersion *database.TemplateVersion
|
templateVersion *database.TemplateVersion
|
||||||
templateVersionJob *database.ProvisionerJob
|
templateVersionJob *database.ProvisionerJob
|
||||||
templateVersionParameters *[]database.TemplateVersionParameter
|
templateVersionParameters *[]database.TemplateVersionParameter
|
||||||
lastBuild *database.WorkspaceBuild
|
templateVersionWorkspaceTags *[]database.TemplateVersionWorkspaceTag
|
||||||
lastBuildErr *error
|
lastBuild *database.WorkspaceBuild
|
||||||
lastBuildParameters *[]database.WorkspaceBuildParameter
|
lastBuildErr *error
|
||||||
lastBuildJob *database.ProvisionerJob
|
lastBuildParameters *[]database.WorkspaceBuildParameter
|
||||||
|
lastBuildJob *database.ProvisionerJob
|
||||||
|
parameterNames *[]string
|
||||||
|
parameterValues *[]string
|
||||||
|
|
||||||
verifyNoLegacyParametersOnce bool
|
verifyNoLegacyParametersOnce bool
|
||||||
}
|
}
|
||||||
@ -297,7 +304,11 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, BuildError{http.StatusInternalServerError, "marshal metadata", err}
|
return nil, nil, BuildError{http.StatusInternalServerError, "marshal metadata", err}
|
||||||
}
|
}
|
||||||
tags := provisionersdk.MutateTags(b.workspace.OwnerID, templateVersionJob.Tags)
|
|
||||||
|
tags, err := b.getProvisionerTags()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err // already wrapped BuildError
|
||||||
|
}
|
||||||
|
|
||||||
now := dbtime.Now()
|
now := dbtime.Now()
|
||||||
provisionerJob, err := b.store.InsertProvisionerJob(b.ctx, database.InsertProvisionerJobParams{
|
provisionerJob, err := b.store.InsertProvisionerJob(b.ctx, database.InsertProvisionerJobParams{
|
||||||
@ -364,6 +375,7 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
|
|||||||
// getParameters already wraps errors in BuildError
|
// getParameters already wraps errors in BuildError
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.InsertWorkspaceBuildParameters(b.ctx, database.InsertWorkspaceBuildParametersParams{
|
err = store.InsertWorkspaceBuildParameters(b.ctx, database.InsertWorkspaceBuildParametersParams{
|
||||||
WorkspaceBuildID: workspaceBuildID,
|
WorkspaceBuildID: workspaceBuildID,
|
||||||
Name: names,
|
Name: names,
|
||||||
@ -502,6 +514,10 @@ func (b *Builder) getState() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) getParameters() (names, values []string, err error) {
|
func (b *Builder) getParameters() (names, values []string, err error) {
|
||||||
|
if b.parameterNames != nil {
|
||||||
|
return *b.parameterNames, *b.parameterValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
templateVersionParameters, err := b.getTemplateVersionParameters()
|
templateVersionParameters, err := b.getTemplateVersionParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, BuildError{http.StatusInternalServerError, "failed to fetch template version parameters", err}
|
return nil, nil, BuildError{http.StatusInternalServerError, "failed to fetch template version parameters", err}
|
||||||
@ -535,6 +551,9 @@ func (b *Builder) getParameters() (names, values []string, err error) {
|
|||||||
names = append(names, templateVersionParameter.Name)
|
names = append(names, templateVersionParameter.Name)
|
||||||
values = append(values, value)
|
values = append(values, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.parameterNames = &names
|
||||||
|
b.parameterValues = &values
|
||||||
return names, values, nil
|
return names, values, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,6 +651,108 @@ func (b *Builder) getLastBuildJob() (*database.ProvisionerJob, error) {
|
|||||||
return b.lastBuildJob, nil
|
return b.lastBuildJob, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Builder) getProvisionerTags() (map[string]string, error) {
|
||||||
|
// Step 1: Mutate template version tags
|
||||||
|
templateVersionJob, err := b.getTemplateVersionJob()
|
||||||
|
if err != nil {
|
||||||
|
return nil, BuildError{http.StatusInternalServerError, "failed to fetch template version job", err}
|
||||||
|
}
|
||||||
|
annotationTags := provisionersdk.MutateTags(b.workspace.OwnerID, templateVersionJob.Tags)
|
||||||
|
|
||||||
|
tags := map[string]string{}
|
||||||
|
for name, value := range annotationTags {
|
||||||
|
tags[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Mutate workspace tags
|
||||||
|
workspaceTags, err := b.getTemplateVersionWorkspaceTags()
|
||||||
|
if err != nil {
|
||||||
|
return nil, BuildError{http.StatusInternalServerError, "failed to fetch template version workspace tags", err}
|
||||||
|
}
|
||||||
|
parameterNames, parameterValues, err := b.getParameters()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err // already wrapped BuildError
|
||||||
|
}
|
||||||
|
|
||||||
|
evalCtx := buildParametersEvalContext(parameterNames, parameterValues)
|
||||||
|
for _, workspaceTag := range workspaceTags {
|
||||||
|
expr, diags := hclsyntax.ParseExpression([]byte(workspaceTag.Value), "expression.hcl", hcl.InitialPos)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
return nil, BuildError{http.StatusBadRequest, "failed to parse workspace tag value", xerrors.Errorf(diags.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
val, diags := expr.Value(evalCtx)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
return nil, BuildError{http.StatusBadRequest, "failed to evaluate workspace tag value", xerrors.Errorf(diags.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not use "val.AsString()" as it can panic
|
||||||
|
str, err := ctyValueString(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, BuildError{http.StatusBadRequest, "failed to marshal cty.Value as string", err}
|
||||||
|
}
|
||||||
|
tags[workspaceTag.Key] = str
|
||||||
|
}
|
||||||
|
return tags, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildParametersEvalContext(names, values []string) *hcl.EvalContext {
|
||||||
|
m := map[string]cty.Value{}
|
||||||
|
for i, name := range names {
|
||||||
|
m[name] = cty.MapVal(map[string]cty.Value{
|
||||||
|
"value": cty.StringVal(values[i]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
return nil // otherwise, panic: must not call MapVal with empty map
|
||||||
|
}
|
||||||
|
|
||||||
|
return &hcl.EvalContext{
|
||||||
|
Variables: map[string]cty.Value{
|
||||||
|
"data": cty.MapVal(map[string]cty.Value{
|
||||||
|
"coder_parameter": cty.MapVal(m),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ctyValueString(val cty.Value) (string, error) {
|
||||||
|
switch val.Type() {
|
||||||
|
case cty.Bool:
|
||||||
|
if val.True() {
|
||||||
|
return "true", nil
|
||||||
|
} else {
|
||||||
|
return "false", nil
|
||||||
|
}
|
||||||
|
case cty.Number:
|
||||||
|
return val.AsBigFloat().String(), nil
|
||||||
|
case cty.String:
|
||||||
|
return val.AsString(), nil
|
||||||
|
default:
|
||||||
|
return "", xerrors.Errorf("only primitive types are supported - bool, number, and string")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Builder) getTemplateVersionWorkspaceTags() ([]database.TemplateVersionWorkspaceTag, error) {
|
||||||
|
if b.templateVersionWorkspaceTags != nil {
|
||||||
|
return *b.templateVersionWorkspaceTags, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
templateVersion, err := b.getTemplateVersion()
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("get template version: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceTags, err := b.store.GetTemplateVersionWorkspaceTags(b.ctx, templateVersion.ID)
|
||||||
|
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
|
||||||
|
return nil, xerrors.Errorf("get template version workspace tags: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.templateVersionWorkspaceTags = &workspaceTags
|
||||||
|
return *b.templateVersionWorkspaceTags, nil
|
||||||
|
}
|
||||||
|
|
||||||
// authorize performs build authorization pre-checks using the provided authFunc
|
// authorize performs build authorization pre-checks using the provided authFunc
|
||||||
func (b *Builder) authorize(authFunc func(action policy.Action, object rbac.Objecter) bool) error {
|
func (b *Builder) authorize(authFunc func(action policy.Action, object rbac.Objecter) bool) error {
|
||||||
// Doing this up front saves a lot of work if the user doesn't have permission.
|
// Doing this up front saves a lot of work if the user doesn't have permission.
|
||||||
|
@ -60,6 +60,7 @@ func TestBuilder_NoOptions(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(nil),
|
withRichParameters(nil),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
||||||
@ -112,6 +113,7 @@ func TestBuilder_Initiator(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(nil),
|
withRichParameters(nil),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
||||||
@ -154,6 +156,7 @@ func TestBuilder_Baggage(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(nil),
|
withRichParameters(nil),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
||||||
@ -188,9 +191,10 @@ func TestBuilder_Reason(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(nil),
|
withRichParameters(nil),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
expectProvisionerJob(func(_ database.InsertProvisionerJobParams) {
|
||||||
}),
|
}),
|
||||||
withInTx,
|
withInTx,
|
||||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||||
@ -221,6 +225,7 @@ func TestBuilder_ActiveVersion(t *testing.T) {
|
|||||||
withActiveVersion(nil),
|
withActiveVersion(nil),
|
||||||
withLastBuildNotFound,
|
withLastBuildNotFound,
|
||||||
withParameterSchemas(activeJobID, nil),
|
withParameterSchemas(activeJobID, nil),
|
||||||
|
withWorkspaceTags(activeVersionID, nil),
|
||||||
// previous rich parameters are not queried because there is no previous build.
|
// previous rich parameters are not queried because there is no previous build.
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
@ -246,6 +251,102 @@ func TestBuilder_ActiveVersion(t *testing.T) {
|
|||||||
req.NoError(err)
|
req.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWorkspaceBuildWithTags(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
asrt := assert.New(t)
|
||||||
|
req := require.New(t)
|
||||||
|
|
||||||
|
workspaceTags := []database.TemplateVersionWorkspaceTag{
|
||||||
|
{
|
||||||
|
Key: "fruits_tag",
|
||||||
|
Value: "data.coder_parameter.number_of_apples.value + data.coder_parameter.number_of_oranges.value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "cluster_tag",
|
||||||
|
Value: `"best_developers"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "project_tag",
|
||||||
|
Value: `"${data.coder_parameter.project.value}+12345"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "team_tag",
|
||||||
|
Value: `data.coder_parameter.team.value`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "yes_or_no",
|
||||||
|
Value: `data.coder_parameter.is_debug_build.value`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "actually_no",
|
||||||
|
Value: `!data.coder_parameter.is_debug_build.value`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "is_debug_build",
|
||||||
|
Value: `data.coder_parameter.is_debug_build.value == "true" ? "in-debug-mode" : "no-debug"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
richParameters := []database.TemplateVersionParameter{
|
||||||
|
// Parameters can be mutable although it is discouraged as the workspace can be moved between provisioner nodes.
|
||||||
|
{Name: "project", Description: "This is first parameter", Mutable: true, Options: json.RawMessage("[]")},
|
||||||
|
{Name: "team", Description: "This is second parameter", Mutable: true, DefaultValue: "godzilla", Options: json.RawMessage("[]")},
|
||||||
|
{Name: "is_debug_build", Type: "bool", Description: "This is third parameter", Mutable: false, DefaultValue: "false", Options: json.RawMessage("[]")},
|
||||||
|
{Name: "number_of_apples", Type: "number", Description: "This is fourth parameter", Mutable: false, DefaultValue: "4", Options: json.RawMessage("[]")},
|
||||||
|
{Name: "number_of_oranges", Type: "number", Description: "This is fifth parameter", Mutable: false, DefaultValue: "6", Options: json.RawMessage("[]")},
|
||||||
|
}
|
||||||
|
|
||||||
|
buildParameters := []codersdk.WorkspaceBuildParameter{
|
||||||
|
{Name: "project", Value: "foobar-foobaz"},
|
||||||
|
{Name: "is_debug_build", Value: "true"},
|
||||||
|
// Parameters "team", "number_of_apples", "number_of_oranges" are skipped, so default value is selected
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
mDB := expectDB(t,
|
||||||
|
// Inputs
|
||||||
|
withTemplate,
|
||||||
|
withInactiveVersion(richParameters),
|
||||||
|
withLastBuildFound,
|
||||||
|
withRichParameters(nil),
|
||||||
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, workspaceTags),
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {
|
||||||
|
asrt.Len(job.Tags, 10)
|
||||||
|
|
||||||
|
expected := database.StringMap{
|
||||||
|
"actually_no": "false",
|
||||||
|
"cluster_tag": "best_developers",
|
||||||
|
"fruits_tag": "10",
|
||||||
|
"is_debug_build": "in-debug-mode",
|
||||||
|
"project_tag": "foobar-foobaz+12345",
|
||||||
|
"team_tag": "godzilla",
|
||||||
|
"yes_or_no": "true",
|
||||||
|
|
||||||
|
"scope": "user",
|
||||||
|
"version": "inactive",
|
||||||
|
"owner": userID.String(),
|
||||||
|
}
|
||||||
|
asrt.Equal(job.Tags, expected)
|
||||||
|
}),
|
||||||
|
withInTx,
|
||||||
|
expectBuild(func(_ database.InsertWorkspaceBuildParams) {}),
|
||||||
|
expectBuildParameters(func(_ database.InsertWorkspaceBuildParametersParams) {
|
||||||
|
}),
|
||||||
|
withBuild,
|
||||||
|
)
|
||||||
|
|
||||||
|
ws := database.Workspace{ID: workspaceID, TemplateID: templateID, OwnerID: userID}
|
||||||
|
uut := wsbuilder.New(ws, database.WorkspaceTransitionStart).RichParameterValues(buildParameters)
|
||||||
|
_, _, err := uut.Build(ctx, mDB, nil, audit.WorkspaceBuildBaggage{})
|
||||||
|
req.NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -302,6 +403,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||||
@ -345,6 +447,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||||
@ -394,11 +497,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(nil),
|
withRichParameters(nil),
|
||||||
withParameterSchemas(inactiveJobID, schemas),
|
withParameterSchemas(inactiveJobID, schemas),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
// Outputs
|
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
|
||||||
withInTx,
|
|
||||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {}),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ws := database.Workspace{ID: workspaceID, TemplateID: templateID, OwnerID: userID}
|
ws := database.Workspace{ID: workspaceID, TemplateID: templateID, OwnerID: userID}
|
||||||
@ -429,13 +528,10 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(inactiveJobID, nil),
|
withParameterSchemas(inactiveJobID, nil),
|
||||||
|
withWorkspaceTags(inactiveVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
// no transaction, since we failed fast while validation build parameters
|
||||||
withInTx,
|
|
||||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {}),
|
|
||||||
// no build parameters, since we hit an error validating.
|
|
||||||
// expectBuildParameters(func(params database.InsertWorkspaceBuildParametersParams) {}),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ws := database.Workspace{ID: workspaceID, TemplateID: templateID, OwnerID: userID}
|
ws := database.Workspace{ID: workspaceID, TemplateID: templateID, OwnerID: userID}
|
||||||
@ -482,6 +578,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(activeJobID, nil),
|
withParameterSchemas(activeJobID, nil),
|
||||||
|
withWorkspaceTags(activeVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||||
@ -542,6 +639,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(activeJobID, nil),
|
withParameterSchemas(activeJobID, nil),
|
||||||
|
withWorkspaceTags(activeVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||||
@ -600,6 +698,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
|||||||
withLastBuildFound,
|
withLastBuildFound,
|
||||||
withRichParameters(initialBuildParameters),
|
withRichParameters(initialBuildParameters),
|
||||||
withParameterSchemas(activeJobID, nil),
|
withParameterSchemas(activeJobID, nil),
|
||||||
|
withWorkspaceTags(activeVersionID, nil),
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||||
@ -813,6 +912,18 @@ func withRichParameters(params []database.WorkspaceBuildParameter) func(mTx *dbm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withWorkspaceTags(versionID uuid.UUID, tags []database.TemplateVersionWorkspaceTag) func(mTx *dbmock.MockStore) {
|
||||||
|
return func(mTx *dbmock.MockStore) {
|
||||||
|
c := mTx.EXPECT().GetTemplateVersionWorkspaceTags(gomock.Any(), versionID).
|
||||||
|
Times(1)
|
||||||
|
if len(tags) > 0 {
|
||||||
|
c.Return(tags, nil)
|
||||||
|
} else {
|
||||||
|
c.Return(nil, sql.ErrNoRows)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Since there is expected to be only one each of job, build, and build-parameters inserted, instead
|
// Since there is expected to be only one each of job, build, and build-parameters inserted, instead
|
||||||
// of building matchers, we match any call and then assert its parameters. This will feel
|
// of building matchers, we match any call and then assert its parameters. This will feel
|
||||||
// more familiar to the way we write other tests.
|
// more familiar to the way we write other tests.
|
||||||
|
Reference in New Issue
Block a user