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:
@@ -3,6 +3,7 @@ package agentapi
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -42,11 +43,12 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
dbApps []database.WorkspaceApp
|
||||
scripts []database.WorkspaceAgentScript
|
||||
metadata []database.WorkspaceAgentMetadatum
|
||||
workspace database.Workspace
|
||||
owner database.User
|
||||
dbApps []database.WorkspaceApp
|
||||
scripts []database.WorkspaceAgentScript
|
||||
metadata []database.WorkspaceAgentMetadatum
|
||||
workspace database.Workspace
|
||||
owner database.User
|
||||
devcontainers []database.WorkspaceAgentDevcontainer
|
||||
)
|
||||
|
||||
var eg errgroup.Group
|
||||
@@ -80,6 +82,13 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||
}
|
||||
return err
|
||||
})
|
||||
eg.Go(func() (err error) {
|
||||
devcontainers, err = a.Database.GetWorkspaceAgentDevcontainersByAgentID(ctx, workspaceAgent.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
err = eg.Wait()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("fetching workspace agent data: %w", err)
|
||||
@@ -125,10 +134,11 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||
DisableDirectConnections: a.DisableDirectConnections,
|
||||
DerpForceWebsockets: a.DerpForceWebSockets,
|
||||
|
||||
DerpMap: tailnet.DERPMapToProto(a.DerpMapFn()),
|
||||
Scripts: dbAgentScriptsToProto(scripts),
|
||||
Apps: apps,
|
||||
Metadata: dbAgentMetadataToProtoDescription(metadata),
|
||||
DerpMap: tailnet.DERPMapToProto(a.DerpMapFn()),
|
||||
Scripts: dbAgentScriptsToProto(scripts),
|
||||
Apps: apps,
|
||||
Metadata: dbAgentMetadataToProtoDescription(metadata),
|
||||
Devcontainers: dbAgentDevcontainersToProto(devcontainers),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -228,3 +238,15 @@ func dbAppToProto(dbApp database.WorkspaceApp, agent database.WorkspaceAgent, ow
|
||||
Hidden: dbApp.Hidden,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func dbAgentDevcontainersToProto(devcontainers []database.WorkspaceAgentDevcontainer) []*agentproto.WorkspaceAgentDevcontainer {
|
||||
ret := make([]*agentproto.WorkspaceAgentDevcontainer, len(devcontainers))
|
||||
for i, dc := range devcontainers {
|
||||
ret[i] = &agentproto.WorkspaceAgentDevcontainer{
|
||||
Id: dc.ID[:],
|
||||
WorkspaceFolder: dc.WorkspaceFolder,
|
||||
ConfigPath: dc.ConfigPath,
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -156,6 +156,19 @@ func TestGetManifest(t *testing.T) {
|
||||
CollectedAt: someTime.Add(time.Hour),
|
||||
},
|
||||
}
|
||||
devcontainers = []database.WorkspaceAgentDevcontainer{
|
||||
{
|
||||
ID: uuid.New(),
|
||||
WorkspaceAgentID: agent.ID,
|
||||
WorkspaceFolder: "/cool/folder",
|
||||
},
|
||||
{
|
||||
ID: uuid.New(),
|
||||
WorkspaceAgentID: agent.ID,
|
||||
WorkspaceFolder: "/another/cool/folder",
|
||||
ConfigPath: "/another/cool/folder/.devcontainer/devcontainer.json",
|
||||
},
|
||||
}
|
||||
derpMapFn = func() *tailcfg.DERPMap {
|
||||
return &tailcfg.DERPMap{
|
||||
Regions: map[int]*tailcfg.DERPRegion{
|
||||
@@ -267,6 +280,17 @@ func TestGetManifest(t *testing.T) {
|
||||
Timeout: durationpb.New(time.Duration(metadata[1].Timeout)),
|
||||
},
|
||||
}
|
||||
protoDevcontainers = []*agentproto.WorkspaceAgentDevcontainer{
|
||||
{
|
||||
Id: devcontainers[0].ID[:],
|
||||
WorkspaceFolder: devcontainers[0].WorkspaceFolder,
|
||||
},
|
||||
{
|
||||
Id: devcontainers[1].ID[:],
|
||||
WorkspaceFolder: devcontainers[1].WorkspaceFolder,
|
||||
ConfigPath: devcontainers[1].ConfigPath,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
@@ -299,6 +323,7 @@ func TestGetManifest(t *testing.T) {
|
||||
WorkspaceAgentID: agent.ID,
|
||||
Keys: nil, // all
|
||||
}).Return(metadata, nil)
|
||||
mDB.EXPECT().GetWorkspaceAgentDevcontainersByAgentID(gomock.Any(), agent.ID).Return(devcontainers, nil)
|
||||
mDB.EXPECT().GetWorkspaceByID(gomock.Any(), workspace.ID).Return(workspace, nil)
|
||||
mDB.EXPECT().GetUserByID(gomock.Any(), workspace.OwnerID).Return(owner, nil)
|
||||
|
||||
@@ -321,10 +346,11 @@ func TestGetManifest(t *testing.T) {
|
||||
// tailnet.DERPMapToProto() is extensively tested elsewhere, so it's
|
||||
// not necessary to manually recreate a big DERP map here like we
|
||||
// did for apps and metadata.
|
||||
DerpMap: tailnet.DERPMapToProto(derpMapFn()),
|
||||
Scripts: protoScripts,
|
||||
Apps: protoApps,
|
||||
Metadata: protoMetadata,
|
||||
DerpMap: tailnet.DERPMapToProto(derpMapFn()),
|
||||
Scripts: protoScripts,
|
||||
Apps: protoApps,
|
||||
Metadata: protoMetadata,
|
||||
Devcontainers: protoDevcontainers,
|
||||
}
|
||||
|
||||
// Log got and expected with spew.
|
||||
@@ -364,6 +390,7 @@ func TestGetManifest(t *testing.T) {
|
||||
WorkspaceAgentID: agent.ID,
|
||||
Keys: nil, // all
|
||||
}).Return(metadata, nil)
|
||||
mDB.EXPECT().GetWorkspaceAgentDevcontainersByAgentID(gomock.Any(), agent.ID).Return(devcontainers, nil)
|
||||
mDB.EXPECT().GetWorkspaceByID(gomock.Any(), workspace.ID).Return(workspace, nil)
|
||||
mDB.EXPECT().GetUserByID(gomock.Any(), workspace.OwnerID).Return(owner, nil)
|
||||
|
||||
@@ -386,10 +413,11 @@ func TestGetManifest(t *testing.T) {
|
||||
// tailnet.DERPMapToProto() is extensively tested elsewhere, so it's
|
||||
// not necessary to manually recreate a big DERP map here like we
|
||||
// did for apps and metadata.
|
||||
DerpMap: tailnet.DERPMapToProto(derpMapFn()),
|
||||
Scripts: protoScripts,
|
||||
Apps: protoApps,
|
||||
Metadata: protoMetadata,
|
||||
DerpMap: tailnet.DERPMapToProto(derpMapFn()),
|
||||
Scripts: protoScripts,
|
||||
Apps: protoApps,
|
||||
Metadata: protoMetadata,
|
||||
Devcontainers: protoDevcontainers,
|
||||
}
|
||||
|
||||
// Log got and expected with spew.
|
||||
|
||||
Reference in New Issue
Block a user