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

Lines changed: 8 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: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/portsharing/portsharing.go

Lines changed: 5 additions & 2 deletions
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

Lines changed: 11 additions & 1 deletion
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

Lines changed: 39 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

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

docs/reference/api/templates.md

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

enterprise/coderd/templates_test.go

Lines changed: 4 additions & 1 deletion
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

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy