mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add port-sharing backend (#11939)
This commit is contained in:
@@ -52,6 +52,7 @@ const (
|
||||
FeatureWorkspaceBatchActions FeatureName = "workspace_batch_actions"
|
||||
FeatureAccessControl FeatureName = "access_control"
|
||||
FeatureOAuth2Provider FeatureName = "oauth2_provider"
|
||||
FeatureControlSharedPorts FeatureName = "control_shared_ports"
|
||||
)
|
||||
|
||||
// FeatureNames must be kept in-sync with the Feature enum above.
|
||||
@@ -72,6 +73,7 @@ var FeatureNames = []FeatureName{
|
||||
FeatureWorkspaceBatchActions,
|
||||
FeatureAccessControl,
|
||||
FeatureOAuth2Provider,
|
||||
FeatureControlSharedPorts,
|
||||
}
|
||||
|
||||
// Humanize returns the feature name in a human-readable format.
|
||||
@@ -2115,14 +2117,17 @@ type Experiment string
|
||||
|
||||
const (
|
||||
// Add new experiments here!
|
||||
ExperimentExample Experiment = "example" // This isn't used for anything.
|
||||
ExperimentExample Experiment = "example" // This isn't used for anything.
|
||||
ExperimentSharedPorts Experiment = "shared-ports"
|
||||
)
|
||||
|
||||
// ExperimentsAll should include all experiments that are safe for
|
||||
// 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{}
|
||||
var ExperimentsAll = Experiments{
|
||||
ExperimentSharedPorts,
|
||||
}
|
||||
|
||||
// Experiments is a list of experiments.
|
||||
// Multiple experiments may be enabled at the same time.
|
||||
|
||||
@@ -61,7 +61,8 @@ type Template struct {
|
||||
|
||||
// RequireActiveVersion mandates that workspaces are built with the active
|
||||
// template version.
|
||||
RequireActiveVersion bool `json:"require_active_version"`
|
||||
RequireActiveVersion bool `json:"require_active_version"`
|
||||
MaxPortShareLevel WorkspaceAgentPortShareLevel `json:"max_port_share_level"`
|
||||
}
|
||||
|
||||
// WeekdaysToBitmap converts a list of weekdays to a bitmap in accordance with
|
||||
@@ -251,7 +252,8 @@ type UpdateTemplateMeta struct {
|
||||
// If this is set to true, the template will not be available to all users,
|
||||
// and must be explicitly granted to users or groups in the permissions settings
|
||||
// of the template.
|
||||
DisableEveryoneGroupAccess bool `json:"disable_everyone_group_access"`
|
||||
DisableEveryoneGroupAccess bool `json:"disable_everyone_group_access"`
|
||||
MaxPortShareLevel *WorkspaceAgentPortShareLevel `json:"max_port_share_level"`
|
||||
}
|
||||
|
||||
type TemplateExample struct {
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package codersdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceAgentPortShareLevelOwner WorkspaceAgentPortShareLevel = "owner"
|
||||
WorkspaceAgentPortShareLevelAuthenticated WorkspaceAgentPortShareLevel = "authenticated"
|
||||
WorkspaceAgentPortShareLevelPublic WorkspaceAgentPortShareLevel = "public"
|
||||
)
|
||||
|
||||
type (
|
||||
WorkspaceAgentPortShareLevel string
|
||||
UpsertWorkspaceAgentPortShareRequest struct {
|
||||
AgentName string `json:"agent_name"`
|
||||
Port int32 `json:"port"`
|
||||
ShareLevel WorkspaceAgentPortShareLevel `json:"share_level"`
|
||||
}
|
||||
WorkspaceAgentPortShares struct {
|
||||
Shares []WorkspaceAgentPortShare `json:"shares"`
|
||||
}
|
||||
WorkspaceAgentPortShare struct {
|
||||
WorkspaceID uuid.UUID `json:"workspace_id" format:"uuid"`
|
||||
AgentName string `json:"agent_name"`
|
||||
Port int32 `json:"port"`
|
||||
ShareLevel WorkspaceAgentPortShareLevel `json:"share_level"`
|
||||
}
|
||||
DeleteWorkspaceAgentPortShareRequest struct {
|
||||
AgentName string `json:"agent_name"`
|
||||
Port int32 `json:"port"`
|
||||
}
|
||||
)
|
||||
|
||||
func (l WorkspaceAgentPortShareLevel) ValidMaxLevel() bool {
|
||||
return l == WorkspaceAgentPortShareLevelOwner ||
|
||||
l == WorkspaceAgentPortShareLevelAuthenticated ||
|
||||
l == WorkspaceAgentPortShareLevelPublic
|
||||
}
|
||||
|
||||
func (l WorkspaceAgentPortShareLevel) ValidPortShareLevel() bool {
|
||||
return l == WorkspaceAgentPortShareLevelAuthenticated ||
|
||||
l == WorkspaceAgentPortShareLevelPublic
|
||||
}
|
||||
|
||||
func (c *Client) GetWorkspaceAgentPortShares(ctx context.Context, workspaceID uuid.UUID) (WorkspaceAgentPortShares, error) {
|
||||
var shares WorkspaceAgentPortShares
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/port-share", workspaceID), nil)
|
||||
if err != nil {
|
||||
return shares, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return shares, ReadBodyAsError(res)
|
||||
}
|
||||
|
||||
return shares, json.NewDecoder(res.Body).Decode(&shares)
|
||||
}
|
||||
|
||||
func (c *Client) UpsertWorkspaceAgentPortShare(ctx context.Context, workspaceID uuid.UUID, req UpsertWorkspaceAgentPortShareRequest) (WorkspaceAgentPortShare, error) {
|
||||
var share WorkspaceAgentPortShare
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/workspaces/%s/port-share", workspaceID), req)
|
||||
if err != nil {
|
||||
return share, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return share, ReadBodyAsError(res)
|
||||
}
|
||||
|
||||
return share, json.NewDecoder(res.Body).Decode(&share)
|
||||
}
|
||||
|
||||
func (c *Client) DeleteWorkspaceAgentPortShare(ctx context.Context, workspaceID uuid.UUID, req DeleteWorkspaceAgentPortShareRequest) error {
|
||||
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/workspaces/%s/port-share", workspaceID), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return ReadBodyAsError(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user