mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: add telemetry support for workspace agent subsystem (#7579)
This commit is contained in:
15
coderd/apidoc/docs.go
generated
15
coderd/apidoc/docs.go
generated
@ -5966,6 +5966,9 @@ const docTemplate = `{
|
||||
"expanded_directory": {
|
||||
"type": "string"
|
||||
},
|
||||
"subsystem": {
|
||||
"$ref": "#/definitions/codersdk.AgentSubsystem"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -6406,6 +6409,15 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.AgentSubsystem": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"envbox"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"AgentSubsystemEnvbox"
|
||||
]
|
||||
},
|
||||
"codersdk.AppHostResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -9627,6 +9639,9 @@ const docTemplate = `{
|
||||
"status": {
|
||||
"$ref": "#/definitions/codersdk.WorkspaceAgentStatus"
|
||||
},
|
||||
"subsystem": {
|
||||
"$ref": "#/definitions/codersdk.AgentSubsystem"
|
||||
},
|
||||
"troubleshooting_url": {
|
||||
"type": "string"
|
||||
},
|
||||
|
11
coderd/apidoc/swagger.json
generated
11
coderd/apidoc/swagger.json
generated
@ -5258,6 +5258,9 @@
|
||||
"expanded_directory": {
|
||||
"type": "string"
|
||||
},
|
||||
"subsystem": {
|
||||
"$ref": "#/definitions/codersdk.AgentSubsystem"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -5676,6 +5679,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.AgentSubsystem": {
|
||||
"type": "string",
|
||||
"enum": ["envbox"],
|
||||
"x-enum-varnames": ["AgentSubsystemEnvbox"]
|
||||
},
|
||||
"codersdk.AppHostResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -8665,6 +8673,9 @@
|
||||
"status": {
|
||||
"$ref": "#/definitions/codersdk.WorkspaceAgentStatus"
|
||||
},
|
||||
"subsystem": {
|
||||
"$ref": "#/definitions/codersdk.AgentSubsystem"
|
||||
},
|
||||
"troubleshooting_url": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -1029,7 +1029,8 @@ func (s *MethodTestSuite) TestWorkspace() {
|
||||
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
|
||||
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
|
||||
check.Args(database.UpdateWorkspaceAgentStartupByIDParams{
|
||||
ID: agt.ID,
|
||||
ID: agt.ID,
|
||||
Subsystem: database.WorkspaceAgentSubsystemNone,
|
||||
}).Asserts(ws, rbac.ActionUpdate).Returns()
|
||||
}))
|
||||
s.Run("GetWorkspaceAgentStartupLogsAfter", s.Subtest(func(db database.Store, check *expects) {
|
||||
|
@ -3702,6 +3702,7 @@ func (q *fakeQuerier) UpdateWorkspaceAgentStartupByID(_ context.Context, arg dat
|
||||
|
||||
agent.Version = arg.Version
|
||||
agent.ExpandedDirectory = arg.ExpandedDirectory
|
||||
agent.Subsystem = arg.Subsystem
|
||||
q.workspaceAgents[index] = agent
|
||||
return nil
|
||||
}
|
||||
|
7
coderd/database/dump.sql
generated
7
coderd/database/dump.sql
generated
@ -116,6 +116,12 @@ CREATE TYPE workspace_agent_lifecycle_state AS ENUM (
|
||||
'off'
|
||||
);
|
||||
|
||||
CREATE TYPE workspace_agent_subsystem AS ENUM (
|
||||
'envbuilder',
|
||||
'envbox',
|
||||
'none'
|
||||
);
|
||||
|
||||
CREATE TYPE workspace_app_health AS ENUM (
|
||||
'disabled',
|
||||
'initializing',
|
||||
@ -597,6 +603,7 @@ CREATE TABLE workspace_agents (
|
||||
shutdown_script_timeout_seconds integer DEFAULT 0 NOT NULL,
|
||||
startup_logs_length integer DEFAULT 0 NOT NULL,
|
||||
startup_logs_overflowed boolean DEFAULT false NOT NULL,
|
||||
subsystem workspace_agent_subsystem DEFAULT 'none'::workspace_agent_subsystem NOT NULL,
|
||||
CONSTRAINT max_startup_logs_length CHECK ((startup_logs_length <= 1048576))
|
||||
);
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
BEGIN;
|
||||
ALTER TABLE workspace_agents DROP COLUMN subsystem;
|
||||
DROP TYPE workspace_agent_subsystem;
|
||||
COMMIT;
|
@ -0,0 +1,4 @@
|
||||
BEGIN;
|
||||
CREATE TYPE workspace_agent_subsystem AS ENUM ('envbuilder', 'envbox', 'none');
|
||||
ALTER TABLE workspace_agents ADD COLUMN subsystem workspace_agent_subsystem NOT NULL default 'none';
|
||||
COMMIT;
|
@ -1096,6 +1096,67 @@ func AllWorkspaceAgentLifecycleStateValues() []WorkspaceAgentLifecycleState {
|
||||
}
|
||||
}
|
||||
|
||||
type WorkspaceAgentSubsystem string
|
||||
|
||||
const (
|
||||
WorkspaceAgentSubsystemEnvbuilder WorkspaceAgentSubsystem = "envbuilder"
|
||||
WorkspaceAgentSubsystemEnvbox WorkspaceAgentSubsystem = "envbox"
|
||||
WorkspaceAgentSubsystemNone WorkspaceAgentSubsystem = "none"
|
||||
)
|
||||
|
||||
func (e *WorkspaceAgentSubsystem) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = WorkspaceAgentSubsystem(s)
|
||||
case string:
|
||||
*e = WorkspaceAgentSubsystem(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for WorkspaceAgentSubsystem: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullWorkspaceAgentSubsystem struct {
|
||||
WorkspaceAgentSubsystem WorkspaceAgentSubsystem
|
||||
Valid bool // Valid is true if WorkspaceAgentSubsystem is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullWorkspaceAgentSubsystem) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.WorkspaceAgentSubsystem, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.WorkspaceAgentSubsystem.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullWorkspaceAgentSubsystem) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.WorkspaceAgentSubsystem), nil
|
||||
}
|
||||
|
||||
func (e WorkspaceAgentSubsystem) Valid() bool {
|
||||
switch e {
|
||||
case WorkspaceAgentSubsystemEnvbuilder,
|
||||
WorkspaceAgentSubsystemEnvbox,
|
||||
WorkspaceAgentSubsystemNone:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AllWorkspaceAgentSubsystemValues() []WorkspaceAgentSubsystem {
|
||||
return []WorkspaceAgentSubsystem{
|
||||
WorkspaceAgentSubsystemEnvbuilder,
|
||||
WorkspaceAgentSubsystemEnvbox,
|
||||
WorkspaceAgentSubsystemNone,
|
||||
}
|
||||
}
|
||||
|
||||
type WorkspaceAppHealth string
|
||||
|
||||
const (
|
||||
@ -1587,7 +1648,8 @@ type WorkspaceAgent struct {
|
||||
// Total length of startup logs
|
||||
StartupLogsLength int32 `db:"startup_logs_length" json:"startup_logs_length"`
|
||||
// Whether the startup logs overflowed in length
|
||||
StartupLogsOverflowed bool `db:"startup_logs_overflowed" json:"startup_logs_overflowed"`
|
||||
StartupLogsOverflowed bool `db:"startup_logs_overflowed" json:"startup_logs_overflowed"`
|
||||
Subsystem WorkspaceAgentSubsystem `db:"subsystem" json:"subsystem"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentMetadatum struct {
|
||||
|
@ -5553,7 +5553,7 @@ func (q *sqlQuerier) DeleteOldWorkspaceAgentStartupLogs(ctx context.Context) err
|
||||
|
||||
const getWorkspaceAgentByAuthToken = `-- name: GetWorkspaceAgentByAuthToken :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5596,13 +5596,14 @@ func (q *sqlQuerier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByID = `-- name: GetWorkspaceAgentByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5643,13 +5644,14 @@ func (q *sqlQuerier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (W
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByInstanceID = `-- name: GetWorkspaceAgentByInstanceID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5692,6 +5694,7 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -5786,7 +5789,7 @@ func (q *sqlQuerier) GetWorkspaceAgentStartupLogsAfter(ctx context.Context, arg
|
||||
|
||||
const getWorkspaceAgentsByResourceIDs = `-- name: GetWorkspaceAgentsByResourceIDs :many
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5833,6 +5836,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -5848,7 +5852,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
||||
}
|
||||
|
||||
const getWorkspaceAgentsCreatedAfter = `-- name: GetWorkspaceAgentsCreatedAfter :many
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed FROM workspace_agents WHERE created_at > $1
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem FROM workspace_agents WHERE created_at > $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceAgent, error) {
|
||||
@ -5891,6 +5895,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -5907,7 +5912,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created
|
||||
|
||||
const getWorkspaceAgentsInLatestBuildByWorkspaceID = `-- name: GetWorkspaceAgentsInLatestBuildByWorkspaceID :many
|
||||
SELECT
|
||||
workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.startup_script, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.login_before_ready, workspace_agents.startup_script_timeout_seconds, workspace_agents.expanded_directory, workspace_agents.shutdown_script, workspace_agents.shutdown_script_timeout_seconds, workspace_agents.startup_logs_length, workspace_agents.startup_logs_overflowed
|
||||
workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.startup_script, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.login_before_ready, workspace_agents.startup_script_timeout_seconds, workspace_agents.expanded_directory, workspace_agents.shutdown_script, workspace_agents.shutdown_script_timeout_seconds, workspace_agents.startup_logs_length, workspace_agents.startup_logs_overflowed, workspace_agents.subsystem
|
||||
FROM
|
||||
workspace_agents
|
||||
JOIN
|
||||
@ -5966,6 +5971,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx context.Co
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -6006,7 +6012,7 @@ INSERT INTO
|
||||
shutdown_script_timeout_seconds
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem
|
||||
`
|
||||
|
||||
type InsertWorkspaceAgentParams struct {
|
||||
@ -6089,6 +6095,7 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
&i.StartupLogsLength,
|
||||
&i.StartupLogsOverflowed,
|
||||
&i.Subsystem,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -6275,19 +6282,26 @@ UPDATE
|
||||
workspace_agents
|
||||
SET
|
||||
version = $2,
|
||||
expanded_directory = $3
|
||||
expanded_directory = $3,
|
||||
subsystem = $4
|
||||
WHERE
|
||||
id = $1
|
||||
`
|
||||
|
||||
type UpdateWorkspaceAgentStartupByIDParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Version string `db:"version" json:"version"`
|
||||
ExpandedDirectory string `db:"expanded_directory" json:"expanded_directory"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
Version string `db:"version" json:"version"`
|
||||
ExpandedDirectory string `db:"expanded_directory" json:"expanded_directory"`
|
||||
Subsystem WorkspaceAgentSubsystem `db:"subsystem" json:"subsystem"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateWorkspaceAgentStartupByID(ctx context.Context, arg UpdateWorkspaceAgentStartupByIDParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateWorkspaceAgentStartupByID, arg.ID, arg.Version, arg.ExpandedDirectory)
|
||||
_, err := q.db.ExecContext(ctx, updateWorkspaceAgentStartupByID,
|
||||
arg.ID,
|
||||
arg.Version,
|
||||
arg.ExpandedDirectory,
|
||||
arg.Subsystem,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,8 @@ UPDATE
|
||||
workspace_agents
|
||||
SET
|
||||
version = $2,
|
||||
expanded_directory = $3
|
||||
expanded_directory = $3,
|
||||
subsystem = $4
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
|
@ -562,6 +562,7 @@ func ConvertWorkspaceAgent(agent database.WorkspaceAgent) WorkspaceAgent {
|
||||
Directory: agent.Directory != "",
|
||||
ConnectionTimeoutSeconds: agent.ConnectionTimeoutSeconds,
|
||||
ShutdownScript: agent.ShutdownScript.Valid,
|
||||
Subsystem: string(agent.Subsystem),
|
||||
}
|
||||
if agent.FirstConnectedAt.Valid {
|
||||
snapAgent.FirstConnectedAt = &agent.FirstConnectedAt.Time
|
||||
@ -783,6 +784,7 @@ type WorkspaceAgent struct {
|
||||
DisconnectedAt *time.Time `json:"disconnected_at"`
|
||||
ConnectionTimeoutSeconds int32 `json:"connection_timeout_seconds"`
|
||||
ShutdownScript bool `json:"shutdown_script"`
|
||||
Subsystem string `json:"subsystem"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentStat struct {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package telemetry_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -22,6 +21,7 @@ import (
|
||||
"github.com/coder/coder/coderd/database/dbfake"
|
||||
"github.com/coder/coder/coderd/database/dbgen"
|
||||
"github.com/coder/coder/coderd/telemetry"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@ -37,7 +37,7 @@ func TestTelemetry(t *testing.T) {
|
||||
|
||||
db := dbfake.New()
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
_, _ = dbgen.APIKey(t, db, database.APIKey{})
|
||||
_ = dbgen.ParameterSchema(t, db, database.ParameterSchema{
|
||||
DefaultSourceScheme: database.ParameterSourceSchemeNone,
|
||||
@ -59,7 +59,18 @@ func TestTelemetry(t *testing.T) {
|
||||
SharingLevel: database.AppSharingLevelOwner,
|
||||
Health: database.WorkspaceAppHealthDisabled,
|
||||
})
|
||||
_ = dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{})
|
||||
wsagent := dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{
|
||||
Subsystem: database.WorkspaceAgentSubsystemEnvbox,
|
||||
})
|
||||
// Update the workspace agent to have a valid subsystem.
|
||||
err = db.UpdateWorkspaceAgentStartupByID(ctx, database.UpdateWorkspaceAgentStartupByIDParams{
|
||||
ID: wsagent.ID,
|
||||
Version: wsagent.Version,
|
||||
ExpandedDirectory: wsagent.ExpandedDirectory,
|
||||
Subsystem: database.WorkspaceAgentSubsystemEnvbox,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
Reason: database.BuildReasonAutostart,
|
||||
@ -88,6 +99,9 @@ func TestTelemetry(t *testing.T) {
|
||||
require.Len(t, snapshot.WorkspaceBuilds, 1)
|
||||
require.Len(t, snapshot.WorkspaceResources, 1)
|
||||
require.Len(t, snapshot.WorkspaceAgentStats, 1)
|
||||
|
||||
wsa := snapshot.WorkspaceAgents[0]
|
||||
require.Equal(t, string(database.WorkspaceAgentSubsystemEnvbox), wsa.Subsystem)
|
||||
})
|
||||
t.Run("HashedEmail", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
@ -220,6 +220,7 @@ func (api *API) postWorkspaceAgentStartup(rw http.ResponseWriter, r *http.Reques
|
||||
ID: apiAgent.ID,
|
||||
Version: req.Version,
|
||||
ExpandedDirectory: req.ExpandedDirectory,
|
||||
Subsystem: convertWorkspaceAgentSubsystem(req.Subsystem),
|
||||
}); err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Error setting agent version",
|
||||
@ -1129,6 +1130,7 @@ func convertWorkspaceAgent(derpMap *tailcfg.DERPMap, coordinator tailnet.Coordin
|
||||
StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds,
|
||||
ShutdownScript: dbAgent.ShutdownScript.String,
|
||||
ShutdownScriptTimeoutSeconds: dbAgent.ShutdownScriptTimeoutSeconds,
|
||||
Subsystem: codersdk.AgentSubsystem(dbAgent.Subsystem),
|
||||
}
|
||||
node := coordinator.Node(dbAgent.ID)
|
||||
if node != nil {
|
||||
@ -1983,3 +1985,12 @@ func convertWorkspaceAgentStartupLog(logEntry database.WorkspaceAgentStartupLog)
|
||||
Level: codersdk.LogLevel(logEntry.Level),
|
||||
}
|
||||
}
|
||||
|
||||
func convertWorkspaceAgentSubsystem(ss codersdk.AgentSubsystem) database.WorkspaceAgentSubsystem {
|
||||
switch ss {
|
||||
case codersdk.AgentSubsystemEnvbox:
|
||||
return database.WorkspaceAgentSubsystemEnvbox
|
||||
default:
|
||||
return database.WorkspaceAgentSubsystemNone
|
||||
}
|
||||
}
|
||||
|
@ -1326,3 +1326,85 @@ func TestWorkspaceAgent_Metadata(t *testing.T) {
|
||||
err = agentClient.PostMetadata(ctx, "unknown", unknownKeyMetadata)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestWorkspaceAgent_Startup(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OK", func(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: echo.ProvisionApplyWithAgent(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)
|
||||
|
||||
agentClient := agentsdk.New(client.URL)
|
||||
agentClient.SetSessionToken(authToken)
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
const (
|
||||
expectedVersion = "v1.2.3"
|
||||
expectedDir = "/home/coder"
|
||||
expectedSubsystem = codersdk.AgentSubsystemEnvbox
|
||||
)
|
||||
|
||||
err := agentClient.PostStartup(ctx, agentsdk.PostStartupRequest{
|
||||
Version: expectedVersion,
|
||||
ExpandedDirectory: expectedDir,
|
||||
Subsystem: expectedSubsystem,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
workspace, err = client.Workspace(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
wsagent, err := client.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedVersion, wsagent.Version)
|
||||
require.Equal(t, expectedDir, wsagent.ExpandedDirectory)
|
||||
require.Equal(t, expectedSubsystem, wsagent.Subsystem)
|
||||
})
|
||||
|
||||
t.Run("InvalidSemver", func(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: echo.ProvisionApplyWithAgent(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)
|
||||
|
||||
agentClient := agentsdk.New(client.URL)
|
||||
agentClient.SetSessionToken(authToken)
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
err := agentClient.PostStartup(ctx, agentsdk.PostStartupRequest{
|
||||
Version: "1.2.3",
|
||||
})
|
||||
require.Error(t, err)
|
||||
cerr, ok := codersdk.AsError(err)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, http.StatusBadRequest, cerr.StatusCode())
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user