mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: allow specifying devcontainer on agent in terraform (#16997)
This change allows specifying devcontainers in terraform and plumbs it through to the agent via agent manifest. This will be used for autostarting devcontainers in a workspace. Depends on coder/terraform-provider-coder#368 Updates #16423
This commit is contained in:
@@ -121,6 +121,7 @@ type Manifest struct {
|
||||
DisableDirectConnections bool `json:"disable_direct_connections"`
|
||||
Metadata []codersdk.WorkspaceAgentMetadataDescription `json:"metadata"`
|
||||
Scripts []codersdk.WorkspaceAgentScript `json:"scripts"`
|
||||
Devcontainers []codersdk.WorkspaceAgentDevcontainer `json:"devcontainers"`
|
||||
}
|
||||
|
||||
type LogSource struct {
|
||||
|
||||
@@ -31,6 +31,10 @@ func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) {
|
||||
if err != nil {
|
||||
return Manifest{}, xerrors.Errorf("error converting workspace ID: %w", err)
|
||||
}
|
||||
devcontainers, err := DevcontainersFromProto(manifest.Devcontainers)
|
||||
if err != nil {
|
||||
return Manifest{}, xerrors.Errorf("error converting workspace agent devcontainers: %w", err)
|
||||
}
|
||||
return Manifest{
|
||||
AgentID: agentID,
|
||||
AgentName: manifest.AgentName,
|
||||
@@ -48,6 +52,7 @@ func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) {
|
||||
MOTDFile: manifest.MotdPath,
|
||||
DisableDirectConnections: manifest.DisableDirectConnections,
|
||||
Metadata: MetadataDescriptionsFromProto(manifest.Metadata),
|
||||
Devcontainers: devcontainers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -73,6 +78,7 @@ func ProtoFromManifest(manifest Manifest) (*proto.Manifest, error) {
|
||||
Scripts: ProtoFromScripts(manifest.Scripts),
|
||||
Apps: apps,
|
||||
Metadata: ProtoFromMetadataDescriptions(manifest.Metadata),
|
||||
Devcontainers: ProtoFromDevcontainers(manifest.Devcontainers),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -424,3 +430,43 @@ func ProtoFromConnectionType(typ ConnectionType) (proto.Connection_Type, error)
|
||||
return 0, xerrors.Errorf("unknown connection type %q", typ)
|
||||
}
|
||||
}
|
||||
|
||||
func DevcontainersFromProto(pdcs []*proto.WorkspaceAgentDevcontainer) ([]codersdk.WorkspaceAgentDevcontainer, error) {
|
||||
ret := make([]codersdk.WorkspaceAgentDevcontainer, len(pdcs))
|
||||
for i, pdc := range pdcs {
|
||||
dc, err := DevcontainerFromProto(pdc)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parse devcontainer %v: %w", i, err)
|
||||
}
|
||||
ret[i] = dc
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func DevcontainerFromProto(pdc *proto.WorkspaceAgentDevcontainer) (codersdk.WorkspaceAgentDevcontainer, error) {
|
||||
id, err := uuid.FromBytes(pdc.Id)
|
||||
if err != nil {
|
||||
return codersdk.WorkspaceAgentDevcontainer{}, xerrors.Errorf("parse id: %w", err)
|
||||
}
|
||||
return codersdk.WorkspaceAgentDevcontainer{
|
||||
ID: id,
|
||||
WorkspaceFolder: pdc.WorkspaceFolder,
|
||||
ConfigPath: pdc.ConfigPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ProtoFromDevcontainers(dcs []codersdk.WorkspaceAgentDevcontainer) []*proto.WorkspaceAgentDevcontainer {
|
||||
ret := make([]*proto.WorkspaceAgentDevcontainer, len(dcs))
|
||||
for i, dc := range dcs {
|
||||
ret[i] = ProtoFromDevcontainer(dc)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func ProtoFromDevcontainer(dc codersdk.WorkspaceAgentDevcontainer) *proto.WorkspaceAgentDevcontainer {
|
||||
return &proto.WorkspaceAgentDevcontainer{
|
||||
Id: dc.ID[:],
|
||||
WorkspaceFolder: dc.WorkspaceFolder,
|
||||
ConfigPath: dc.ConfigPath,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,13 @@ func TestManifest(t *testing.T) {
|
||||
DisplayName: "bar",
|
||||
},
|
||||
},
|
||||
Devcontainers: []codersdk.WorkspaceAgentDevcontainer{
|
||||
{
|
||||
ID: uuid.New(),
|
||||
WorkspaceFolder: "/home/coder/coder",
|
||||
ConfigPath: "/home/coder/coder/.devcontainer/devcontainer.json",
|
||||
},
|
||||
},
|
||||
}
|
||||
p, err := agentsdk.ProtoFromManifest(manifest)
|
||||
require.NoError(t, err)
|
||||
@@ -152,6 +159,7 @@ func TestManifest(t *testing.T) {
|
||||
require.Equal(t, manifest.DisableDirectConnections, back.DisableDirectConnections)
|
||||
require.Equal(t, manifest.Metadata, back.Metadata)
|
||||
require.Equal(t, manifest.Scripts, back.Scripts)
|
||||
require.Equal(t, manifest.Devcontainers, back.Devcontainers)
|
||||
}
|
||||
|
||||
func TestSubsystems(t *testing.T) {
|
||||
|
||||
@@ -35,6 +35,7 @@ const (
|
||||
ResourceTemplate RBACResource = "template"
|
||||
ResourceUser RBACResource = "user"
|
||||
ResourceWorkspace RBACResource = "workspace"
|
||||
ResourceWorkspaceAgentDevcontainers RBACResource = "workspace_agent_devcontainers"
|
||||
ResourceWorkspaceAgentResourceMonitor RBACResource = "workspace_agent_resource_monitor"
|
||||
ResourceWorkspaceDormant RBACResource = "workspace_dormant"
|
||||
ResourceWorkspaceProxy RBACResource = "workspace_proxy"
|
||||
@@ -93,6 +94,7 @@ var RBACResourceActions = map[RBACResource][]RBACAction{
|
||||
ResourceTemplate: {ActionCreate, ActionDelete, ActionRead, ActionUpdate, ActionUse, ActionViewInsights},
|
||||
ResourceUser: {ActionCreate, ActionDelete, ActionRead, ActionReadPersonal, ActionUpdate, ActionUpdatePersonal},
|
||||
ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate},
|
||||
ResourceWorkspaceAgentDevcontainers: {ActionCreate},
|
||||
ResourceWorkspaceAgentResourceMonitor: {ActionCreate, ActionRead, ActionUpdate},
|
||||
ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate},
|
||||
ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
|
||||
@@ -392,6 +392,14 @@ func (c *Client) WorkspaceAgentListeningPorts(ctx context.Context, agentID uuid.
|
||||
return listeningPorts, json.NewDecoder(res.Body).Decode(&listeningPorts)
|
||||
}
|
||||
|
||||
// WorkspaceAgentDevcontainer defines the location of a devcontainer
|
||||
// configuration in a workspace that is visible to the workspace agent.
|
||||
type WorkspaceAgentDevcontainer struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
WorkspaceFolder string `json:"workspace_folder"`
|
||||
ConfigPath string `json:"config_path,omitempty"`
|
||||
}
|
||||
|
||||
// WorkspaceAgentContainer describes a devcontainer of some sort
|
||||
// that is visible to the workspace agent. This struct is an abstraction
|
||||
// of potentially multiple implementations, and the fields will be
|
||||
|
||||
Reference in New Issue
Block a user