Skip to content

Commit 9f2a931

Browse files
authored
feat(coderd): support ephemeral parameters (#8367)
1 parent 8f4157c commit 9f2a931

29 files changed

+626
-345
lines changed

coderd/apidoc/docs.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/db2sdk/db2sdk.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func TemplateVersionParameter(param database.TemplateVersionParameter) (codersdk
7575
ValidationError: param.ValidationError,
7676
ValidationMonotonic: codersdk.ValidationMonotonicOrder(param.ValidationMonotonic),
7777
Required: param.Required,
78+
Ephemeral: param.Ephemeral,
7879
}, nil
7980
}
8081

coderd/database/dbfake/dbfake.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3966,6 +3966,7 @@ func (q *fakeQuerier) InsertTemplateVersionParameter(_ context.Context, arg data
39663966
ValidationMonotonic: arg.ValidationMonotonic,
39673967
Required: arg.Required,
39683968
DisplayOrder: arg.DisplayOrder,
3969+
Ephemeral: arg.Ephemeral,
39693970
}
39703971
q.templateVersionParameters = append(q.templateVersionParameters, param)
39713972
return param, nil

coderd/database/dump.sql

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE template_version_parameters DROP COLUMN ephemeral;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ALTER TABLE template_version_parameters ADD COLUMN ephemeral boolean NOT NULL DEFAULT false;
2+
3+
COMMENT ON COLUMN template_version_parameters.ephemeral
4+
IS 'The value of an ephemeral parameter will not be preserved between consecutive workspace builds.';

coderd/database/models.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 10 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/templateversionparameters.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ INSERT INTO
1616
validation_monotonic,
1717
required,
1818
display_name,
19-
display_order
19+
display_order,
20+
ephemeral
2021
)
2122
VALUES
2223
(
@@ -35,7 +36,8 @@ VALUES
3536
$13,
3637
$14,
3738
$15,
38-
$16
39+
$16,
40+
$17
3941
) RETURNING *;
4042

4143
-- name: GetTemplateVersionParameters :many

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
789789
server.Logger.Info(ctx, "inserting template import job parameter",
790790
slog.F("job_id", job.ID.String()),
791791
slog.F("parameter_name", richParameter.Name),
792+
slog.F("type", richParameter.Type),
793+
slog.F("ephemeral", richParameter.Ephemeral),
792794
)
793795
options, err := json.Marshal(richParameter.Options)
794796
if err != nil {
@@ -826,6 +828,7 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
826828
ValidationMonotonic: richParameter.ValidationMonotonic,
827829
Required: richParameter.Required,
828830
DisplayOrder: richParameter.Order,
831+
Ephemeral: richParameter.Ephemeral,
829832
})
830833
if err != nil {
831834
return nil, xerrors.Errorf("insert parameter: %w", err)

coderd/templateversions.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,7 @@ func convertTemplateVersionParameter(param database.TemplateVersionParameter) (c
14841484
ValidationError: param.ValidationError,
14851485
ValidationMonotonic: codersdk.ValidationMonotonicOrder(param.ValidationMonotonic),
14861486
Required: param.Required,
1487+
Ephemeral: param.Ephemeral,
14871488
}, nil
14881489
}
14891490

coderd/workspaces_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,6 +2518,131 @@ func TestWorkspaceWithOptionalRichParameters(t *testing.T) {
25182518
require.ElementsMatch(t, expectedBuildParameters, workspaceBuildParameters)
25192519
}
25202520

2521+
func TestWorkspaceWithEphemeralRichParameters(t *testing.T) {
2522+
t.Parallel()
2523+
2524+
const (
2525+
firstParameterName = "first_parameter"
2526+
firstParameterType = "string"
2527+
firstParameterDescription = "This is first parameter"
2528+
firstParameterMutable = true
2529+
firstParameterDefaultValue = "1"
2530+
firstParameterValue = "i_am_first_parameter"
2531+
2532+
ephemeralParameterName = "second_parameter"
2533+
ephemeralParameterType = "string"
2534+
ephemeralParameterDescription = "This is second parameter"
2535+
ephemeralParameterDefaultValue = ""
2536+
ephemeralParameterMutable = true
2537+
ephemeralParameterValue = "i_am_ephemeral"
2538+
)
2539+
2540+
// Create template version with ephemeral parameter
2541+
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
2542+
user := coderdtest.CreateFirstUser(t, client)
2543+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
2544+
Parse: echo.ParseComplete,
2545+
ProvisionPlan: []*proto.Provision_Response{
2546+
{
2547+
Type: &proto.Provision_Response_Complete{
2548+
Complete: &proto.Provision_Complete{
2549+
Parameters: []*proto.RichParameter{
2550+
{
2551+
Name: firstParameterName,
2552+
Type: firstParameterType,
2553+
Description: firstParameterDescription,
2554+
DefaultValue: firstParameterDefaultValue,
2555+
Mutable: firstParameterMutable,
2556+
},
2557+
{
2558+
Name: ephemeralParameterName,
2559+
Type: ephemeralParameterType,
2560+
Description: ephemeralParameterDescription,
2561+
DefaultValue: ephemeralParameterDefaultValue,
2562+
Mutable: ephemeralParameterMutable,
2563+
Ephemeral: true,
2564+
},
2565+
},
2566+
},
2567+
},
2568+
},
2569+
},
2570+
ProvisionApply: []*proto.Provision_Response{{
2571+
Type: &proto.Provision_Response_Complete{
2572+
Complete: &proto.Provision_Complete{},
2573+
},
2574+
}},
2575+
})
2576+
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
2577+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
2578+
2579+
// Create workspace with default values
2580+
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
2581+
workspaceBuild := coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
2582+
require.Equal(t, codersdk.WorkspaceStatusRunning, workspaceBuild.Status)
2583+
2584+
// Verify workspace build parameters (default values)
2585+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
2586+
defer cancel()
2587+
2588+
workspaceBuildParameters, err := client.WorkspaceBuildParameters(ctx, workspaceBuild.ID)
2589+
require.NoError(t, err)
2590+
2591+
expectedBuildParameters := []codersdk.WorkspaceBuildParameter{
2592+
{Name: firstParameterName, Value: firstParameterDefaultValue},
2593+
{Name: ephemeralParameterName, Value: ephemeralParameterDefaultValue},
2594+
}
2595+
require.ElementsMatch(t, expectedBuildParameters, workspaceBuildParameters)
2596+
2597+
// Trigger workspace build job with ephemeral parameter
2598+
workspaceBuild, err = client.CreateWorkspaceBuild(ctx, workspaceBuild.WorkspaceID, codersdk.CreateWorkspaceBuildRequest{
2599+
Transition: codersdk.WorkspaceTransitionStart,
2600+
RichParameterValues: []codersdk.WorkspaceBuildParameter{
2601+
{
2602+
Name: ephemeralParameterName,
2603+
Value: ephemeralParameterValue,
2604+
},
2605+
},
2606+
})
2607+
require.NoError(t, err)
2608+
workspaceBuild = coderdtest.AwaitWorkspaceBuildJob(t, client, workspaceBuild.ID)
2609+
require.Equal(t, codersdk.WorkspaceStatusRunning, workspaceBuild.Status)
2610+
2611+
// Verify workspace build parameters (including ephemeral)
2612+
workspaceBuildParameters, err = client.WorkspaceBuildParameters(ctx, workspaceBuild.ID)
2613+
require.NoError(t, err)
2614+
2615+
expectedBuildParameters = []codersdk.WorkspaceBuildParameter{
2616+
{Name: firstParameterName, Value: firstParameterDefaultValue},
2617+
{Name: ephemeralParameterName, Value: ephemeralParameterValue},
2618+
}
2619+
require.ElementsMatch(t, expectedBuildParameters, workspaceBuildParameters)
2620+
2621+
// Trigger workspace build one more time without the ephemeral parameter
2622+
workspaceBuild, err = client.CreateWorkspaceBuild(ctx, workspaceBuild.WorkspaceID, codersdk.CreateWorkspaceBuildRequest{
2623+
Transition: codersdk.WorkspaceTransitionStart,
2624+
RichParameterValues: []codersdk.WorkspaceBuildParameter{
2625+
{
2626+
Name: firstParameterName,
2627+
Value: firstParameterValue,
2628+
},
2629+
},
2630+
})
2631+
require.NoError(t, err)
2632+
workspaceBuild = coderdtest.AwaitWorkspaceBuildJob(t, client, workspaceBuild.ID)
2633+
require.Equal(t, codersdk.WorkspaceStatusRunning, workspaceBuild.Status)
2634+
2635+
// Verify workspace build parameters (ephemeral should be back to default)
2636+
workspaceBuildParameters, err = client.WorkspaceBuildParameters(ctx, workspaceBuild.ID)
2637+
require.NoError(t, err)
2638+
2639+
expectedBuildParameters = []codersdk.WorkspaceBuildParameter{
2640+
{Name: firstParameterName, Value: firstParameterValue},
2641+
{Name: ephemeralParameterName, Value: ephemeralParameterDefaultValue},
2642+
}
2643+
require.ElementsMatch(t, expectedBuildParameters, workspaceBuildParameters)
2644+
}
2645+
25212646
func TestWorkspaceLock(t *testing.T) {
25222647
t.Parallel()
25232648

codersdk/richparameters.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ func (r *ParameterResolver) ValidateResolve(p TemplateVersionParameter, v *Works
148148
}
149149
// First, the provided value
150150
resolvedValue := v
151-
// Second, previous value
152-
if resolvedValue == nil {
151+
// Second, previous value if not ephemeral
152+
if resolvedValue == nil && !p.Ephemeral {
153153
resolvedValue = prevV
154154
}
155155
// Last, default value

0 commit comments

Comments
 (0)