mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add agent metadata (#6614)
This commit is contained in:
+163
-11
@@ -831,10 +831,10 @@ func TestWorkspaceAgentAppHealth(t *testing.T) {
|
||||
agentClient := agentsdk.New(client.URL)
|
||||
agentClient.SetSessionToken(authToken)
|
||||
|
||||
metadata, err := agentClient.Metadata(ctx)
|
||||
manifest, err := agentClient.Manifest(ctx)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthDisabled, metadata.Apps[0].Health)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthInitializing, metadata.Apps[1].Health)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthDisabled, manifest.Apps[0].Health)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthInitializing, manifest.Apps[1].Health)
|
||||
err = agentClient.PostAppHealth(ctx, agentsdk.PostAppHealthsRequest{})
|
||||
require.Error(t, err)
|
||||
// empty
|
||||
@@ -843,37 +843,37 @@ func TestWorkspaceAgentAppHealth(t *testing.T) {
|
||||
// healthcheck disabled
|
||||
err = agentClient.PostAppHealth(ctx, agentsdk.PostAppHealthsRequest{
|
||||
Healths: map[uuid.UUID]codersdk.WorkspaceAppHealth{
|
||||
metadata.Apps[0].ID: codersdk.WorkspaceAppHealthInitializing,
|
||||
manifest.Apps[0].ID: codersdk.WorkspaceAppHealthInitializing,
|
||||
},
|
||||
})
|
||||
require.Error(t, err)
|
||||
// invalid value
|
||||
err = agentClient.PostAppHealth(ctx, agentsdk.PostAppHealthsRequest{
|
||||
Healths: map[uuid.UUID]codersdk.WorkspaceAppHealth{
|
||||
metadata.Apps[1].ID: codersdk.WorkspaceAppHealth("bad-value"),
|
||||
manifest.Apps[1].ID: codersdk.WorkspaceAppHealth("bad-value"),
|
||||
},
|
||||
})
|
||||
require.Error(t, err)
|
||||
// update to healthy
|
||||
err = agentClient.PostAppHealth(ctx, agentsdk.PostAppHealthsRequest{
|
||||
Healths: map[uuid.UUID]codersdk.WorkspaceAppHealth{
|
||||
metadata.Apps[1].ID: codersdk.WorkspaceAppHealthHealthy,
|
||||
manifest.Apps[1].ID: codersdk.WorkspaceAppHealthHealthy,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
metadata, err = agentClient.Metadata(ctx)
|
||||
manifest, err = agentClient.Manifest(ctx)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthHealthy, metadata.Apps[1].Health)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthHealthy, manifest.Apps[1].Health)
|
||||
// update to unhealthy
|
||||
err = agentClient.PostAppHealth(ctx, agentsdk.PostAppHealthsRequest{
|
||||
Healths: map[uuid.UUID]codersdk.WorkspaceAppHealth{
|
||||
metadata.Apps[1].ID: codersdk.WorkspaceAppHealthUnhealthy,
|
||||
manifest.Apps[1].ID: codersdk.WorkspaceAppHealthUnhealthy,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
metadata, err = agentClient.Metadata(ctx)
|
||||
manifest, err = agentClient.Manifest(ctx)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthUnhealthy, metadata.Apps[1].Health)
|
||||
require.EqualValues(t, codersdk.WorkspaceAppHealthUnhealthy, manifest.Apps[1].Health)
|
||||
}
|
||||
|
||||
// nolint:bodyclose
|
||||
@@ -1262,3 +1262,155 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWorkspaceAgent_Metadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
IncludeProvisionerDaemon: true,
|
||||
})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
authToken := uuid.NewString()
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionPlan: echo.ProvisionComplete,
|
||||
ProvisionApply: []*proto.Provision_Response{{
|
||||
Type: &proto.Provision_Response_Complete{
|
||||
Complete: &proto.Provision_Complete{
|
||||
Resources: []*proto.Resource{{
|
||||
Name: "example",
|
||||
Type: "aws_instance",
|
||||
Agents: []*proto.Agent{{
|
||||
Metadata: []*proto.Agent_Metadata{
|
||||
{
|
||||
DisplayName: "First Meta",
|
||||
Key: "foo1",
|
||||
Script: "echo hi",
|
||||
Interval: 10,
|
||||
Timeout: 3,
|
||||
},
|
||||
{
|
||||
DisplayName: "Second Meta",
|
||||
Key: "foo2",
|
||||
Script: "echo howdy",
|
||||
Interval: 10,
|
||||
Timeout: 3,
|
||||
},
|
||||
{
|
||||
DisplayName: "TooLong",
|
||||
Key: "foo3",
|
||||
Script: "echo howdy",
|
||||
Interval: 10,
|
||||
Timeout: 3,
|
||||
},
|
||||
},
|
||||
Id: uuid.NewString(),
|
||||
Auth: &proto.Agent_Token{
|
||||
Token: authToken,
|
||||
},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
for _, res := range workspace.LatestBuild.Resources {
|
||||
for _, a := range res.Agents {
|
||||
require.Equal(t, codersdk.WorkspaceAgentLifecycleCreated, a.LifecycleState)
|
||||
}
|
||||
}
|
||||
|
||||
agentClient := agentsdk.New(client.URL)
|
||||
agentClient.SetSessionToken(authToken)
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
manifest, err := agentClient.Manifest(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify manifest API response.
|
||||
require.Equal(t, "First Meta", manifest.Metadata[0].DisplayName)
|
||||
require.Equal(t, "foo1", manifest.Metadata[0].Key)
|
||||
require.Equal(t, "echo hi", manifest.Metadata[0].Script)
|
||||
require.EqualValues(t, 10, manifest.Metadata[0].Interval)
|
||||
require.EqualValues(t, 3, manifest.Metadata[0].Timeout)
|
||||
|
||||
post := func(key string, mr codersdk.WorkspaceAgentMetadataResult) {
|
||||
err := agentClient.PostMetadata(ctx, key, mr)
|
||||
require.NoError(t, err, "post metadata", t)
|
||||
}
|
||||
|
||||
workspace, err = client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err, "get workspace")
|
||||
|
||||
agentID := workspace.LatestBuild.Resources[0].Agents[0].ID
|
||||
|
||||
var update []codersdk.WorkspaceAgentMetadata
|
||||
|
||||
check := func(want codersdk.WorkspaceAgentMetadataResult, got codersdk.WorkspaceAgentMetadata) {
|
||||
require.WithinDuration(t, want.CollectedAt, got.Result.CollectedAt, time.Second)
|
||||
require.WithinDuration(
|
||||
t, time.Now(), got.Result.CollectedAt.Add(time.Duration(got.Result.Age)*time.Second), time.Millisecond*500,
|
||||
)
|
||||
require.Equal(t, want.Value, got.Result.Value)
|
||||
require.Equal(t, want.Error, got.Result.Error)
|
||||
}
|
||||
|
||||
wantMetadata1 := codersdk.WorkspaceAgentMetadataResult{
|
||||
CollectedAt: time.Now(),
|
||||
Value: "bar",
|
||||
}
|
||||
|
||||
// Initial post must come before the Watch is established.
|
||||
post("foo1", wantMetadata1)
|
||||
|
||||
updates, errors := client.WatchWorkspaceAgentMetadata(ctx, agentID)
|
||||
|
||||
recvUpdate := func() []codersdk.WorkspaceAgentMetadata {
|
||||
select {
|
||||
case err := <-errors:
|
||||
t.Fatalf("error watching metadata: %v", err)
|
||||
return nil
|
||||
case update := <-updates:
|
||||
return update
|
||||
}
|
||||
}
|
||||
|
||||
update = recvUpdate()
|
||||
require.Len(t, update, 3)
|
||||
check(wantMetadata1, update[0])
|
||||
// The second metadata result is not yet posted.
|
||||
require.Zero(t, update[1].Result.CollectedAt)
|
||||
|
||||
wantMetadata2 := wantMetadata1
|
||||
post("foo2", wantMetadata2)
|
||||
update = recvUpdate()
|
||||
require.Len(t, update, 3)
|
||||
check(wantMetadata1, update[0])
|
||||
check(wantMetadata2, update[1])
|
||||
|
||||
wantMetadata1.Error = "error"
|
||||
post("foo1", wantMetadata1)
|
||||
update = recvUpdate()
|
||||
require.Len(t, update, 3)
|
||||
check(wantMetadata1, update[0])
|
||||
|
||||
const maxValueLen = 32 << 10
|
||||
tooLongValueMetadata := wantMetadata1
|
||||
tooLongValueMetadata.Value = strings.Repeat("a", maxValueLen*2)
|
||||
tooLongValueMetadata.Error = ""
|
||||
tooLongValueMetadata.CollectedAt = time.Now()
|
||||
post("foo3", tooLongValueMetadata)
|
||||
got := recvUpdate()[2]
|
||||
require.Len(t, got.Result.Value, maxValueLen)
|
||||
require.NotEmpty(t, got.Result.Error)
|
||||
|
||||
unknownKeyMetadata := wantMetadata1
|
||||
err = agentClient.PostMetadata(ctx, "unknown", unknownKeyMetadata)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user