diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 48c68ca9e5601..b3607a1c7a351 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -9517,7 +9517,6 @@ const docTemplate = `{ "type": "string", "enum": [ "example", - "shared-ports", "auto-fill-parameters" ], "x-enum-comments": { @@ -9526,7 +9525,6 @@ const docTemplate = `{ }, "x-enum-varnames": [ "ExperimentExample", - "ExperimentSharedPorts", "ExperimentAutoFillParameters" ] }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 5270c54eae154..e73b54f3c92d0 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -8516,16 +8516,12 @@ }, "codersdk.Experiment": { "type": "string", - "enum": ["example", "shared-ports", "auto-fill-parameters"], + "enum": ["example", "auto-fill-parameters"], "x-enum-comments": { "ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.", "ExperimentExample": "This isn't used for anything." }, - "x-enum-varnames": [ - "ExperimentExample", - "ExperimentSharedPorts", - "ExperimentAutoFillParameters" - ] + "x-enum-varnames": ["ExperimentExample", "ExperimentAutoFillParameters"] }, "codersdk.ExternalAuth": { "type": "object", diff --git a/coderd/coderd.go b/coderd/coderd.go index 7c9d94620a13f..0bd6a5a4ae746 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1055,9 +1055,6 @@ func New(options *Options) *API { r.Put("/autoupdates", api.putWorkspaceAutoupdates) r.Get("/resolve-autostart", api.resolveAutostart) r.Route("/port-share", func(r chi.Router) { - r.Use( - httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentSharedPorts), - ) r.Get("/", api.workspaceAgentPortShares) r.Post("/", api.postWorkspaceAgentPortShare) r.Delete("/", api.deleteWorkspaceAgentPortShare) diff --git a/coderd/prometheusmetrics/prometheusmetrics_test.go b/coderd/prometheusmetrics/prometheusmetrics_test.go index ddb599abef65b..9c4c9fca0b66f 100644 --- a/coderd/prometheusmetrics/prometheusmetrics_test.go +++ b/coderd/prometheusmetrics/prometheusmetrics_test.go @@ -511,23 +511,29 @@ func TestAgentStats(t *testing.T) { func TestExperimentsMetric(t *testing.T) { t.Parallel() + if len(codersdk.ExperimentsAll) == 0 { + t.Skip("No experiments are currently defined; skipping test.") + } + tests := []struct { name string experiments codersdk.Experiments expected map[codersdk.Experiment]float64 }{ { - name: "Enabled experiment is exported in metrics", - experiments: codersdk.Experiments{codersdk.ExperimentSharedPorts}, + name: "Enabled experiment is exported in metrics", + experiments: codersdk.Experiments{ + codersdk.ExperimentsAll[0], + }, expected: map[codersdk.Experiment]float64{ - codersdk.ExperimentSharedPorts: 1, + codersdk.ExperimentsAll[0]: 1, }, }, { name: "Disabled experiment is exported in metrics", experiments: codersdk.Experiments{}, expected: map[codersdk.Experiment]float64{ - codersdk.ExperimentSharedPorts: 0, + codersdk.ExperimentsAll[0]: 0, }, }, { diff --git a/coderd/workspaceagentportshare_test.go b/coderd/workspaceagentportshare_test.go index ae8b9fb96d39d..f767aed933562 100644 --- a/coderd/workspaceagentportshare_test.go +++ b/coderd/workspaceagentportshare_test.go @@ -19,11 +19,7 @@ func TestPostWorkspaceAgentPortShare(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - dep := coderdtest.DeploymentValues(t) - dep.Experiments = append(dep.Experiments, string(codersdk.ExperimentSharedPorts)) - ownerClient, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: dep, - }) + ownerClient, db := coderdtest.NewWithDatabase(t, nil) owner := coderdtest.CreateFirstUser(t, ownerClient) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) @@ -140,11 +136,7 @@ func TestGetWorkspaceAgentPortShares(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - dep := coderdtest.DeploymentValues(t) - dep.Experiments = append(dep.Experiments, string(codersdk.ExperimentSharedPorts)) - ownerClient, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: dep, - }) + ownerClient, db := coderdtest.NewWithDatabase(t, nil) owner := coderdtest.CreateFirstUser(t, ownerClient) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) @@ -180,11 +172,7 @@ func TestDeleteWorkspaceAgentPortShare(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - dep := coderdtest.DeploymentValues(t) - dep.Experiments = append(dep.Experiments, string(codersdk.ExperimentSharedPorts)) - ownerClient, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: dep, - }) + ownerClient, db := coderdtest.NewWithDatabase(t, nil) owner := coderdtest.CreateFirstUser(t, ownerClient) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) diff --git a/coderd/workspaceapps_test.go b/coderd/workspaceapps_test.go index ae4fd7bca4633..308c451e87aca 100644 --- a/coderd/workspaceapps_test.go +++ b/coderd/workspaceapps_test.go @@ -257,7 +257,6 @@ func TestWorkspaceApps(t *testing.T) { deploymentValues.DisablePathApps = serpent.Bool(opts.DisablePathApps) deploymentValues.Dangerous.AllowPathAppSharing = serpent.Bool(opts.DangerousAllowPathAppSharing) deploymentValues.Dangerous.AllowPathAppSiteOwnerAccess = serpent.Bool(opts.DangerousAllowPathAppSiteOwnerAccess) - deploymentValues.Experiments = append(deploymentValues.Experiments, string(codersdk.ExperimentSharedPorts)) if opts.DisableSubdomainApps { opts.AppHost = "" diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 6d6ea2197a574..8b11e2c827e16 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -2192,8 +2192,7 @@ type Experiment string const ( // Add new experiments here! - ExperimentExample Experiment = "example" // This isn't used for anything. - ExperimentSharedPorts Experiment = "shared-ports" + ExperimentExample Experiment = "example" // This isn't used for anything. ExperimentAutoFillParameters Experiment = "auto-fill-parameters" // This should not be taken out of experiments until we have redesigned the feature. ) @@ -2201,9 +2200,7 @@ const ( // users to opt-in to via --experimental='*'. // Experiments that are not ready for consumption by all users should // not be included here and will be essentially hidden. -var ExperimentsAll = Experiments{ - ExperimentSharedPorts, -} +var ExperimentsAll = Experiments{} // Experiments is a list of experiments. // Multiple experiments may be enabled at the same time. diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 90343e1a19a20..040e6adcdd5b8 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2666,7 +2666,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | Value | | ---------------------- | | `example` | -| `shared-ports` | | `auto-fill-parameters` | ## codersdk.ExternalAuth diff --git a/enterprise/coderd/workspaceportshare_test.go b/enterprise/coderd/workspaceportshare_test.go index c5dd07226190c..389f612b26669 100644 --- a/enterprise/coderd/workspaceportshare_test.go +++ b/enterprise/coderd/workspaceportshare_test.go @@ -17,12 +17,9 @@ import ( func TestWorkspacePortShare(t *testing.T) { t.Parallel() - dep := coderdtest.DeploymentValues(t) - dep.Experiments = append(dep.Experiments, string(codersdk.ExperimentSharedPorts)) ownerClient, owner := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ IncludeProvisionerDaemon: true, - DeploymentValues: dep, }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 2fc3b5ea7a35d..5488d5c161ad4 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1898,12 +1898,8 @@ export const Entitlements: Entitlement[] = [ ]; // From codersdk/deployment.go -export type Experiment = "auto-fill-parameters" | "example" | "shared-ports"; -export const Experiments: Experiment[] = [ - "auto-fill-parameters", - "example", - "shared-ports", -]; +export type Experiment = "auto-fill-parameters" | "example"; +export const Experiments: Experiment[] = ["auto-fill-parameters", "example"]; // From codersdk/deployment.go export type FeatureName = diff --git a/site/src/modules/resources/PortForwardButton.tsx b/site/src/modules/resources/PortForwardButton.tsx index 1e4e2c2f59b82..c6f0b6433fc04 100644 --- a/site/src/modules/resources/PortForwardButton.tsx +++ b/site/src/modules/resources/PortForwardButton.tsx @@ -65,7 +65,7 @@ export interface PortForwardButtonProps { export const PortForwardButton: FC = (props) => { const { agent } = props; - const { entitlements, experiments } = useDashboard(); + const { entitlements } = useDashboard(); const paper = useClassName(classNames.paper, []); const portsQuery = useQuery({ @@ -103,7 +103,6 @@ export const PortForwardButton: FC = (props) => { interface PortForwardPopoverViewProps extends PortForwardButtonProps { listeningPorts?: readonly WorkspaceAgentListeningPort[]; - portSharingExperimentEnabled: boolean; portSharingControlsEnabled: boolean; } @@ -135,7 +133,6 @@ export const PortForwardPopoverView: FC = ({ template, username, listeningPorts, - portSharingExperimentEnabled, portSharingControlsEnabled, }) => { const theme = useTheme(); @@ -200,9 +197,9 @@ export const PortForwardPopoverView: FC = ({ filteredSharedPorts.every((sharedPort) => sharedPort.port !== port.port), ); // only disable the form if shared port controls are entitled and the template doesn't allow sharing ports - const canSharePorts = - portSharingExperimentEnabled && - !(portSharingControlsEnabled && template.max_port_share_level === "owner"); + const canSharePorts = !( + portSharingControlsEnabled && template.max_port_share_level === "owner" + ); const canSharePortsPublic = canSharePorts && template.max_port_share_level === "public"; @@ -396,183 +393,179 @@ export const PortForwardPopoverView: FC = ({ })} - {portSharingExperimentEnabled && ( -
- Shared Ports - - {canSharePorts - ? "Ports can be shared with other Coder users or with the public. Changing the protocol may take up to 1 minute to take effect." - : "This workspace template does not allow sharing ports. Contact a template administrator to enable port sharing."} - - {canSharePorts && ( -
- {filteredSharedPorts?.map((share) => { - const url = portForwardURL( - host, - share.port, - agent.name, - workspaceName, - username, - share.protocol, - ); - const label = share.port; - return ( - + Shared Ports + + {canSharePorts + ? "Ports can be shared with other Coder users or with the public. Changing the protocol may take up to 1 minute to take effect." + : "This workspace template does not allow sharing ports. Contact a template administrator to enable port sharing."} + + {canSharePorts && ( +
+ {filteredSharedPorts?.map((share) => { + const url = portForwardURL( + host, + share.port, + agent.name, + workspaceName, + username, + share.protocol, + ); + const label = share.port; + return ( + + - + ) : ( + + )} + {label} + + + + + + + - {share.share_level === "public" ? ( - - ) : ( - - )} - {label} - - - - - - - - - + /> + - ); - })} -
- - - - HTTP - HTTPS - - - Authenticated - {canSharePortsPublic ? ( - Public - ) : ( - disabledPublicMenuItem - )} - - - Share Port - -
-
- )} -
- )} + ); + })} +
+ + + + HTTP + HTTPS + + + Authenticated + {canSharePortsPublic ? ( + Public + ) : ( + disabledPublicMenuItem + )} + + + Share Port + + +
+
+ )} + ); }; diff --git a/site/src/modules/resources/PortForwardPopoverView.stories.tsx b/site/src/modules/resources/PortForwardPopoverView.stories.tsx index 9042c05e07c6c..02ce092192abf 100644 --- a/site/src/modules/resources/PortForwardPopoverView.stories.tsx +++ b/site/src/modules/resources/PortForwardPopoverView.stories.tsx @@ -29,7 +29,6 @@ const meta: Meta = { agent: MockWorkspaceAgent, template: MockTemplate, workspaceID: MockWorkspace.id, - portSharingExperimentEnabled: true, portSharingControlsEnabled: true, }, }; @@ -83,13 +82,6 @@ export const Empty: Story = { }, }; -export const NoPortSharingExperiment: Story = { - args: { - listeningPorts: MockListeningPortsResponse.ports, - portSharingExperimentEnabled: false, - }, -}; - export const AGPLPortSharing: Story = { args: { listeningPorts: MockListeningPortsResponse.ports, diff --git a/site/src/modules/resources/PortForwardPopoverView.test.tsx b/site/src/modules/resources/PortForwardPopoverView.test.tsx index a7f0156dbdad7..58389ba9a903e 100644 --- a/site/src/modules/resources/PortForwardPopoverView.test.tsx +++ b/site/src/modules/resources/PortForwardPopoverView.test.tsx @@ -21,7 +21,6 @@ describe("Port Forward Popover View", () => { template={MockTemplate} workspaceID={MockWorkspace.id} listeningPorts={MockListeningPortsResponse.ports} - portSharingExperimentEnabled portSharingControlsEnabled host="host" username="username" diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx index 98600c08cbcc9..3e6cc138426ca 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx @@ -61,7 +61,6 @@ export interface TemplateSettingsForm { initialTouched?: FormikTouched; accessControlEnabled: boolean; advancedSchedulingEnabled: boolean; - portSharingExperimentEnabled: boolean; portSharingControlsEnabled: boolean; } @@ -74,7 +73,6 @@ export const TemplateSettingsForm: FC = ({ initialTouched, accessControlEnabled, advancedSchedulingEnabled, - portSharingExperimentEnabled, portSharingControlsEnabled, }) => { const validationSchema = getValidationSchema(); @@ -258,45 +256,43 @@ export const TemplateSettingsForm: FC = ({ - {portSharingExperimentEnabled && ( - - - - Owner - Authenticated - Public - - {!portSharingControlsEnabled && ( - - - - Enterprise license required to control max port sharing level. - - - )} - - - )} + > + + + Owner + Authenticated + Public + + {!portSharingControlsEnabled && ( + + + + Enterprise license required to control max port sharing level. + + + )} + + diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx index 15e4c8fb21206..05e61630db9f1 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx @@ -18,11 +18,10 @@ export const TemplateSettingsPage: FC = () => { const { organizationId } = useAuthenticated(); const { template } = useTemplateSettings(); const queryClient = useQueryClient(); - const { entitlements, experiments } = useDashboard(); + const { entitlements } = useDashboard(); const accessControlEnabled = entitlements.features.access_control.enabled; const advancedSchedulingEnabled = entitlements.features.advanced_template_scheduling.enabled; - const sharedPortsExperimentEnabled = experiments.includes("shared-ports"); const sharedPortControlsEnabled = entitlements.features.control_shared_ports.enabled; @@ -73,7 +72,6 @@ export const TemplateSettingsPage: FC = () => { }} accessControlEnabled={accessControlEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled} - sharedPortsExperimentEnabled={sharedPortsExperimentEnabled} sharedPortControlsEnabled={sharedPortControlsEnabled} /> diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx index 01351f686957f..c36e52da79782 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx @@ -14,7 +14,6 @@ export interface TemplateSettingsPageViewProps { >["initialTouched"]; accessControlEnabled: boolean; advancedSchedulingEnabled: boolean; - sharedPortsExperimentEnabled: boolean; sharedPortControlsEnabled: boolean; } @@ -27,7 +26,6 @@ export const TemplateSettingsPageView: FC = ({ initialTouched, accessControlEnabled, advancedSchedulingEnabled, - sharedPortsExperimentEnabled, sharedPortControlsEnabled, }) => { return ( @@ -45,7 +43,6 @@ export const TemplateSettingsPageView: FC = ({ error={submitError} accessControlEnabled={accessControlEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled} - portSharingExperimentEnabled={sharedPortsExperimentEnabled} portSharingControlsEnabled={sharedPortControlsEnabled} />