Skip to content

Commit c73e535

Browse files
committed
feat: enable setting max port share level during template creation
1 parent 40baa5b commit c73e535

File tree

10 files changed

+84
-4
lines changed

10 files changed

+84
-4
lines changed

coderd/apidoc/docs.go

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/portsharing/portsharing.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ func (AGPLPortSharer) AuthorizedLevel(_ database.Template, _ codersdk.WorkspaceA
1919
return nil
2020
}
2121

22-
func (AGPLPortSharer) ValidateTemplateMaxLevel(_ codersdk.WorkspaceAgentPortShareLevel) error {
23-
return xerrors.New("Restricting port sharing level is an enterprise feature that is not enabled.")
22+
func (AGPLPortSharer) ValidateTemplateMaxLevel(level codersdk.WorkspaceAgentPortShareLevel) error {
23+
if level != codersdk.WorkspaceAgentPortShareLevelOwner {
24+
return xerrors.New("Restricting port sharing level is an enterprise feature that is not enabled.")
25+
}
26+
return nil
2427
}
2528

2629
func (AGPLPortSharer) ConvertMaxLevel(_ database.AppSharingLevel) codersdk.WorkspaceAgentPortShareLevel {

coderd/templates.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ func (api *API) notifyTemplateDeleted(ctx context.Context, template database.Tem
163163
func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Request) {
164164
var (
165165
ctx = r.Context()
166+
portSharer = *api.PortSharer.Load()
166167
createTemplate codersdk.CreateTemplateRequest
167168
organization = httpmw.OrganizationParam(r)
168169
apiKey = httpmw.APIKey(r)
@@ -309,6 +310,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
309310
validErrs []codersdk.ValidationError
310311
autostopRequirementDaysOfWeekParsed uint8
311312
autostartRequirementDaysOfWeekParsed uint8
313+
maxPortShareLevel = database.AppSharingLevelOwner // default
312314
)
313315
if defaultTTL < 0 {
314316
validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be a positive integer."})
@@ -329,6 +331,14 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
329331
validErrs = append(validErrs, codersdk.ValidationError{Field: "autostart_requirement.days_of_week", Detail: err.Error()})
330332
}
331333
}
334+
if createTemplate.MaxPortShareLevel != nil {
335+
err = portSharer.ValidateTemplateMaxLevel(*createTemplate.MaxPortShareLevel)
336+
if err != nil {
337+
validErrs = append(validErrs, codersdk.ValidationError{Field: "max_port_share_level", Detail: err.Error()})
338+
} else {
339+
maxPortShareLevel = database.AppSharingLevel(*createTemplate.MaxPortShareLevel)
340+
}
341+
}
332342

333343
if autostopRequirementWeeks < 0 {
334344
validErrs = append(validErrs, codersdk.ValidationError{Field: "autostop_requirement.weeks", Detail: "Must be a positive integer."})
@@ -386,7 +396,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
386396
DisplayName: createTemplate.DisplayName,
387397
Icon: createTemplate.Icon,
388398
AllowUserCancelWorkspaceJobs: allowUserCancelWorkspaceJobs,
389-
MaxPortSharingLevel: database.AppSharingLevelOwner,
399+
MaxPortSharingLevel: maxPortShareLevel,
390400
})
391401
if err != nil {
392402
return xerrors.Errorf("insert template: %s", err)

coderd/templates_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,45 @@ func TestPostTemplateByOrganization(t *testing.T) {
401401
require.EqualValues(t, 1, got.AutostopRequirement.Weeks)
402402
})
403403
})
404+
405+
t.Run("MaxPortShareLevel", func(t *testing.T) {
406+
t.Parallel()
407+
408+
t.Run("OK", func(t *testing.T) {
409+
client := coderdtest.New(t, nil)
410+
user := coderdtest.CreateFirstUser(t, client)
411+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
412+
413+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
414+
defer cancel()
415+
416+
got, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{
417+
Name: "testing",
418+
VersionID: version.ID,
419+
MaxPortShareLevel: ptr.Ref(codersdk.WorkspaceAgentPortShareLevelOwner),
420+
})
421+
require.NoError(t, err)
422+
require.Equal(t, codersdk.WorkspaceAgentPortShareLevelPublic, got.MaxPortShareLevel)
423+
})
424+
425+
t.Run("EnterpriseLevelError", func(t *testing.T) {
426+
client := coderdtest.New(t, nil)
427+
user := coderdtest.CreateFirstUser(t, client)
428+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
429+
430+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
431+
defer cancel()
432+
433+
_, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{
434+
Name: "testing",
435+
VersionID: version.ID,
436+
MaxPortShareLevel: ptr.Ref(codersdk.WorkspaceAgentPortShareLevelPublic),
437+
})
438+
var apiErr *codersdk.Error
439+
require.ErrorAs(t, err, &apiErr)
440+
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
441+
})
442+
})
404443
}
405444

406445
func TestTemplatesByOrganization(t *testing.T) {

codersdk/organizations.go

+5
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ type CreateTemplateRequest struct {
184184
// RequireActiveVersion mandates that workspaces are built with the active
185185
// template version.
186186
RequireActiveVersion bool `json:"require_active_version"`
187+
188+
// MaxPortShareLevel allows optionally specifying the maximum port share level
189+
// for workspaces created from the template. Defaults to "owner', private to the
190+
// owner of the workspace.
191+
MaxPortShareLevel *WorkspaceAgentPortShareLevel `json:"max_port_share_level"`
187192
}
188193

189194
// CreateWorkspaceRequest provides options for creating a new workspace.

docs/reference/api/schemas.md

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/api/templates.md

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enterprise/coderd/templates_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ func TestTemplates(t *testing.T) {
132132
},
133133
}},
134134
})
135-
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
135+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
136+
ctr.MaxPortShareLevel = ptr.Ref(codersdk.WorkspaceAgentPortShareLevelPublic)
137+
})
138+
require.Equal(t, template.MaxPortShareLevel, codersdk.WorkspaceAgentPortShareLevelPublic)
136139
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
137140
ws := coderdtest.CreateWorkspace(t, client, template.ID)
138141
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)

site/src/api/typesGenerated.ts

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)