mirror of https://github.com/coder/coder.git
chore: remove resources calls (#4344)
This commit is contained in:
parent
9bc0d06aa0
commit
738a38d71f
|
@ -60,10 +60,11 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
ctx := context.WithValue(ctx, "azure-client", metadataClient)
|
||||
errC <- cmd.ExecuteContext(ctx)
|
||||
}()
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
if assert.NotEmpty(t, resources) && assert.NotEmpty(t, resources[0].Agents) {
|
||||
resources := workspace.LatestBuild.Resources
|
||||
if assert.NotEmpty(t, workspace.LatestBuild.Resources) && assert.NotEmpty(t, resources[0].Agents) {
|
||||
assert.NotEmpty(t, resources[0].Agents[0].Version)
|
||||
}
|
||||
dialer, err := client.DialWorkspaceAgentTailnet(ctx, slog.Logger{}, resources[0].Agents[0].ID)
|
||||
|
@ -120,9 +121,10 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
ctx := context.WithValue(ctx, "aws-client", metadataClient)
|
||||
errC <- cmd.ExecuteContext(ctx)
|
||||
}()
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
resources := workspace.LatestBuild.Resources
|
||||
if assert.NotEmpty(t, resources) && assert.NotEmpty(t, resources[0].Agents) {
|
||||
assert.NotEmpty(t, resources[0].Agents[0].Version)
|
||||
}
|
||||
|
@ -180,9 +182,10 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
ctx := context.WithValue(ctx, "gcp-client", metadata)
|
||||
errC <- cmd.ExecuteContext(ctx)
|
||||
}()
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
resources := workspace.LatestBuild.Resources
|
||||
if assert.NotEmpty(t, resources) && assert.NotEmpty(t, resources[0].Agents) {
|
||||
assert.NotEmpty(t, resources[0].Agents[0].Version)
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ func TestConfigSSH(t *testing.T) {
|
|||
defer func() {
|
||||
_ = agentCloser.Close()
|
||||
}()
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
agentConn, err := client.DialWorkspaceAgentTailnet(context.Background(), slog.Logger{}, resources[0].Agents[0].ID)
|
||||
require.NoError(t, err)
|
||||
defer agentConn.Close()
|
||||
|
|
|
@ -81,7 +81,7 @@ func prepareTestGitSSH(ctx context.Context, t *testing.T) (*codersdk.Client, str
|
|||
errC <- cmd.ExecuteContext(ctx)
|
||||
}()
|
||||
t.Cleanup(func() { require.NoError(t, <-errC) })
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
return agentClient, agentToken, pubkey
|
||||
}
|
||||
|
||||
|
|
|
@ -114,9 +114,9 @@ func TestPortForward(t *testing.T) {
|
|||
// Setup agent once to be shared between test-cases (avoid expensive
|
||||
// non-parallel setup).
|
||||
var (
|
||||
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user = coderdtest.CreateFirstUser(t, client)
|
||||
_, workspace = runAgent(t, client, user.UserID)
|
||||
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user = coderdtest.CreateFirstUser(t, client)
|
||||
workspace = runAgent(t, client, user.UserID)
|
||||
)
|
||||
|
||||
for _, c := range cases { //nolint:paralleltest // the `c := c` confuses the linter
|
||||
|
@ -283,7 +283,7 @@ func TestPortForward(t *testing.T) {
|
|||
// runAgent creates a fake workspace and starts an agent locally for that
|
||||
// workspace. The agent will be cleaned up on test completion.
|
||||
// nolint:unused
|
||||
func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) ([]codersdk.WorkspaceResource, codersdk.Workspace) {
|
||||
func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) codersdk.Workspace {
|
||||
ctx := context.Background()
|
||||
user, err := client.User(ctx, userID.String())
|
||||
require.NoError(t, err, "specified user does not exist")
|
||||
|
@ -336,11 +336,9 @@ func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) ([]coders
|
|||
errC <- cmd.ExecuteContext(agentCtx)
|
||||
}()
|
||||
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
return resources, workspace
|
||||
return workspace
|
||||
}
|
||||
|
||||
// setupTestListener starts accepting connections and echoing a single packet.
|
||||
|
|
|
@ -26,11 +26,7 @@ func show() *cobra.Command {
|
|||
if err != nil {
|
||||
return xerrors.Errorf("get workspace: %w", err)
|
||||
}
|
||||
resources, err := client.WorkspaceResourcesByBuild(cmd.Context(), workspace.LatestBuild.ID)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get workspace resources: %w", err)
|
||||
}
|
||||
return cliui.WorkspaceResources(cmd.OutOrStdout(), resources, cliui.WorkspaceResourcesOptions{
|
||||
return cliui.WorkspaceResources(cmd.OutOrStdout(), workspace.LatestBuild.Resources, cliui.WorkspaceResourcesOptions{
|
||||
WorkspaceName: workspace.Name,
|
||||
ServerVersion: buildInfo.Version,
|
||||
})
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestSpeedtest(t *testing.T) {
|
|||
Logger: slogtest.Make(t, nil).Named("agent"),
|
||||
})
|
||||
defer agentCloser.Close()
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
cmd, root := clitest.New(t, "speedtest", workspace.Name)
|
||||
clitest.SetupConfig(t, client, root)
|
||||
|
|
|
@ -261,10 +261,7 @@ func getWorkspaceAndAgent(ctx context.Context, cmd *cobra.Command, client *coder
|
|||
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("workspace %q is being deleted", workspace.Name)
|
||||
}
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
if err != nil {
|
||||
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("fetch workspace resources: %w", err)
|
||||
}
|
||||
resources := workspace.LatestBuild.Resources
|
||||
|
||||
agents := make([]codersdk.WorkspaceAgent, 0)
|
||||
for _, resource := range resources {
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||
)
|
||||
firstDeadline := workspace.LatestBuild.Deadline.Time
|
||||
|
||||
_ = coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
_ = coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
return client, workspace, func(want bool) {
|
||||
if !want {
|
||||
|
@ -73,7 +73,7 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||
|
||||
client, workspace, assertBumped := setupActivityTest(t)
|
||||
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
conn, err := client.DialWorkspaceAgentTailnet(ctx, slogtest.Make(t, nil), resources[0].Agents[0].ID)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
@ -90,9 +90,9 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||
|
||||
client, workspace, assertBumped := setupActivityTest(t)
|
||||
|
||||
// Benign operations like retrieving resources must not
|
||||
// Benign operations like retrieving workspace must not
|
||||
// bump the deadline.
|
||||
_, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
_, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
assertBumped(false)
|
||||
|
|
|
@ -449,14 +449,6 @@ func New(options *Options) *API {
|
|||
})
|
||||
})
|
||||
})
|
||||
r.Route("/workspaceresources/{workspaceresource}", func(r chi.Router) {
|
||||
r.Use(
|
||||
apiKeyMiddleware,
|
||||
httpmw.ExtractWorkspaceResourceParam(options.Database),
|
||||
httpmw.ExtractWorkspaceParam(options.Database),
|
||||
)
|
||||
r.Get("/", api.workspaceResource)
|
||||
})
|
||||
r.Route("/workspaces", func(r chi.Router) {
|
||||
r.Use(
|
||||
apiKeyMiddleware,
|
||||
|
|
|
@ -100,10 +100,6 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
|
|||
AssertAction: rbac.ActionUpdate,
|
||||
AssertObject: workspaceRBACObj,
|
||||
},
|
||||
"GET:/api/v2/workspaceresources/{workspaceresource}": {
|
||||
AssertAction: rbac.ActionRead,
|
||||
AssertObject: workspaceRBACObj,
|
||||
},
|
||||
"PATCH:/api/v2/workspacebuilds/{workspacebuild}/cancel": {
|
||||
AssertAction: rbac.ActionUpdate,
|
||||
AssertObject: workspaceRBACObj,
|
||||
|
@ -351,7 +347,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
|
|||
AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
file, err := client.Upload(ctx, codersdk.ContentTypeTar, make([]byte, 1024))
|
||||
require.NoError(t, err, "upload file")
|
||||
workspaceResources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
workspace, err = client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err, "workspace resources")
|
||||
templateVersionDryRun, err := client.CreateTemplateVersionDryRun(ctx, version.ID, codersdk.CreateTemplateVersionDryRunRequest{
|
||||
ParameterValues: []codersdk.CreateParameterRequest{},
|
||||
|
@ -372,16 +368,16 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
|
|||
"{workspace}": workspace.ID.String(),
|
||||
"{workspacebuild}": workspace.LatestBuild.ID.String(),
|
||||
"{workspacename}": workspace.Name,
|
||||
"{workspaceagent}": workspaceResources[0].Agents[0].ID.String(),
|
||||
"{workspaceagent}": workspace.LatestBuild.Resources[0].Agents[0].ID.String(),
|
||||
"{buildnumber}": strconv.FormatInt(int64(workspace.LatestBuild.BuildNumber), 10),
|
||||
"{template}": template.ID.String(),
|
||||
"{hash}": file.Hash,
|
||||
"{workspaceresource}": workspaceResources[0].ID.String(),
|
||||
"{workspaceapp}": workspaceResources[0].Agents[0].Apps[0].Name,
|
||||
"{workspaceresource}": workspace.LatestBuild.Resources[0].ID.String(),
|
||||
"{workspaceapp}": workspace.LatestBuild.Resources[0].Agents[0].Apps[0].Name,
|
||||
"{templateversion}": version.ID.String(),
|
||||
"{jobID}": templateVersionDryRun.ID.String(),
|
||||
"{templatename}": template.Name,
|
||||
"{workspace_and_agent}": workspace.Name + "." + workspaceResources[0].Agents[0].Name,
|
||||
"{workspace_and_agent}": workspace.Name + "." + workspace.LatestBuild.Resources[0].Agents[0].Name,
|
||||
// Only checking template scoped params here
|
||||
"parameters/{scope}/{id}": fmt.Sprintf("parameters/%s/%s",
|
||||
string(templateParam.Scope), templateParam.ScopeID.String()),
|
||||
|
@ -397,7 +393,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
|
|||
Admin: admin,
|
||||
Template: template,
|
||||
Version: version,
|
||||
WorkspaceResource: workspaceResources[0],
|
||||
WorkspaceResource: workspace.LatestBuild.Resources[0],
|
||||
File: file,
|
||||
TemplateVersionDryRun: templateVersionDryRun,
|
||||
TemplateParam: templateParam,
|
||||
|
|
|
@ -486,18 +486,22 @@ func AwaitWorkspaceBuildJob(t *testing.T, client *codersdk.Client, build uuid.UU
|
|||
}
|
||||
|
||||
// AwaitWorkspaceAgents waits for all resources with agents to be connected.
|
||||
func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID) []codersdk.WorkspaceResource {
|
||||
func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, workspaceID uuid.UUID) []codersdk.WorkspaceResource {
|
||||
t.Helper()
|
||||
|
||||
t.Logf("waiting for workspace agents (build %s)", build)
|
||||
t.Logf("waiting for workspace agents (workspace %s)", workspaceID)
|
||||
var resources []codersdk.WorkspaceResource
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
resources, err = client.WorkspaceResourcesByBuild(context.Background(), build)
|
||||
workspace, err := client.Workspace(context.Background(), workspaceID)
|
||||
if !assert.NoError(t, err) {
|
||||
return false
|
||||
}
|
||||
for _, resource := range resources {
|
||||
if workspace.LatestBuild.Job.CompletedAt.IsZero() {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, resource := range workspace.LatestBuild.Resources {
|
||||
for _, agent := range resource.Agents {
|
||||
if agent.Status != codersdk.WorkspaceAgentConnected {
|
||||
t.Logf("agent %s not connected yet", agent.Name)
|
||||
|
@ -505,6 +509,8 @@ func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID
|
|||
}
|
||||
}
|
||||
}
|
||||
resources = workspace.LatestBuild.Resources
|
||||
|
||||
return true
|
||||
}, testutil.WaitLong, testutil.IntervalFast)
|
||||
return resources
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestNew(t *testing.T) {
|
|||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false)
|
||||
_, _ = coderdtest.NewAWSInstanceIdentity(t, "an-instance")
|
||||
}
|
||||
|
|
|
@ -610,7 +610,7 @@ func TestTemplateDAUs(t *testing.T) {
|
|||
defer func() {
|
||||
_ = agentCloser.Close()
|
||||
}()
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
|
|
@ -61,10 +61,10 @@ func TestWorkspaceAgent(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tmpDir, resources[0].Agents[0].Directory)
|
||||
_, err = client.WorkspaceAgent(ctx, resources[0].Agents[0].ID)
|
||||
require.Equal(t, tmpDir, workspace.LatestBuild.Resources[0].Agents[0].Directory)
|
||||
_, err = client.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ func TestWorkspaceAgentListen(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
conn, err := client.DialWorkspaceAgentTailnet(ctx, slog.Logger{}, resources[0].Agents[0].ID)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
|
@ -246,7 +246,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) {
|
|||
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),
|
||||
})
|
||||
defer agentCloser.Close()
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
@ -313,8 +313,7 @@ func TestWorkspaceAgentPTY(t *testing.T) {
|
|||
defer func() {
|
||||
_ = agentCloser.Close()
|
||||
}()
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ func setupProxyTest(t *testing.T, workspaceMutators ...func(*codersdk.CreateWork
|
|||
t.Cleanup(func() {
|
||||
_ = agentCloser.Close()
|
||||
})
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
|
||||
// Configure the HTTP client to not follow redirects and to route all
|
||||
// requests regardless of hostname to the coderd test server.
|
||||
|
|
|
@ -393,13 +393,13 @@ func TestWorkspaceBuildResources(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
require.Len(t, resources, 2)
|
||||
require.Equal(t, "some", resources[1].Name)
|
||||
require.Equal(t, "example", resources[1].Type)
|
||||
require.Len(t, resources[1].Agents, 1)
|
||||
require.NotNil(t, workspace.LatestBuild.Resources)
|
||||
require.Len(t, workspace.LatestBuild.Resources, 2)
|
||||
require.Equal(t, "some", workspace.LatestBuild.Resources[0].Name)
|
||||
require.Equal(t, "example", workspace.LatestBuild.Resources[1].Type)
|
||||
require.Len(t, workspace.LatestBuild.Resources[0].Agents, 1)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
package coderd
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/httpmw"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
workspaceBuild := httpmw.WorkspaceBuildParam(r)
|
||||
workspaceResource := httpmw.WorkspaceResourceParam(r)
|
||||
workspace := httpmw.WorkspaceParam(r)
|
||||
if !api.Authorize(r, rbac.ActionRead, workspace) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
|
||||
job, err := api.Database.GetProvisionerJobByID(ctx, workspaceBuild.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching provisioner job.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !job.CompletedAt.Valid {
|
||||
httpapi.Write(ctx, rw, http.StatusPreconditionFailed, codersdk.Response{
|
||||
Message: "Job hasn't completed!",
|
||||
})
|
||||
return
|
||||
}
|
||||
agents, err := api.Database.GetWorkspaceAgentsByResourceIDs(ctx, []uuid.UUID{workspaceResource.ID})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching provisioner job agents.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
agentIDs := make([]uuid.UUID, 0)
|
||||
for _, agent := range agents {
|
||||
agentIDs = append(agentIDs, agent.ID)
|
||||
}
|
||||
apps, err := api.Database.GetWorkspaceAppsByAgentIDs(ctx, agentIDs)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching workspace agent applications.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
apiAgents := make([]codersdk.WorkspaceAgent, 0)
|
||||
for _, agent := range agents {
|
||||
dbApps := make([]database.WorkspaceApp, 0)
|
||||
for _, app := range apps {
|
||||
if app.AgentID == agent.ID {
|
||||
dbApps = append(dbApps, app)
|
||||
}
|
||||
}
|
||||
|
||||
convertedAgent, err := convertWorkspaceAgent(api.DERPMap, api.TailnetCoordinator, agent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error reading workspace agent.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
apiAgents = append(apiAgents, convertedAgent)
|
||||
}
|
||||
sort.Slice(apiAgents, func(i, j int) bool {
|
||||
return apiAgents[i].Name < apiAgents[j].Name
|
||||
})
|
||||
|
||||
metadata, err := api.Database.GetWorkspaceResourceMetadataByResourceID(ctx, workspaceResource.ID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching workspace resource metadata.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, convertWorkspaceResource(workspaceResource, apiAgents, metadata))
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/provisioner/echo"
|
||||
"github.com/coder/coder/provisionersdk/proto"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
|
||||
func TestWorkspaceResource(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "beta",
|
||||
Type: "example",
|
||||
Icon: "/icon/server.svg",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Name: "b",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}, {
|
||||
Id: "another",
|
||||
Name: "a",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}},
|
||||
}, {
|
||||
Name: "alpha",
|
||||
Type: "example",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
// Ensure it's sorted alphabetically!
|
||||
require.Equal(t, "alpha", resources[0].Name)
|
||||
require.Equal(t, "beta", resources[1].Name)
|
||||
resource, err := client.WorkspaceResource(ctx, resources[1].ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resource.Agents, 2)
|
||||
// Ensure agents are sorted alphabetically!
|
||||
require.Equal(t, "a", resource.Agents[0].Name)
|
||||
require.Equal(t, "b", resource.Agents[1].Name)
|
||||
// Ensure Icon is present
|
||||
require.Equal(t, "/icon/server.svg", resources[1].Icon)
|
||||
})
|
||||
|
||||
t.Run("Apps", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
apps := []*proto.App{
|
||||
{
|
||||
Name: "code-server",
|
||||
Command: "some-command",
|
||||
Url: "http://localhost:3000",
|
||||
Icon: "/code.svg",
|
||||
},
|
||||
{
|
||||
Name: "code-server-2",
|
||||
Command: "some-command",
|
||||
Url: "http://localhost:3000",
|
||||
Icon: "/code.svg",
|
||||
Healthcheck: &proto.Healthcheck{
|
||||
Url: "http://localhost:3000",
|
||||
Interval: 5,
|
||||
Threshold: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "some",
|
||||
Type: "example",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Auth: &proto.Agent_Token{},
|
||||
Apps: apps,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
resource, err := client.WorkspaceResource(ctx, resources[0].ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resource.Agents, 1)
|
||||
agent := resource.Agents[0]
|
||||
require.Len(t, agent.Apps, 2)
|
||||
got := agent.Apps[0]
|
||||
app := apps[0]
|
||||
require.EqualValues(t, app.Command, got.Command)
|
||||
require.EqualValues(t, app.Icon, got.Icon)
|
||||
require.EqualValues(t, app.Name, got.Name)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthDisabled, got.Health)
|
||||
require.EqualValues(t, "", got.Healthcheck.URL)
|
||||
require.EqualValues(t, 0, got.Healthcheck.Interval)
|
||||
require.EqualValues(t, 0, got.Healthcheck.Threshold)
|
||||
got = agent.Apps[1]
|
||||
app = apps[1]
|
||||
require.EqualValues(t, app.Command, got.Command)
|
||||
require.EqualValues(t, app.Icon, got.Icon)
|
||||
require.EqualValues(t, app.Name, got.Name)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthInitializing, got.Health)
|
||||
require.EqualValues(t, app.Healthcheck.Url, got.Healthcheck.URL)
|
||||
require.EqualValues(t, app.Healthcheck.Interval, got.Healthcheck.Interval)
|
||||
require.EqualValues(t, app.Healthcheck.Threshold, got.Healthcheck.Threshold)
|
||||
})
|
||||
|
||||
t.Run("Metadata", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "some",
|
||||
Type: "example",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}},
|
||||
Metadata: []*proto.Resource_Metadata{{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
}, {
|
||||
Key: "null",
|
||||
IsNull: true,
|
||||
}, {
|
||||
Key: "empty",
|
||||
}, {
|
||||
Key: "secret",
|
||||
Value: "squirrel",
|
||||
Sensitive: true,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
|
||||
require.NoError(t, err)
|
||||
resource, err := client.WorkspaceResource(ctx, resources[0].ID)
|
||||
require.NoError(t, err)
|
||||
metadata := resource.Metadata
|
||||
require.Equal(t, []codersdk.WorkspaceResourceMetadata{{
|
||||
Key: "empty",
|
||||
}, {
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
}, {
|
||||
Key: "secret",
|
||||
Value: "squirrel",
|
||||
Sensitive: true,
|
||||
}, {
|
||||
Key: "type",
|
||||
Value: "example",
|
||||
}}, metadata)
|
||||
})
|
||||
}
|
|
@ -1265,3 +1265,189 @@ func mustLocation(t *testing.T, location string) *time.Location {
|
|||
|
||||
return loc
|
||||
}
|
||||
|
||||
func TestWorkspaceResource(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "beta",
|
||||
Type: "example",
|
||||
Icon: "/icon/server.svg",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Name: "b",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}, {
|
||||
Id: "another",
|
||||
Name: "a",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}},
|
||||
}, {
|
||||
Name: "alpha",
|
||||
Type: "example",
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspace.LatestBuild.Resources[0].Agents, 2)
|
||||
// Ensure Icon is present
|
||||
require.Equal(t, "/icon/server.svg", workspace.LatestBuild.Resources[0].Icon)
|
||||
})
|
||||
|
||||
t.Run("Apps", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
apps := []*proto.App{
|
||||
{
|
||||
Name: "code-server",
|
||||
Command: "some-command",
|
||||
Url: "http://localhost:3000",
|
||||
Icon: "/code.svg",
|
||||
},
|
||||
{
|
||||
Name: "code-server-2",
|
||||
Command: "some-command",
|
||||
Url: "http://localhost:3000",
|
||||
Icon: "/code.svg",
|
||||
Healthcheck: &proto.Healthcheck{
|
||||
Url: "http://localhost:3000",
|
||||
Interval: 5,
|
||||
Threshold: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "some",
|
||||
Type: "example",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Auth: &proto.Agent_Token{},
|
||||
Apps: apps,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspace.LatestBuild.Resources[0].Agents, 1)
|
||||
agent := workspace.LatestBuild.Resources[0].Agents[0]
|
||||
require.Len(t, agent.Apps, 2)
|
||||
got := agent.Apps[0]
|
||||
app := apps[0]
|
||||
require.EqualValues(t, app.Command, got.Command)
|
||||
require.EqualValues(t, app.Icon, got.Icon)
|
||||
require.EqualValues(t, app.Name, got.Name)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthDisabled, got.Health)
|
||||
require.EqualValues(t, "", got.Healthcheck.URL)
|
||||
require.EqualValues(t, 0, got.Healthcheck.Interval)
|
||||
require.EqualValues(t, 0, got.Healthcheck.Threshold)
|
||||
got = agent.Apps[1]
|
||||
app = apps[1]
|
||||
require.EqualValues(t, app.Command, got.Command)
|
||||
require.EqualValues(t, app.Icon, got.Icon)
|
||||
require.EqualValues(t, app.Name, got.Name)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthInitializing, got.Health)
|
||||
require.EqualValues(t, app.Healthcheck.Url, got.Healthcheck.URL)
|
||||
require.EqualValues(t, app.Healthcheck.Interval, got.Healthcheck.Interval)
|
||||
require.EqualValues(t, app.Healthcheck.Threshold, got.Healthcheck.Threshold)
|
||||
})
|
||||
|
||||
t.Run("Metadata", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
Provision: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "some",
|
||||
Type: "example",
|
||||
Agents: []*proto.Agent{{
|
||||
Id: "something",
|
||||
Auth: &proto.Agent_Token{},
|
||||
}},
|
||||
Metadata: []*proto.Resource_Metadata{{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
}, {
|
||||
Key: "null",
|
||||
IsNull: true,
|
||||
}, {
|
||||
Key: "empty",
|
||||
}, {
|
||||
Key: "secret",
|
||||
Value: "squirrel",
|
||||
Sensitive: true,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
workspace, err := client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
metadata := workspace.LatestBuild.Resources[0].Metadata
|
||||
require.Equal(t, []codersdk.WorkspaceResourceMetadata{{
|
||||
Key: "empty",
|
||||
}, {
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
}, {
|
||||
Key: "secret",
|
||||
Value: "squirrel",
|
||||
Sensitive: true,
|
||||
}, {
|
||||
Key: "type",
|
||||
Value: "example",
|
||||
}}, metadata)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -26,6 +26,61 @@ import (
|
|||
"github.com/coder/retry"
|
||||
)
|
||||
|
||||
type WorkspaceAgentStatus string
|
||||
|
||||
const (
|
||||
WorkspaceAgentConnecting WorkspaceAgentStatus = "connecting"
|
||||
WorkspaceAgentConnected WorkspaceAgentStatus = "connected"
|
||||
WorkspaceAgentDisconnected WorkspaceAgentStatus = "disconnected"
|
||||
)
|
||||
|
||||
type WorkspaceAgent struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
FirstConnectedAt *time.Time `json:"first_connected_at,omitempty"`
|
||||
LastConnectedAt *time.Time `json:"last_connected_at,omitempty"`
|
||||
DisconnectedAt *time.Time `json:"disconnected_at,omitempty"`
|
||||
Status WorkspaceAgentStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
InstanceID string `json:"instance_id,omitempty"`
|
||||
Architecture string `json:"architecture"`
|
||||
EnvironmentVariables map[string]string `json:"environment_variables"`
|
||||
OperatingSystem string `json:"operating_system"`
|
||||
StartupScript string `json:"startup_script,omitempty"`
|
||||
Directory string `json:"directory,omitempty"`
|
||||
Version string `json:"version"`
|
||||
Apps []WorkspaceApp `json:"apps"`
|
||||
// DERPLatency is mapped by region name (e.g. "New York City", "Seattle").
|
||||
DERPLatency map[string]DERPRegion `json:"latency,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentResourceMetadata struct {
|
||||
MemoryTotal uint64 `json:"memory_total"`
|
||||
DiskTotal uint64 `json:"disk_total"`
|
||||
CPUCores uint64 `json:"cpu_cores"`
|
||||
CPUModel string `json:"cpu_model"`
|
||||
CPUMhz float64 `json:"cpu_mhz"`
|
||||
}
|
||||
|
||||
type DERPRegion struct {
|
||||
Preferred bool `json:"preferred"`
|
||||
LatencyMilliseconds float64 `json:"latency_ms"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentInstanceMetadata struct {
|
||||
JailOrchestrator string `json:"jail_orchestrator"`
|
||||
OperatingSystem string `json:"operating_system"`
|
||||
Platform string `json:"platform"`
|
||||
PlatformFamily string `json:"platform_family"`
|
||||
KernelVersion string `json:"kernel_version"`
|
||||
KernelArchitecture string `json:"kernel_architecture"`
|
||||
Cloud string `json:"cloud"`
|
||||
Jail string `json:"jail"`
|
||||
VNC bool `json:"vnc"`
|
||||
}
|
||||
|
||||
// @typescript-ignore GoogleInstanceIdentityToken
|
||||
type GoogleInstanceIdentityToken struct {
|
||||
JSONWebToken string `json:"json_web_token" validate:"required"`
|
||||
|
|
|
@ -70,6 +70,25 @@ type WorkspaceBuild struct {
|
|||
Status WorkspaceStatus `json:"status"`
|
||||
}
|
||||
|
||||
type WorkspaceResource struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
JobID uuid.UUID `json:"job_id"`
|
||||
Transition WorkspaceTransition `json:"workspace_transition"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Hide bool `json:"hide"`
|
||||
Icon string `json:"icon"`
|
||||
Agents []WorkspaceAgent `json:"agents,omitempty"`
|
||||
Metadata []WorkspaceResourceMetadata `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceResourceMetadata struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Sensitive bool `json:"sensitive"`
|
||||
}
|
||||
|
||||
// WorkspaceBuild returns a single workspace build for a workspace.
|
||||
// If history is "", the latest version is returned.
|
||||
func (c *Client) WorkspaceBuild(ctx context.Context, id uuid.UUID) (WorkspaceBuild, error) {
|
||||
|
@ -98,20 +117,6 @@ func (c *Client) CancelWorkspaceBuild(ctx context.Context, id uuid.UUID) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WorkspaceResourcesByBuild returns resources for a workspace build.
|
||||
func (c *Client) WorkspaceResourcesByBuild(ctx context.Context, build uuid.UUID) ([]WorkspaceResource, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspacebuilds/%s/resources", build), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
var resources []WorkspaceResource
|
||||
return resources, json.NewDecoder(res.Body).Decode(&resources)
|
||||
}
|
||||
|
||||
// WorkspaceBuildLogsBefore returns logs that occurred before a specific time.
|
||||
func (c *Client) WorkspaceBuildLogsBefore(ctx context.Context, build uuid.UUID, before time.Time) ([]ProvisionerJobLog, error) {
|
||||
return c.provisionerJobLogsBefore(ctx, fmt.Sprintf("/api/v2/workspacebuilds/%s/logs", build), before)
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
package codersdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type WorkspaceAgentStatus string
|
||||
|
||||
const (
|
||||
WorkspaceAgentConnecting WorkspaceAgentStatus = "connecting"
|
||||
WorkspaceAgentConnected WorkspaceAgentStatus = "connected"
|
||||
WorkspaceAgentDisconnected WorkspaceAgentStatus = "disconnected"
|
||||
)
|
||||
|
||||
type WorkspaceResource struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
JobID uuid.UUID `json:"job_id"`
|
||||
Transition WorkspaceTransition `json:"workspace_transition"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Hide bool `json:"hide"`
|
||||
Icon string `json:"icon"`
|
||||
Agents []WorkspaceAgent `json:"agents,omitempty"`
|
||||
Metadata []WorkspaceResourceMetadata `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceResourceMetadata struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Sensitive bool `json:"sensitive"`
|
||||
}
|
||||
|
||||
type DERPRegion struct {
|
||||
Preferred bool `json:"preferred"`
|
||||
LatencyMilliseconds float64 `json:"latency_ms"`
|
||||
}
|
||||
|
||||
type WorkspaceAgent struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
FirstConnectedAt *time.Time `json:"first_connected_at,omitempty"`
|
||||
LastConnectedAt *time.Time `json:"last_connected_at,omitempty"`
|
||||
DisconnectedAt *time.Time `json:"disconnected_at,omitempty"`
|
||||
Status WorkspaceAgentStatus `json:"status"`
|
||||
Name string `json:"name"`
|
||||
ResourceID uuid.UUID `json:"resource_id"`
|
||||
InstanceID string `json:"instance_id,omitempty"`
|
||||
Architecture string `json:"architecture"`
|
||||
EnvironmentVariables map[string]string `json:"environment_variables"`
|
||||
OperatingSystem string `json:"operating_system"`
|
||||
StartupScript string `json:"startup_script,omitempty"`
|
||||
Directory string `json:"directory,omitempty"`
|
||||
Version string `json:"version"`
|
||||
Apps []WorkspaceApp `json:"apps"`
|
||||
// DERPLatency is mapped by region name (e.g. "New York City", "Seattle").
|
||||
DERPLatency map[string]DERPRegion `json:"latency,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentResourceMetadata struct {
|
||||
MemoryTotal uint64 `json:"memory_total"`
|
||||
DiskTotal uint64 `json:"disk_total"`
|
||||
CPUCores uint64 `json:"cpu_cores"`
|
||||
CPUModel string `json:"cpu_model"`
|
||||
CPUMhz float64 `json:"cpu_mhz"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentInstanceMetadata struct {
|
||||
JailOrchestrator string `json:"jail_orchestrator"`
|
||||
OperatingSystem string `json:"operating_system"`
|
||||
Platform string `json:"platform"`
|
||||
PlatformFamily string `json:"platform_family"`
|
||||
KernelVersion string `json:"kernel_version"`
|
||||
KernelArchitecture string `json:"kernel_architecture"`
|
||||
Cloud string `json:"cloud"`
|
||||
Jail string `json:"jail"`
|
||||
VNC bool `json:"vnc"`
|
||||
}
|
||||
|
||||
func (c *Client) WorkspaceResource(ctx context.Context, id uuid.UUID) (WorkspaceResource, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaceresources/%s", id), nil)
|
||||
if err != nil {
|
||||
return WorkspaceResource{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return WorkspaceResource{}, readBodyAsError(res)
|
||||
}
|
||||
var resource WorkspaceResource
|
||||
return resource, json.NewDecoder(res.Body).Decode(&resource)
|
||||
}
|
|
@ -92,6 +92,6 @@ func setupWorkspaceAgent(t *testing.T, client *codersdk.Client, user codersdk.Cr
|
|||
defer func() {
|
||||
_ = agentCloser.Close()
|
||||
}()
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
|
||||
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
|
||||
return resources[0].Agents[0].ID
|
||||
}
|
||||
|
|
|
@ -264,15 +264,6 @@ export const getWorkspaceByOwnerAndName = async (
|
|||
return response.data
|
||||
}
|
||||
|
||||
export const getWorkspaceResources = async (
|
||||
workspaceBuildID: string,
|
||||
): Promise<TypesGen.WorkspaceResource[]> => {
|
||||
const response = await axios.get<TypesGen.WorkspaceResource[]>(
|
||||
`/api/v2/workspacebuilds/${workspaceBuildID}/resources`,
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
const postWorkspaceBuild =
|
||||
(transition: WorkspaceBuildTransition) =>
|
||||
async (workspaceId: string, template_version_id?: string): Promise<TypesGen.WorkspaceBuild> => {
|
||||
|
|
|
@ -233,7 +233,7 @@ export interface DAUEntry {
|
|||
readonly amount: number
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspaceagents.go
|
||||
export interface DERPRegion {
|
||||
readonly preferred: boolean
|
||||
readonly latency_ms: number
|
||||
|
@ -552,7 +552,7 @@ export interface Workspace {
|
|||
readonly last_used_at: string
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspaceagents.go
|
||||
export interface WorkspaceAgent {
|
||||
readonly id: string
|
||||
readonly created_at: string
|
||||
|
@ -574,7 +574,7 @@ export interface WorkspaceAgent {
|
|||
readonly latency?: Record<string, DERPRegion>
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspaceagents.go
|
||||
export interface WorkspaceAgentInstanceMetadata {
|
||||
readonly jail_orchestrator: string
|
||||
readonly operating_system: string
|
||||
|
@ -587,7 +587,7 @@ export interface WorkspaceAgentInstanceMetadata {
|
|||
readonly vnc: boolean
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspaceagents.go
|
||||
export interface WorkspaceAgentResourceMetadata {
|
||||
readonly memory_total: number
|
||||
readonly disk_total: number
|
||||
|
@ -648,7 +648,7 @@ export interface WorkspaceQuota {
|
|||
readonly user_workspace_limit: number
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspacebuilds.go
|
||||
export interface WorkspaceResource {
|
||||
readonly id: string
|
||||
readonly created_at: string
|
||||
|
@ -662,7 +662,7 @@ export interface WorkspaceResource {
|
|||
readonly metadata?: WorkspaceResourceMetadata[]
|
||||
}
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspacebuilds.go
|
||||
export interface WorkspaceResourceMetadata {
|
||||
readonly key: string
|
||||
readonly value: string
|
||||
|
@ -730,7 +730,7 @@ export type ServerSentEventType = "data" | "error" | "ping"
|
|||
// From codersdk/users.go
|
||||
export type UserStatus = "active" | "suspended"
|
||||
|
||||
// From codersdk/workspaceresources.go
|
||||
// From codersdk/workspaceagents.go
|
||||
export type WorkspaceAgentStatus = "connected" | "connecting" | "disconnected"
|
||||
|
||||
// From codersdk/workspaceapps.go
|
||||
|
|
|
@ -69,21 +69,6 @@ describe("TerminalPage", () => {
|
|||
await expectTerminalText(container, Language.workspaceErrorMessagePrefix)
|
||||
})
|
||||
|
||||
it("shows an error if fetching workspace agent fails", async () => {
|
||||
// Given
|
||||
server.use(
|
||||
rest.get("/api/v2/workspacebuilds/:workspaceId/resources", (req, res, ctx) => {
|
||||
return res(ctx.status(500), ctx.json({ message: "nope" }))
|
||||
}),
|
||||
)
|
||||
|
||||
// When
|
||||
const { container } = renderTerminal()
|
||||
|
||||
// Then
|
||||
await expectTerminalText(container, Language.workspaceAgentErrorMessagePrefix)
|
||||
})
|
||||
|
||||
it("shows an error if the websocket fails", async () => {
|
||||
// Given
|
||||
server.use(
|
||||
|
|
|
@ -189,150 +189,6 @@ export const MockTemplate: TypesGen.Template = {
|
|||
icon: "/icon/code.svg",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAutostartDisabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||
schedule: "",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAutostartEnabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||
// Runs at 9:30am Monday through Friday using Canada/Eastern
|
||||
// (America/Toronto) time
|
||||
schedule: "CRON_TZ=Canada/Eastern 30 9 * * 1-5",
|
||||
}
|
||||
|
||||
export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
|
||||
build_number: 1,
|
||||
created_at: "2022-05-17T17:39:01.382927298Z",
|
||||
id: "1",
|
||||
initiator_id: MockUser.id,
|
||||
initiator_name: MockUser.username,
|
||||
job: MockProvisionerJob,
|
||||
template_version_id: "",
|
||||
transition: "start",
|
||||
updated_at: "2022-05-17T17:39:01.382927298Z",
|
||||
workspace_name: "test-workspace",
|
||||
workspace_owner_id: MockUser.id,
|
||||
workspace_owner_name: MockUser.username,
|
||||
workspace_id: "759f1d46-3174-453d-aa60-980a9c1442f3",
|
||||
deadline: "2022-05-17T23:39:00.00Z",
|
||||
reason: "initiator",
|
||||
resources: [],
|
||||
status: "running",
|
||||
}
|
||||
|
||||
export const MockFailedWorkspaceBuild = (
|
||||
transition: TypesGen.WorkspaceTransition = "start",
|
||||
): TypesGen.WorkspaceBuild => ({
|
||||
build_number: 1,
|
||||
created_at: "2022-05-17T17:39:01.382927298Z",
|
||||
id: "1",
|
||||
initiator_id: MockUser.id,
|
||||
initiator_name: MockUser.username,
|
||||
job: MockFailedProvisionerJob,
|
||||
template_version_id: "",
|
||||
transition: transition,
|
||||
updated_at: "2022-05-17T17:39:01.382927298Z",
|
||||
workspace_name: "test-workspace",
|
||||
workspace_owner_id: MockUser.id,
|
||||
workspace_owner_name: MockUser.username,
|
||||
workspace_id: "759f1d46-3174-453d-aa60-980a9c1442f3",
|
||||
deadline: "2022-05-17T23:39:00.00Z",
|
||||
reason: "initiator",
|
||||
resources: [],
|
||||
status: "running",
|
||||
})
|
||||
|
||||
export const MockWorkspaceBuildStop: TypesGen.WorkspaceBuild = {
|
||||
...MockWorkspaceBuild,
|
||||
id: "2",
|
||||
transition: "stop",
|
||||
}
|
||||
|
||||
export const MockWorkspaceBuildDelete: TypesGen.WorkspaceBuild = {
|
||||
...MockWorkspaceBuild,
|
||||
id: "3",
|
||||
transition: "delete",
|
||||
}
|
||||
|
||||
export const MockBuilds = [MockWorkspaceBuild, MockWorkspaceBuildStop, MockWorkspaceBuildDelete]
|
||||
|
||||
export const MockWorkspace: TypesGen.Workspace = {
|
||||
id: "test-workspace",
|
||||
name: "Test-Workspace",
|
||||
created_at: "",
|
||||
updated_at: "",
|
||||
template_id: MockTemplate.id,
|
||||
template_name: MockTemplate.name,
|
||||
template_icon: MockTemplate.icon,
|
||||
outdated: false,
|
||||
owner_id: MockUser.id,
|
||||
owner_name: MockUser.username,
|
||||
autostart_schedule: MockWorkspaceAutostartEnabled.schedule,
|
||||
ttl_ms: 2 * 60 * 60 * 1000, // 2 hours as milliseconds
|
||||
latest_build: MockWorkspaceBuild,
|
||||
last_used_at: "",
|
||||
}
|
||||
|
||||
export const MockStoppedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: MockWorkspaceBuildStop,
|
||||
}
|
||||
export const MockStoppingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuildStop,
|
||||
job: MockRunningProvisionerJob,
|
||||
},
|
||||
}
|
||||
export const MockStartingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockRunningProvisionerJob,
|
||||
transition: "start",
|
||||
},
|
||||
}
|
||||
export const MockCancelingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuild, job: MockCancelingProvisionerJob },
|
||||
}
|
||||
export const MockCanceledWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuild, job: MockCanceledProvisionerJob },
|
||||
}
|
||||
export const MockFailedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockFailedProvisionerJob,
|
||||
},
|
||||
}
|
||||
export const MockDeletingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuildDelete, job: MockRunningProvisionerJob },
|
||||
}
|
||||
export const MockDeletedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: MockWorkspaceBuildDelete,
|
||||
}
|
||||
|
||||
export const MockOutdatedWorkspace: TypesGen.Workspace = { ...MockFailedWorkspace, outdated: true }
|
||||
|
||||
export const MockQueuedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockPendingProvisionerJob,
|
||||
transition: "start",
|
||||
},
|
||||
}
|
||||
|
||||
// requests the MockWorkspace
|
||||
export const MockWorkspaceRequest: TypesGen.CreateWorkspaceRequest = {
|
||||
name: "test",
|
||||
parameter_values: [],
|
||||
template_id: "test-template",
|
||||
}
|
||||
|
||||
export const MockWorkspaceApp: TypesGen.WorkspaceApp = {
|
||||
id: "test-app",
|
||||
name: "test-app",
|
||||
|
@ -454,6 +310,150 @@ export const MockWorkspaceResource3: TypesGen.WorkspaceResource = {
|
|||
],
|
||||
}
|
||||
|
||||
export const MockWorkspaceAutostartDisabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||
schedule: "",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAutostartEnabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||
// Runs at 9:30am Monday through Friday using Canada/Eastern
|
||||
// (America/Toronto) time
|
||||
schedule: "CRON_TZ=Canada/Eastern 30 9 * * 1-5",
|
||||
}
|
||||
|
||||
export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
|
||||
build_number: 1,
|
||||
created_at: "2022-05-17T17:39:01.382927298Z",
|
||||
id: "1",
|
||||
initiator_id: MockUser.id,
|
||||
initiator_name: MockUser.username,
|
||||
job: MockProvisionerJob,
|
||||
template_version_id: "",
|
||||
transition: "start",
|
||||
updated_at: "2022-05-17T17:39:01.382927298Z",
|
||||
workspace_name: "test-workspace",
|
||||
workspace_owner_id: MockUser.id,
|
||||
workspace_owner_name: MockUser.username,
|
||||
workspace_id: "759f1d46-3174-453d-aa60-980a9c1442f3",
|
||||
deadline: "2022-05-17T23:39:00.00Z",
|
||||
reason: "initiator",
|
||||
resources: [MockWorkspaceResource],
|
||||
status: "running",
|
||||
}
|
||||
|
||||
export const MockFailedWorkspaceBuild = (
|
||||
transition: TypesGen.WorkspaceTransition = "start",
|
||||
): TypesGen.WorkspaceBuild => ({
|
||||
build_number: 1,
|
||||
created_at: "2022-05-17T17:39:01.382927298Z",
|
||||
id: "1",
|
||||
initiator_id: MockUser.id,
|
||||
initiator_name: MockUser.username,
|
||||
job: MockFailedProvisionerJob,
|
||||
template_version_id: "",
|
||||
transition: transition,
|
||||
updated_at: "2022-05-17T17:39:01.382927298Z",
|
||||
workspace_name: "test-workspace",
|
||||
workspace_owner_id: MockUser.id,
|
||||
workspace_owner_name: MockUser.username,
|
||||
workspace_id: "759f1d46-3174-453d-aa60-980a9c1442f3",
|
||||
deadline: "2022-05-17T23:39:00.00Z",
|
||||
reason: "initiator",
|
||||
resources: [],
|
||||
status: "running",
|
||||
})
|
||||
|
||||
export const MockWorkspaceBuildStop: TypesGen.WorkspaceBuild = {
|
||||
...MockWorkspaceBuild,
|
||||
id: "2",
|
||||
transition: "stop",
|
||||
}
|
||||
|
||||
export const MockWorkspaceBuildDelete: TypesGen.WorkspaceBuild = {
|
||||
...MockWorkspaceBuild,
|
||||
id: "3",
|
||||
transition: "delete",
|
||||
}
|
||||
|
||||
export const MockBuilds = [MockWorkspaceBuild, MockWorkspaceBuildStop, MockWorkspaceBuildDelete]
|
||||
|
||||
export const MockWorkspace: TypesGen.Workspace = {
|
||||
id: "test-workspace",
|
||||
name: "Test-Workspace",
|
||||
created_at: "",
|
||||
updated_at: "",
|
||||
template_id: MockTemplate.id,
|
||||
template_name: MockTemplate.name,
|
||||
template_icon: MockTemplate.icon,
|
||||
outdated: false,
|
||||
owner_id: MockUser.id,
|
||||
owner_name: MockUser.username,
|
||||
autostart_schedule: MockWorkspaceAutostartEnabled.schedule,
|
||||
ttl_ms: 2 * 60 * 60 * 1000, // 2 hours as milliseconds
|
||||
latest_build: MockWorkspaceBuild,
|
||||
last_used_at: "",
|
||||
}
|
||||
|
||||
export const MockStoppedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: MockWorkspaceBuildStop,
|
||||
}
|
||||
export const MockStoppingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuildStop,
|
||||
job: MockRunningProvisionerJob,
|
||||
},
|
||||
}
|
||||
export const MockStartingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockRunningProvisionerJob,
|
||||
transition: "start",
|
||||
},
|
||||
}
|
||||
export const MockCancelingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuild, job: MockCancelingProvisionerJob },
|
||||
}
|
||||
export const MockCanceledWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuild, job: MockCanceledProvisionerJob },
|
||||
}
|
||||
export const MockFailedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockFailedProvisionerJob,
|
||||
},
|
||||
}
|
||||
export const MockDeletingWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: { ...MockWorkspaceBuildDelete, job: MockRunningProvisionerJob },
|
||||
}
|
||||
export const MockDeletedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: MockWorkspaceBuildDelete,
|
||||
}
|
||||
|
||||
export const MockOutdatedWorkspace: TypesGen.Workspace = { ...MockFailedWorkspace, outdated: true }
|
||||
|
||||
export const MockQueuedWorkspace: TypesGen.Workspace = {
|
||||
...MockWorkspace,
|
||||
latest_build: {
|
||||
...MockWorkspaceBuild,
|
||||
job: MockPendingProvisionerJob,
|
||||
transition: "start",
|
||||
},
|
||||
}
|
||||
|
||||
// requests the MockWorkspace
|
||||
export const MockWorkspaceRequest: TypesGen.CreateWorkspaceRequest = {
|
||||
name: "test",
|
||||
parameter_values: [],
|
||||
template_id: "test-template",
|
||||
}
|
||||
|
||||
export const MockUserAgent: Types.UserAgent = {
|
||||
browser: "Chrome 99.0.4844",
|
||||
device: "Other",
|
||||
|
|
|
@ -148,9 +148,7 @@ export const terminalMachine =
|
|||
throw new Error("workspace or workspace name is not set")
|
||||
}
|
||||
|
||||
const resources = await API.getWorkspaceResources(context.workspace.latest_build.id)
|
||||
|
||||
const agent = resources
|
||||
const agent = context.workspace.latest_build.resources
|
||||
.map((resource) => {
|
||||
if (!resource.agents || resource.agents.length === 0) {
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue