From 19ec74707b18791f8ba7d186b922d973edd7f051 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Tue, 15 Apr 2025 10:55:29 +0000 Subject: [PATCH 1/6] fix: add some more thorough testing for preset workspace creation --- coderd/workspaces_test.go | 278 +++++++++++++++++++++++++++++++++----- 1 file changed, 244 insertions(+), 34 deletions(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 136e259d541f9..c7e75466f8aa6 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -426,47 +426,257 @@ func TestWorkspace(t *testing.T) { t.Run("TemplateVersionPreset", func(t *testing.T) { t.Parallel() - client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) - user := coderdtest.CreateFirstUser(t, client) - authz := coderdtest.AssertRBAC(t, api, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: []*proto.Response{{ - Type: &proto.Response_Plan{ - Plan: &proto.PlanComplete{ - Presets: []*proto.Preset{{ - Name: "test", - }}, + + testCases := []struct { + name string + presets []*proto.Preset + expectedCount int + selectedPresetIndex int // Index of the preset to use, or -1 if no preset should be used + }{ + { + name: "No Presets", + presets: []*proto.Preset{}, + expectedCount: 0, + selectedPresetIndex: -1, + }, + { + name: "Single Preset - No Parameters", + presets: []*proto.Preset{{ + Name: "test", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }}, + expectedCount: 1, + selectedPresetIndex: 0, + }, + { + name: "Single Preset - With Parameters", + presets: []*proto.Preset{{ + Name: "test", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, }, + }}, + expectedCount: 1, + selectedPresetIndex: 0, + }, + { + name: "Multiple Presets - No Parameters", + presets: []*proto.Preset{ + {Name: "test1"}, + {Name: "test2"}, + {Name: "test3"}, }, - }}, - ProvisionApply: echo.ApplyComplete, - }) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + expectedCount: 3, + selectedPresetIndex: 0, + }, + { + name: "Multiple Presets - First Has Parameters", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + {Name: "test2"}, + {Name: "test3"}, + }, + expectedCount: 3, + selectedPresetIndex: 0, + }, + { + name: "Multiple Presets - Middle Has Parameters", + presets: []*proto.Preset{ + {Name: "test1"}, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + {Name: "test3"}, + }, + expectedCount: 3, + selectedPresetIndex: 1, + }, + { + name: "Multiple Presets - Last Has Parameters", + presets: []*proto.Preset{ + {Name: "test1"}, + {Name: "test2"}, + { + Name: "test3", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + }, + expectedCount: 3, + selectedPresetIndex: 2, + }, + { + name: "Multiple Presets - All Have Parameters", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + }, + }, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param2", Value: "value2"}, + }, + }, + { + Name: "test3", + Parameters: []*proto.PresetParameter{ + {Name: "param3", Value: "value3"}, + }, + }, + }, + expectedCount: 3, + selectedPresetIndex: 1, + }, + { + name: "Multiple Presets - With Parameters But Not Used", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + }, + }, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param2", Value: "value2"}, + }, + }, + }, + expectedCount: 2, + selectedPresetIndex: -1, + }, + } - ctx := testutil.Context(t, testutil.WaitLong) + for _, tc := range testCases { + tc := tc // Capture range variable + t.Run(tc.name, func(t *testing.T) { + t.Parallel() - presets, err := client.TemplateVersionPresets(ctx, version.ID) - require.NoError(t, err) - require.Equal(t, 1, len(presets)) - require.Equal(t, "test", presets[0].Name) + client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) + authz := coderdtest.AssertRBAC(t, api, client) - workspace := coderdtest.CreateWorkspace(t, client, template.ID, func(request *codersdk.CreateWorkspaceRequest) { - request.TemplateVersionPresetID = presets[0].ID - }) + // Create a plan response with the specified presets + planResponse := &proto.Response{ + Type: &proto.Response_Plan{ + Plan: &proto.PlanComplete{ + Presets: tc.presets, + }, + }, + } - authz.Reset() // Reset all previous checks done in setup. - ws, err := client.Workspace(ctx, workspace.ID) - authz.AssertChecked(t, policy.ActionRead, ws) - require.NoError(t, err) - require.Equal(t, user.UserID, ws.LatestBuild.InitiatorID) - require.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) - require.Equal(t, presets[0].ID, *ws.LatestBuild.TemplateVersionPresetID) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ + Parse: echo.ParseComplete, + ProvisionPlan: []*proto.Response{planResponse}, + ProvisionApply: echo.ApplyComplete, + }) + coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - org, err := client.Organization(ctx, ws.OrganizationID) - require.NoError(t, err) - require.Equal(t, ws.OrganizationName, org.Name) + ctx := testutil.Context(t, testutil.WaitLong) + + // Check presets + presets, err := client.TemplateVersionPresets(ctx, version.ID) + require.NoError(t, err) + require.Equal(t, tc.expectedCount, len(presets)) + + if tc.expectedCount > 0 { + // Verify preset names and parameters + for i, preset := range presets { + require.Equal(t, tc.presets[i].Name, preset.Name) + + // Check if the preset should have parameters + if tc.presets[i].Parameters != nil { + // Verify that the preset has the expected parameters + for _, param := range tc.presets[i].Parameters { + found := false + for _, presetParam := range preset.Parameters { + if param.Name == presetParam.Name { + require.Equal(t, param.Value, presetParam.Value, + "Parameter %s should have value %s", param.Name, param.Value) + found = true + break + } + } + require.True(t, found, "Parameter %s should be present in preset", param.Name) + } + } + } + } + + // Create workspace with or without preset + var workspace codersdk.Workspace + if tc.selectedPresetIndex >= 0 && tc.expectedCount > 0 { + // Use the selected preset + selectedIndex := tc.selectedPresetIndex + if selectedIndex >= len(presets) { + selectedIndex = 0 // Fallback to first preset if index is out of bounds + } + + workspace = coderdtest.CreateWorkspace(t, client, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.TemplateVersionPresetID = presets[selectedIndex].ID + }) + } else { + workspace = coderdtest.CreateWorkspace(t, client, template.ID) + } + + // Verify workspace details + authz.Reset() // Reset all previous checks done in setup. + ws, err := client.Workspace(ctx, workspace.ID) + authz.AssertChecked(t, policy.ActionRead, ws) + require.NoError(t, err) + require.Equal(t, user.UserID, ws.LatestBuild.InitiatorID) + require.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) + + // Check preset ID if expected + if tc.selectedPresetIndex >= 0 && tc.expectedCount > 0 { + require.NotNil(t, ws.LatestBuild.TemplateVersionPresetID) + + // Use the selected preset index + selectedIndex := tc.selectedPresetIndex + if selectedIndex >= len(presets) { + selectedIndex = 0 // Fallback to first preset if index is out of bounds + } + + require.Equal(t, presets[selectedIndex].ID, *ws.LatestBuild.TemplateVersionPresetID) + + // If the selected preset has parameters, verify they were applied + if tc.presets[selectedIndex].Parameters != nil { + // This would require additional verification based on how parameters + // are stored in the workspace. For now, we'll just log that we checked. + t.Logf("Selected preset %s has parameters that should be applied to the workspace", + tc.presets[selectedIndex].Name) + } + } else { + require.Nil(t, ws.LatestBuild.TemplateVersionPresetID) + } + + // Verify organization + org, err := client.Organization(ctx, ws.OrganizationID) + require.NoError(t, err) + require.Equal(t, ws.OrganizationName, org.Name) + }) + } }) } From 2fad945e31383e665ba71ba48bf3af3f45f08ee0 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Tue, 15 Apr 2025 13:57:06 +0000 Subject: [PATCH 2/6] fix: set preset parameters in the API instead of relying on the frontend --- coderd/workspaces_test.go | 268 ++++++++++++++++++++++++++++------ coderd/wsbuilder/wsbuilder.go | 42 ++++-- 2 files changed, 256 insertions(+), 54 deletions(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index c7e75466f8aa6..cbc2503feed74 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -428,19 +428,39 @@ func TestWorkspace(t *testing.T) { t.Parallel() testCases := []struct { - name string - presets []*proto.Preset - expectedCount int - selectedPresetIndex int // Index of the preset to use, or -1 if no preset should be used + name string + presets []*proto.Preset + templateVersionParameters []*proto.RichParameter + selectedPresetIndex int // -1 if no preset should be used }{ { - name: "No Presets", - presets: []*proto.Preset{}, - expectedCount: 0, - selectedPresetIndex: -1, + name: "No Presets", + presets: []*proto.Preset{}, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: -1, }, { name: "Single Preset - No Parameters", + presets: []*proto.Preset{{ + Name: "test", + }}, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 0, + }, + { + name: "Single Preset - With Parameters But No Template Parameters", + presets: []*proto.Preset{{ + Name: "test", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }}, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 0, + }, + { + name: "Single Preset - With Matching Parameters", presets: []*proto.Preset{{ Name: "test", Parameters: []*proto.PresetParameter{ @@ -448,19 +468,26 @@ func TestWorkspace(t *testing.T) { {Name: "param2", Value: "value2"}, }, }}, - expectedCount: 1, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: true}, + {Name: "param2", Type: "string", Required: true}, + }, selectedPresetIndex: 0, }, { - name: "Single Preset - With Parameters", + name: "Single Preset - With Partial Matching Parameters", presets: []*proto.Preset{{ Name: "test", Parameters: []*proto.PresetParameter{ {Name: "param1", Value: "value1"}, {Name: "param2", Value: "value2"}, + {Name: "param3", Value: "value3"}, // This parameter doesn't exist in template }, }}, - expectedCount: 1, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: false}, + {Name: "param2", Type: "string", Required: false}, + }, selectedPresetIndex: 0, }, { @@ -470,8 +497,8 @@ func TestWorkspace(t *testing.T) { {Name: "test2"}, {Name: "test3"}, }, - expectedCount: 3, - selectedPresetIndex: 0, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 0, }, { name: "Multiple Presets - First Has Parameters", @@ -486,7 +513,26 @@ func TestWorkspace(t *testing.T) { {Name: "test2"}, {Name: "test3"}, }, - expectedCount: 3, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 0, + }, + { + name: "Multiple Presets - First Has Matching Parameters", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + {Name: "test2"}, + {Name: "test3"}, + }, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: true}, + {Name: "param2", Type: "string", Required: true}, + }, selectedPresetIndex: 0, }, { @@ -502,7 +548,26 @@ func TestWorkspace(t *testing.T) { }, {Name: "test3"}, }, - expectedCount: 3, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 1, + }, + { + name: "Multiple Presets - Middle Has Matching Parameters", + presets: []*proto.Preset{ + {Name: "test1"}, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + {Name: "test3"}, + }, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: true}, + {Name: "param2", Type: "string", Required: true}, + }, selectedPresetIndex: 1, }, { @@ -518,7 +583,26 @@ func TestWorkspace(t *testing.T) { }, }, }, - expectedCount: 3, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 2, + }, + { + name: "Multiple Presets - Last Has Matching Parameters", + presets: []*proto.Preset{ + {Name: "test1"}, + {Name: "test2"}, + { + Name: "test3", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + }, + }, + }, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: true}, + {Name: "param2", Type: "string", Required: true}, + }, selectedPresetIndex: 2, }, { @@ -543,7 +627,36 @@ func TestWorkspace(t *testing.T) { }, }, }, - expectedCount: 3, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: 1, + }, + { + name: "Multiple Presets - All Have Matching Parameters", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + }, + }, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param2", Value: "value2"}, + }, + }, + { + Name: "test3", + Parameters: []*proto.PresetParameter{ + {Name: "param3", Value: "value3"}, + }, + }, + }, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: false}, + {Name: "param2", Type: "string", Required: true}, + {Name: "param3", Type: "string", Required: false}, + }, selectedPresetIndex: 1, }, { @@ -562,7 +675,29 @@ func TestWorkspace(t *testing.T) { }, }, }, - expectedCount: 2, + templateVersionParameters: []*proto.RichParameter{}, + selectedPresetIndex: -1, + }, + { + name: "Multiple Presets - With Matching Parameters But Not Used", + presets: []*proto.Preset{ + { + Name: "test1", + Parameters: []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + }, + }, + { + Name: "test2", + Parameters: []*proto.PresetParameter{ + {Name: "param2", Value: "value2"}, + }, + }, + }, + templateVersionParameters: []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: false}, + {Name: "param2", Type: "string", Required: false}, + }, selectedPresetIndex: -1, }, } @@ -576,11 +711,12 @@ func TestWorkspace(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) authz := coderdtest.AssertRBAC(t, api, client) - // Create a plan response with the specified presets + // Create a plan response with the specified presets and parameters planResponse := &proto.Response{ Type: &proto.Response_Plan{ Plan: &proto.PlanComplete{ - Presets: tc.presets, + Presets: tc.presets, + Parameters: tc.templateVersionParameters, }, }, } @@ -598,9 +734,9 @@ func TestWorkspace(t *testing.T) { // Check presets presets, err := client.TemplateVersionPresets(ctx, version.ID) require.NoError(t, err) - require.Equal(t, tc.expectedCount, len(presets)) + require.Equal(t, len(tc.presets), len(presets)) - if tc.expectedCount > 0 { + if len(tc.presets) > 0 { // Verify preset names and parameters for i, preset := range presets { require.Equal(t, tc.presets[i].Name, preset.Name) @@ -626,15 +762,10 @@ func TestWorkspace(t *testing.T) { // Create workspace with or without preset var workspace codersdk.Workspace - if tc.selectedPresetIndex >= 0 && tc.expectedCount > 0 { + if tc.selectedPresetIndex >= 0 { // Use the selected preset - selectedIndex := tc.selectedPresetIndex - if selectedIndex >= len(presets) { - selectedIndex = 0 // Fallback to first preset if index is out of bounds - } - workspace = coderdtest.CreateWorkspace(t, client, template.ID, func(request *codersdk.CreateWorkspaceRequest) { - request.TemplateVersionPresetID = presets[selectedIndex].ID + request.TemplateVersionPresetID = presets[tc.selectedPresetIndex].ID }) } else { workspace = coderdtest.CreateWorkspace(t, client, template.ID) @@ -649,23 +780,76 @@ func TestWorkspace(t *testing.T) { require.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) // Check preset ID if expected - if tc.selectedPresetIndex >= 0 && tc.expectedCount > 0 { + if tc.selectedPresetIndex >= 0 { require.NotNil(t, ws.LatestBuild.TemplateVersionPresetID) + require.Equal(t, presets[tc.selectedPresetIndex].ID, *ws.LatestBuild.TemplateVersionPresetID) + + // If the selected preset has parameters and there are template version parameters, + // verify that only matching parameters were applied + if tc.presets[tc.selectedPresetIndex].Parameters != nil && len(tc.templateVersionParameters) > 0 { + builds, err := client.WorkspaceBuilds(ctx, codersdk.WorkspaceBuildsRequest{ + WorkspaceID: ws.ID, + }) + require.NoError(t, err) + require.Equal(t, 1, len(builds)) + parameters, err := client.WorkspaceBuildParameters(ctx, builds[0].ID) + require.NoError(t, err) + parametersSetByPreset := 0 + for _, param := range parameters { + for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { + if param.Name == presetParam.Name && param.Value == presetParam.Value { + parametersSetByPreset++ + break + } + } + } - // Use the selected preset index - selectedIndex := tc.selectedPresetIndex - if selectedIndex >= len(presets) { - selectedIndex = 0 // Fallback to first preset if index is out of bounds - } + // Track which template parameters were set by the preset + expectedParamCount := 0 + for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { + for _, templateParam := range tc.templateVersionParameters { + if presetParam.Name == templateParam.Name { + expectedParamCount++ + break + } + } + } - require.Equal(t, presets[selectedIndex].ID, *ws.LatestBuild.TemplateVersionPresetID) + // Verify that only the expected number of parameters were set + require.Equal(t, expectedParamCount, parametersSetByPreset, + "Expected %d parameters to be set, but found %d", expectedParamCount, parametersSetByPreset) + + // Verify each parameter that should have been set + for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { + // Check if this parameter exists in the template version + paramExists := false + for _, templateParam := range tc.templateVersionParameters { + if presetParam.Name == templateParam.Name { + paramExists = true + break + } + } - // If the selected preset has parameters, verify they were applied - if tc.presets[selectedIndex].Parameters != nil { - // This would require additional verification based on how parameters - // are stored in the workspace. For now, we'll just log that we checked. - t.Logf("Selected preset %s has parameters that should be applied to the workspace", - tc.presets[selectedIndex].Name) + if paramExists { + // This parameter should have been set + paramFound := false + for _, appliedParam := range parameters { + if appliedParam.Name == presetParam.Name { + require.Equal(t, presetParam.Value, appliedParam.Value, + "Parameter %s should have value %s", presetParam.Name, presetParam.Value) + paramFound = true + break + } + } + require.True(t, paramFound, "Parameter %s should be applied to the workspace", presetParam.Name) + } else { + // This parameter should NOT have been set + for _, appliedParam := range parameters { + require.NotEqual(t, presetParam.Name, appliedParam.Name, + "Parameter %s should not be applied to the workspace", presetParam.Name) + } + } + } } } else { require.Nil(t, ws.LatestBuild.TemplateVersionPresetID) diff --git a/coderd/wsbuilder/wsbuilder.go b/coderd/wsbuilder/wsbuilder.go index 469c8fbcfdd6d..fa7c00861202d 100644 --- a/coderd/wsbuilder/wsbuilder.go +++ b/coderd/wsbuilder/wsbuilder.go @@ -61,18 +61,19 @@ type Builder struct { store database.Store // cache of objects, so we only fetch once - template *database.Template - templateVersion *database.TemplateVersion - templateVersionJob *database.ProvisionerJob - templateVersionParameters *[]database.TemplateVersionParameter - templateVersionVariables *[]database.TemplateVersionVariable - templateVersionWorkspaceTags *[]database.TemplateVersionWorkspaceTag - lastBuild *database.WorkspaceBuild - lastBuildErr *error - lastBuildParameters *[]database.WorkspaceBuildParameter - lastBuildJob *database.ProvisionerJob - parameterNames *[]string - parameterValues *[]string + template *database.Template + templateVersion *database.TemplateVersion + templateVersionJob *database.ProvisionerJob + templateVersionParameters *[]database.TemplateVersionParameter + templateVersionVariables *[]database.TemplateVersionVariable + templateVersionWorkspaceTags *[]database.TemplateVersionWorkspaceTag + lastBuild *database.WorkspaceBuild + lastBuildErr *error + lastBuildParameters *[]database.WorkspaceBuildParameter + lastBuildJob *database.ProvisionerJob + parameterNames *[]string + parameterValues *[]string + templateVersionPresetParameterValues []database.TemplateVersionPresetParameter prebuild bool @@ -565,6 +566,14 @@ func (b *Builder) getParameters() (names, values []string, err error) { if err != nil { return nil, nil, BuildError{http.StatusInternalServerError, "failed to fetch last build parameters", err} } + if b.templateVersionPresetID != uuid.Nil { + // Fetch and cache these, since we'll need them to override requested values if a preset was chosen + presetParameters, err := b.store.GetPresetParametersByPresetID(b.ctx, b.templateVersionPresetID) + if err != nil { + return nil, nil, BuildError{http.StatusInternalServerError, "failed to get preset parameters", err} + } + b.templateVersionPresetParameterValues = presetParameters + } err = b.verifyNoLegacyParameters() if err != nil { return nil, nil, BuildError{http.StatusBadRequest, "Unable to build workspace with unsupported parameters", err} @@ -597,6 +606,15 @@ func (b *Builder) getParameters() (names, values []string, err error) { } func (b *Builder) findNewBuildParameterValue(name string) *codersdk.WorkspaceBuildParameter { + for _, v := range b.templateVersionPresetParameterValues { + if v.Name == name { + return &codersdk.WorkspaceBuildParameter{ + Name: v.Name, + Value: v.Value, + } + } + } + for _, v := range b.richParameterValues { if v.Name == name { return &v From 86d93c5a4ea61505c08a1d7eae6a828f103e07fd Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Tue, 15 Apr 2025 14:25:26 +0000 Subject: [PATCH 3/6] update expectations in TestWorkspaceBuildWithPreset --- coderd/wsbuilder/wsbuilder_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/coderd/wsbuilder/wsbuilder_test.go b/coderd/wsbuilder/wsbuilder_test.go index bd6e64a60414a..901d8ffe80273 100644 --- a/coderd/wsbuilder/wsbuilder_test.go +++ b/coderd/wsbuilder/wsbuilder_test.go @@ -789,6 +789,7 @@ func TestWorkspaceBuildWithPreset(t *testing.T) { // Inputs withTemplate, withActiveVersion(nil), + withTemplateVersionPreset(presetID), withLastBuildNotFound, withTemplateVersionVariables(activeVersionID, nil), withParameterSchemas(activeJobID, nil), @@ -960,6 +961,12 @@ func withInactiveVersion(params []database.TemplateVersionParameter) func(mTx *d } } +func withTemplateVersionPreset(presetID uuid.UUID) func(mTx *dbmock.MockStore) { + return func(mTx *dbmock.MockStore) { + mTx.EXPECT().GetPresetParametersByPresetID(gomock.Any(), presetID).Return(nil, nil) + } +} + func withLastBuildFound(mTx *dbmock.MockStore) { mTx.EXPECT().GetLatestWorkspaceBuildByWorkspaceID(gomock.Any(), workspaceID). Times(1). From 24cb22577c7094167c1ccde0e7921df05dd7af1c Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Wed, 16 Apr 2025 10:38:01 +0000 Subject: [PATCH 4/6] simplify tests --- coderd/util/slice/slice.go | 13 ++ coderd/workspaces_test.go | 461 +++++++++++++++---------------------- 2 files changed, 197 insertions(+), 277 deletions(-) diff --git a/coderd/util/slice/slice.go b/coderd/util/slice/slice.go index 508827dfaae81..b4ee79291d73f 100644 --- a/coderd/util/slice/slice.go +++ b/coderd/util/slice/slice.go @@ -66,6 +66,19 @@ func Contains[T comparable](haystack []T, needle T) bool { }) } +func CountMatchingPairs[A, B any](a []A, b []B, match func(A, B) bool) int { + count := 0 + for _, a := range a { + for _, b := range b { + if match(a, b) { + count++ + break + } + } + } + return count +} + // Find returns the first element that satisfies the condition. func Find[T any](haystack []T, cond func(T) bool) (T, bool) { for _, hay := range haystack { diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index cbc2503feed74..8f7ec4ec7ff14 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -36,6 +36,7 @@ import ( "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/schedule/cron" "github.com/coder/coder/v2/coderd/util/ptr" + "github.com/coder/coder/v2/coderd/util/slice" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/cryptorand" "github.com/coder/coder/v2/provisioner/echo" @@ -427,278 +428,226 @@ func TestWorkspace(t *testing.T) { t.Run("TemplateVersionPreset", func(t *testing.T) { t.Parallel() + // Test Utility variables + templateVersionParameters := []*proto.RichParameter{ + {Name: "param1", Type: "string", Required: false}, + {Name: "param2", Type: "string", Required: false}, + {Name: "param3", Type: "string", Required: false}, + } + presetParameters := []*proto.PresetParameter{ + {Name: "param1", Value: "value1"}, + {Name: "param2", Value: "value2"}, + {Name: "param3", Value: "value3"}, + } + emptyPreset := &proto.Preset{ + Name: "Empty Preset", + } + presetWithParameters := &proto.Preset{ + Name: "Preset With Parameters", + Parameters: presetParameters, + } + testCases := []struct { name string presets []*proto.Preset templateVersionParameters []*proto.RichParameter - selectedPresetIndex int // -1 if no preset should be used + selectedPresetIndex *int }{ { - name: "No Presets", + name: "No Presets - No Template Parameters", presets: []*proto.Preset{}, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: -1, + templateVersionParameters: templateVersionParameters, }, { - name: "Single Preset - No Parameters", - presets: []*proto.Preset{{ - Name: "test", - }}, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 0, + name: "No Presets - With Template Parameters", + presets: []*proto.Preset{}, + templateVersionParameters: templateVersionParameters, }, { - name: "Single Preset - With Parameters But No Template Parameters", - presets: []*proto.Preset{{ - Name: "test", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }}, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 0, + name: "Single Preset - No Preset Parameters But With Template Parameters", + presets: []*proto.Preset{emptyPreset}, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(0), }, { - name: "Single Preset - With Matching Parameters", - presets: []*proto.Preset{{ - Name: "test", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }}, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: true}, - {Name: "param2", Type: "string", Required: true}, - }, - selectedPresetIndex: 0, + name: "Single Preset - No Preset Parameters And No Template Parameters", + presets: []*proto.Preset{emptyPreset}, + selectedPresetIndex: ptr.Ref(0), + }, + { + name: "Single Preset - With Preset Parameters But No Template Parameters", + presets: []*proto.Preset{presetWithParameters}, + selectedPresetIndex: ptr.Ref(0), + }, + { + name: "Single Preset - With Matching Parameters", + presets: []*proto.Preset{presetWithParameters}, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(0), }, { name: "Single Preset - With Partial Matching Parameters", presets: []*proto.Preset{{ - Name: "test", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - {Name: "param3", Value: "value3"}, // This parameter doesn't exist in template - }, + Name: "test", + Parameters: presetParameters, }}, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: false}, - {Name: "param2", Type: "string", Required: false}, - }, - selectedPresetIndex: 0, + templateVersionParameters: templateVersionParameters[:2], + selectedPresetIndex: ptr.Ref(0), }, { name: "Multiple Presets - No Parameters", presets: []*proto.Preset{ - {Name: "test1"}, - {Name: "test2"}, - {Name: "test3"}, + {Name: "preset1"}, + {Name: "preset2"}, + {Name: "preset3"}, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 0, + selectedPresetIndex: ptr.Ref(0), }, { name: "Multiple Presets - First Has Parameters", presets: []*proto.Preset{ { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, + Name: "preset1", + Parameters: presetParameters, }, - {Name: "test2"}, - {Name: "test3"}, + {Name: "preset2"}, + {Name: "preset3"}, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 0, + selectedPresetIndex: ptr.Ref(0), }, { name: "Multiple Presets - First Has Matching Parameters", presets: []*proto.Preset{ - { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }, - {Name: "test2"}, - {Name: "test3"}, - }, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: true}, - {Name: "param2", Type: "string", Required: true}, + presetWithParameters, + {Name: "preset2"}, + {Name: "preset3"}, }, - selectedPresetIndex: 0, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(0), }, { name: "Multiple Presets - Middle Has Parameters", presets: []*proto.Preset{ - {Name: "test1"}, - { - Name: "test2", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }, - {Name: "test3"}, + {Name: "preset1"}, + presetWithParameters, + {Name: "preset3"}, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 1, + selectedPresetIndex: ptr.Ref(1), }, { name: "Multiple Presets - Middle Has Matching Parameters", presets: []*proto.Preset{ - {Name: "test1"}, - { - Name: "test2", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }, - {Name: "test3"}, - }, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: true}, - {Name: "param2", Type: "string", Required: true}, + {Name: "preset1"}, + presetWithParameters, + {Name: "preset3"}, }, - selectedPresetIndex: 1, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(1), }, { name: "Multiple Presets - Last Has Parameters", presets: []*proto.Preset{ - {Name: "test1"}, - {Name: "test2"}, - { - Name: "test3", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }, + {Name: "preset1"}, + {Name: "preset2"}, + presetWithParameters, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 2, + selectedPresetIndex: ptr.Ref(2), }, { name: "Multiple Presets - Last Has Matching Parameters", presets: []*proto.Preset{ - {Name: "test1"}, - {Name: "test2"}, - { - Name: "test3", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - {Name: "param2", Value: "value2"}, - }, - }, - }, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: true}, - {Name: "param2", Type: "string", Required: true}, + {Name: "preset1"}, + {Name: "preset2"}, + presetWithParameters, }, - selectedPresetIndex: 2, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(2), }, { name: "Multiple Presets - All Have Parameters", presets: []*proto.Preset{ { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - }, + Name: "preset1", + Parameters: presetParameters[:1], }, { - Name: "test2", - Parameters: []*proto.PresetParameter{ - {Name: "param2", Value: "value2"}, - }, + Name: "preset2", + Parameters: presetParameters[1:2], }, { - Name: "test3", - Parameters: []*proto.PresetParameter{ - {Name: "param3", Value: "value3"}, - }, + Name: "preset3", + Parameters: presetParameters[2:3], }, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: 1, + selectedPresetIndex: ptr.Ref(1), }, { - name: "Multiple Presets - All Have Matching Parameters", + name: "Multiple Presets - All Have Partially Matching Parameters", presets: []*proto.Preset{ { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - }, + Name: "preset1", + Parameters: presetParameters[:1], + }, + { + Name: "preset2", + Parameters: presetParameters[1:2], }, { - Name: "test2", + Name: "preset3", + Parameters: presetParameters[2:3], + }, + }, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(1), + }, + { + name: "Multiple presets - With Overlapping Matching Parameters", + presets: []*proto.Preset{ + { + Name: "preset1", Parameters: []*proto.PresetParameter{ - {Name: "param2", Value: "value2"}, + {Name: "param1", Value: "expectedValue1"}, + {Name: "param2", Value: "expectedValue2"}, }, }, { - Name: "test3", + Name: "preset2", Parameters: []*proto.PresetParameter{ - {Name: "param3", Value: "value3"}, + {Name: "param1", Value: "incorrectValue1"}, + {Name: "param2", Value: "incorrectValue2"}, }, }, }, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: false}, - {Name: "param2", Type: "string", Required: true}, - {Name: "param3", Type: "string", Required: false}, - }, - selectedPresetIndex: 1, + templateVersionParameters: templateVersionParameters, + selectedPresetIndex: ptr.Ref(0), }, { name: "Multiple Presets - With Parameters But Not Used", presets: []*proto.Preset{ { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - }, + Name: "preset1", + Parameters: presetParameters[:1], }, { - Name: "test2", - Parameters: []*proto.PresetParameter{ - {Name: "param2", Value: "value2"}, - }, + Name: "preset2", + Parameters: presetParameters[1:2], }, }, - templateVersionParameters: []*proto.RichParameter{}, - selectedPresetIndex: -1, + templateVersionParameters: templateVersionParameters, }, { name: "Multiple Presets - With Matching Parameters But Not Used", presets: []*proto.Preset{ { - Name: "test1", - Parameters: []*proto.PresetParameter{ - {Name: "param1", Value: "value1"}, - }, + Name: "preset1", + Parameters: presetParameters[:1], }, { - Name: "test2", - Parameters: []*proto.PresetParameter{ - {Name: "param2", Value: "value2"}, - }, + Name: "preset2", + Parameters: presetParameters[1:2], }, }, - templateVersionParameters: []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: false}, - {Name: "param2", Type: "string", Required: false}, - }, - selectedPresetIndex: -1, + templateVersionParameters: templateVersionParameters[0:2], }, } @@ -731,41 +680,32 @@ func TestWorkspace(t *testing.T) { ctx := testutil.Context(t, testutil.WaitLong) - // Check presets - presets, err := client.TemplateVersionPresets(ctx, version.ID) + // Check createdPresets + createdPresets, err := client.TemplateVersionPresets(ctx, version.ID) require.NoError(t, err) - require.Equal(t, len(tc.presets), len(presets)) - - if len(tc.presets) > 0 { - // Verify preset names and parameters - for i, preset := range presets { - require.Equal(t, tc.presets[i].Name, preset.Name) - - // Check if the preset should have parameters - if tc.presets[i].Parameters != nil { - // Verify that the preset has the expected parameters - for _, param := range tc.presets[i].Parameters { - found := false - for _, presetParam := range preset.Parameters { - if param.Name == presetParam.Name { - require.Equal(t, param.Value, presetParam.Value, - "Parameter %s should have value %s", param.Name, param.Value) - found = true - break - } - } - require.True(t, found, "Parameter %s should be present in preset", param.Name) - } - } + require.Equal(t, len(tc.presets), len(createdPresets)) + + for _, createdPreset := range createdPresets { + presetIndex := slices.IndexFunc(tc.presets, func(expectedPreset *proto.Preset) bool { + return expectedPreset.Name == createdPreset.Name + }) + require.NotEqual(t, -1, presetIndex, "Preset %s should be present", createdPreset.Name) + + // Verify that the preset has the expected parameters + for _, expectedPresetParam := range tc.presets[presetIndex].Parameters { + paramFoundAtIndex := slices.IndexFunc(createdPreset.Parameters, func(createdPresetParam codersdk.PresetParameter) bool { + return expectedPresetParam.Name == createdPresetParam.Name && expectedPresetParam.Value == createdPresetParam.Value + }) + require.NotEqual(t, -1, paramFoundAtIndex, "Parameter %s should be present in preset", expectedPresetParam.Name) } } // Create workspace with or without preset var workspace codersdk.Workspace - if tc.selectedPresetIndex >= 0 { + if tc.selectedPresetIndex != nil { // Use the selected preset workspace = coderdtest.CreateWorkspace(t, client, template.ID, func(request *codersdk.CreateWorkspaceRequest) { - request.TemplateVersionPresetID = presets[tc.selectedPresetIndex].ID + request.TemplateVersionPresetID = createdPresets[*tc.selectedPresetIndex].ID }) } else { workspace = coderdtest.CreateWorkspace(t, client, template.ID) @@ -779,86 +719,53 @@ func TestWorkspace(t *testing.T) { require.Equal(t, user.UserID, ws.LatestBuild.InitiatorID) require.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) - // Check preset ID if expected - if tc.selectedPresetIndex >= 0 { - require.NotNil(t, ws.LatestBuild.TemplateVersionPresetID) - require.Equal(t, presets[tc.selectedPresetIndex].ID, *ws.LatestBuild.TemplateVersionPresetID) + // Check that the preset ID is set if expected + require.Equal(t, tc.selectedPresetIndex == nil, ws.LatestBuild.TemplateVersionPresetID == nil) - // If the selected preset has parameters and there are template version parameters, - // verify that only matching parameters were applied - if tc.presets[tc.selectedPresetIndex].Parameters != nil && len(tc.templateVersionParameters) > 0 { - builds, err := client.WorkspaceBuilds(ctx, codersdk.WorkspaceBuildsRequest{ - WorkspaceID: ws.ID, - }) - require.NoError(t, err) - require.Equal(t, 1, len(builds)) - parameters, err := client.WorkspaceBuildParameters(ctx, builds[0].ID) - require.NoError(t, err) - parametersSetByPreset := 0 - for _, param := range parameters { - for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { - if param.Name == presetParam.Name && param.Value == presetParam.Value { - parametersSetByPreset++ - break - } - } - } - - // Track which template parameters were set by the preset - expectedParamCount := 0 - for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { - for _, templateParam := range tc.templateVersionParameters { - if presetParam.Name == templateParam.Name { - expectedParamCount++ - break - } - } - } - - // Verify that only the expected number of parameters were set - require.Equal(t, expectedParamCount, parametersSetByPreset, - "Expected %d parameters to be set, but found %d", expectedParamCount, parametersSetByPreset) - - // Verify each parameter that should have been set - for _, presetParam := range tc.presets[tc.selectedPresetIndex].Parameters { - // Check if this parameter exists in the template version - paramExists := false - for _, templateParam := range tc.templateVersionParameters { - if presetParam.Name == templateParam.Name { - paramExists = true - break - } - } - - if paramExists { - // This parameter should have been set - paramFound := false - for _, appliedParam := range parameters { - if appliedParam.Name == presetParam.Name { - require.Equal(t, presetParam.Value, appliedParam.Value, - "Parameter %s should have value %s", presetParam.Name, presetParam.Value) - paramFound = true - break - } - } - require.True(t, paramFound, "Parameter %s should be applied to the workspace", presetParam.Name) - } else { - // This parameter should NOT have been set - for _, appliedParam := range parameters { - require.NotEqual(t, presetParam.Name, appliedParam.Name, - "Parameter %s should not be applied to the workspace", presetParam.Name) - } - } - } - } - } else { - require.Nil(t, ws.LatestBuild.TemplateVersionPresetID) + if tc.selectedPresetIndex == nil { + // No preset selected, so no further checks are needed + // Pre-preset tests cover this case sufficiently. + return } - // Verify organization - org, err := client.Organization(ctx, ws.OrganizationID) + // If we get here, we expect a preset to be selected. + // So we need to assert that selecting the preset had all the correct consequences. + require.Equal(t, createdPresets[*tc.selectedPresetIndex].ID, *ws.LatestBuild.TemplateVersionPresetID) + + selectedPresetParameters := tc.presets[*tc.selectedPresetIndex].Parameters + + // Get parameters that were applied to the latest workspace build + builds, err := client.WorkspaceBuilds(ctx, codersdk.WorkspaceBuildsRequest{ + WorkspaceID: ws.ID, + }) require.NoError(t, err) - require.Equal(t, ws.OrganizationName, org.Name) + require.Equal(t, 1, len(builds)) + gotWorkspaceBuildParameters, err := client.WorkspaceBuildParameters(ctx, builds[0].ID) + require.NoError(t, err) + + // Count how many parameters were set by the preset + parametersSetByPreset := slice.CountMatchingPairs( + gotWorkspaceBuildParameters, + selectedPresetParameters, + func(gotParameter codersdk.WorkspaceBuildParameter, presetParameter *proto.PresetParameter) bool { + namesMatch := gotParameter.Name == presetParameter.Name + valuesMatch := gotParameter.Value == presetParameter.Value + return namesMatch && valuesMatch + }, + ) + + // Count how many parameters should have been set by the preset + expectedParamCount := slice.CountMatchingPairs( + selectedPresetParameters, + tc.templateVersionParameters, + func(presetParam *proto.PresetParameter, templateParam *proto.RichParameter) bool { + return presetParam.Name == templateParam.Name + }, + ) + + // Verify that only the expected number of parameters were set by the preset + require.Equal(t, expectedParamCount, parametersSetByPreset, + "Expected %d parameters to be set, but found %d", expectedParamCount, parametersSetByPreset) }) } }) From 9bdb8ce6229cc51e4206262596a4dbec098d9044 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Wed, 16 Apr 2025 12:40:10 +0000 Subject: [PATCH 5/6] remove typo in presets test case --- coderd/workspaces_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 8f7ec4ec7ff14..3101346f5b43a 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -454,9 +454,8 @@ func TestWorkspace(t *testing.T) { selectedPresetIndex *int }{ { - name: "No Presets - No Template Parameters", - presets: []*proto.Preset{}, - templateVersionParameters: templateVersionParameters, + name: "No Presets - No Template Parameters", + presets: []*proto.Preset{}, }, { name: "No Presets - With Template Parameters", From a66c533684c6b4e4a5db56211e19a07c4008c081 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Wed, 16 Apr 2025 12:40:40 +0000 Subject: [PATCH 6/6] add the option to specify preset parameters in wsbuilder_test --- coderd/wsbuilder/wsbuilder_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/coderd/wsbuilder/wsbuilder_test.go b/coderd/wsbuilder/wsbuilder_test.go index 901d8ffe80273..00b7b5f0ae08b 100644 --- a/coderd/wsbuilder/wsbuilder_test.go +++ b/coderd/wsbuilder/wsbuilder_test.go @@ -789,7 +789,10 @@ func TestWorkspaceBuildWithPreset(t *testing.T) { // Inputs withTemplate, withActiveVersion(nil), - withTemplateVersionPreset(presetID), + // building workspaces using presets with different combinations of parameters + // is tested at the API layer, in TestWorkspace. Here, it is sufficient to + // test that the preset is used when provided. + withTemplateVersionPresetParameters(presetID, nil), withLastBuildNotFound, withTemplateVersionVariables(activeVersionID, nil), withParameterSchemas(activeJobID, nil), @@ -961,9 +964,9 @@ func withInactiveVersion(params []database.TemplateVersionParameter) func(mTx *d } } -func withTemplateVersionPreset(presetID uuid.UUID) func(mTx *dbmock.MockStore) { +func withTemplateVersionPresetParameters(presetID uuid.UUID, params []database.TemplateVersionPresetParameter) func(mTx *dbmock.MockStore) { return func(mTx *dbmock.MockStore) { - mTx.EXPECT().GetPresetParametersByPresetID(gomock.Any(), presetID).Return(nil, nil) + mTx.EXPECT().GetPresetParametersByPresetID(gomock.Any(), presetID).Return(params, nil) } }