feat: add agent metadata (#6614)

This commit is contained in:
Ammar Bandukwala
2023-03-31 15:26:19 -05:00
committed by GitHub
parent c191692751
commit ca4fa81570
62 changed files with 3139 additions and 727 deletions

View File

@ -1564,6 +1564,44 @@ func (q *querier) InsertWorkspaceAgentStat(ctx context.Context, arg database.Ins
return q.db.InsertWorkspaceAgentStat(ctx, arg)
}
func (q *querier) InsertWorkspaceAgentMetadata(ctx context.Context, arg database.InsertWorkspaceAgentMetadataParams) error {
// We don't check for workspace ownership here since the agent metadata may
// be associated with an orphaned agent used by a dry run build.
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
return err
}
return q.db.InsertWorkspaceAgentMetadata(ctx, arg)
}
func (q *querier) UpdateWorkspaceAgentMetadata(ctx context.Context, arg database.UpdateWorkspaceAgentMetadataParams) error {
workspace, err := q.db.GetWorkspaceByAgentID(ctx, arg.WorkspaceAgentID)
if err != nil {
return err
}
err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace)
if err != nil {
return err
}
return q.db.UpdateWorkspaceAgentMetadata(ctx, arg)
}
func (q *querier) GetWorkspaceAgentMetadata(ctx context.Context, workspaceAgentID uuid.UUID) ([]database.WorkspaceAgentMetadatum, error) {
workspace, err := q.db.GetWorkspaceByAgentID(ctx, workspaceAgentID)
if err != nil {
return nil, err
}
err = q.authorizeContext(ctx, rbac.ActionRead, workspace)
if err != nil {
return nil, err
}
return q.db.GetWorkspaceAgentMetadata(ctx, workspaceAgentID)
}
func (q *querier) UpdateWorkspaceAppHealthByID(ctx context.Context, arg database.UpdateWorkspaceAppHealthByIDParams) error {
// TODO: This is a workspace agent operation. Should users be able to query this?
workspace, err := q.db.GetWorkspaceByWorkspaceAppID(ctx, arg.ID)

View File

@ -124,6 +124,7 @@ type data struct {
templateVersionVariables []database.TemplateVersionVariable
templates []database.Template
workspaceAgents []database.WorkspaceAgent
workspaceAgentMetadata []database.WorkspaceAgentMetadatum
workspaceAgentLogs []database.WorkspaceAgentStartupLog
workspaceApps []database.WorkspaceApp
workspaceBuilds []database.WorkspaceBuild
@ -2741,6 +2742,60 @@ func (q *fakeQuerier) InsertAPIKey(_ context.Context, arg database.InsertAPIKeyP
return key, nil
}
func (q *fakeQuerier) UpdateWorkspaceAgentMetadata(_ context.Context, arg database.UpdateWorkspaceAgentMetadataParams) error {
q.mutex.Lock()
defer q.mutex.Unlock()
//nolint:gosimple
updated := database.WorkspaceAgentMetadatum{
WorkspaceAgentID: arg.WorkspaceAgentID,
Key: arg.Key,
Value: arg.Value,
Error: arg.Error,
CollectedAt: arg.CollectedAt,
}
for i, m := range q.workspaceAgentMetadata {
if m.WorkspaceAgentID == arg.WorkspaceAgentID && m.Key == arg.Key {
q.workspaceAgentMetadata[i] = updated
return nil
}
}
return nil
}
func (q *fakeQuerier) InsertWorkspaceAgentMetadata(_ context.Context, arg database.InsertWorkspaceAgentMetadataParams) error {
q.mutex.Lock()
defer q.mutex.Unlock()
//nolint:gosimple
metadatum := database.WorkspaceAgentMetadatum{
WorkspaceAgentID: arg.WorkspaceAgentID,
Script: arg.Script,
DisplayName: arg.DisplayName,
Key: arg.Key,
Timeout: arg.Timeout,
Interval: arg.Interval,
}
q.workspaceAgentMetadata = append(q.workspaceAgentMetadata, metadatum)
return nil
}
func (q *fakeQuerier) GetWorkspaceAgentMetadata(_ context.Context, workspaceAgentID uuid.UUID) ([]database.WorkspaceAgentMetadatum, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
metadata := make([]database.WorkspaceAgentMetadatum, 0)
for _, m := range q.workspaceAgentMetadata {
if m.WorkspaceAgentID == workspaceAgentID {
metadata = append(metadata, m)
}
}
return metadata, nil
}
func (q *fakeQuerier) InsertFile(_ context.Context, arg database.InsertFileParams) (database.File, error) {
if err := validateDatabaseType(arg); err != nil {
return database.File{}, err

View File

@ -475,6 +475,18 @@ CREATE TABLE users (
last_seen_at timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL
);
CREATE UNLOGGED TABLE workspace_agent_metadata (
workspace_agent_id uuid NOT NULL,
display_name character varying(127) NOT NULL,
key character varying(127) NOT NULL,
script character varying(65535) NOT NULL,
value character varying(65535) DEFAULT ''::character varying NOT NULL,
error character varying(65535) DEFAULT ''::character varying NOT NULL,
timeout bigint NOT NULL,
"interval" bigint NOT NULL,
collected_at timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL
);
CREATE TABLE workspace_agent_startup_logs (
agent_id uuid NOT NULL,
created_at timestamp with time zone NOT NULL,
@ -756,6 +768,9 @@ ALTER TABLE ONLY user_links
ALTER TABLE ONLY users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
ALTER TABLE ONLY workspace_agent_metadata
ADD CONSTRAINT workspace_agent_metadata_pkey PRIMARY KEY (workspace_agent_id, key);
ALTER TABLE ONLY workspace_agent_startup_logs
ADD CONSTRAINT workspace_agent_startup_logs_pkey PRIMARY KEY (id);
@ -894,6 +909,9 @@ ALTER TABLE ONLY templates
ALTER TABLE ONLY user_links
ADD CONSTRAINT user_links_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_agent_metadata
ADD CONSTRAINT workspace_agent_metadata_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_agent_startup_logs
ADD CONSTRAINT workspace_agent_startup_logs_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;

View File

@ -0,0 +1 @@
DROP TABLE workspace_agent_metadata;

View File

@ -0,0 +1,16 @@
-- This table is UNLOGGED because it is very update-heavy and the the data
-- is not valuable enough to justify the overhead of WAL logging. This should
-- give us a ~70% improvement in write throughput.
CREATE UNLOGGED TABLE workspace_agent_metadata (
workspace_agent_id uuid NOT NULL,
display_name varchar(127) NOT NULL,
key varchar(127) NOT NULL,
script varchar(65535) NOT NULL,
value varchar(65535) NOT NULL DEFAULT '',
error varchar(65535) NOT NULL DEFAULT '',
timeout bigint NOT NULL,
interval bigint NOT NULL,
collected_at timestamp with time zone NOT NULL DEFAULT '0001-01-01 00:00:00+00',
PRIMARY KEY (workspace_agent_id, key),
FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE
);

View File

@ -0,0 +1,18 @@
INSERT INTO
workspace_agent_metadata (
workspace_agent_id,
display_name,
key,
script,
timeout,
interval
)
VALUES
(
'45e89705-e09d-4850-bcec-f9a937f5d78d',
'a h e m',
'ahem',
'rm -rf',
3,
1
);

View File

@ -1575,6 +1575,18 @@ type WorkspaceAgent struct {
StartupLogsOverflowed bool `db:"startup_logs_overflowed" json:"startup_logs_overflowed"`
}
type WorkspaceAgentMetadatum struct {
WorkspaceAgentID uuid.UUID `db:"workspace_agent_id" json:"workspace_agent_id"`
DisplayName string `db:"display_name" json:"display_name"`
Key string `db:"key" json:"key"`
Script string `db:"script" json:"script"`
Value string `db:"value" json:"value"`
Error string `db:"error" json:"error"`
Timeout int64 `db:"timeout" json:"timeout"`
Interval int64 `db:"interval" json:"interval"`
CollectedAt time.Time `db:"collected_at" json:"collected_at"`
}
type WorkspaceAgentStartupLog struct {
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`

View File

@ -126,6 +126,7 @@ type sqlcQuerier interface {
GetWorkspaceAgentByAuthToken(ctx context.Context, authToken uuid.UUID) (WorkspaceAgent, error)
GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (WorkspaceAgent, error)
GetWorkspaceAgentByInstanceID(ctx context.Context, authInstanceID string) (WorkspaceAgent, error)
GetWorkspaceAgentMetadata(ctx context.Context, workspaceAgentID uuid.UUID) ([]WorkspaceAgentMetadatum, error)
GetWorkspaceAgentStartupLogsAfter(ctx context.Context, arg GetWorkspaceAgentStartupLogsAfterParams) ([]WorkspaceAgentStartupLog, error)
GetWorkspaceAgentStats(ctx context.Context, createdAt time.Time) ([]GetWorkspaceAgentStatsRow, error)
GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceAgent, error)
@ -185,6 +186,7 @@ type sqlcQuerier interface {
InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error)
InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error)
InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error)
InsertWorkspaceAgentMetadata(ctx context.Context, arg InsertWorkspaceAgentMetadataParams) error
InsertWorkspaceAgentStartupLogs(ctx context.Context, arg InsertWorkspaceAgentStartupLogsParams) ([]WorkspaceAgentStartupLog, error)
InsertWorkspaceAgentStat(ctx context.Context, arg InsertWorkspaceAgentStatParams) (WorkspaceAgentStat, error)
InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error)
@ -229,6 +231,7 @@ type sqlcQuerier interface {
UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (Workspace, error)
UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg UpdateWorkspaceAgentConnectionByIDParams) error
UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context, arg UpdateWorkspaceAgentLifecycleStateByIDParams) error
UpdateWorkspaceAgentMetadata(ctx context.Context, arg UpdateWorkspaceAgentMetadataParams) error
UpdateWorkspaceAgentStartupByID(ctx context.Context, arg UpdateWorkspaceAgentStartupByIDParams) error
UpdateWorkspaceAgentStartupLogOverflowByID(ctx context.Context, arg UpdateWorkspaceAgentStartupLogOverflowByIDParams) error
UpdateWorkspaceAppHealthByID(ctx context.Context, arg UpdateWorkspaceAppHealthByIDParams) error

View File

@ -5297,6 +5297,48 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst
return i, err
}
const getWorkspaceAgentMetadata = `-- name: GetWorkspaceAgentMetadata :many
SELECT
workspace_agent_id, display_name, key, script, value, error, timeout, interval, collected_at
FROM
workspace_agent_metadata
WHERE
workspace_agent_id = $1
`
func (q *sqlQuerier) GetWorkspaceAgentMetadata(ctx context.Context, workspaceAgentID uuid.UUID) ([]WorkspaceAgentMetadatum, error) {
rows, err := q.db.QueryContext(ctx, getWorkspaceAgentMetadata, workspaceAgentID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []WorkspaceAgentMetadatum
for rows.Next() {
var i WorkspaceAgentMetadatum
if err := rows.Scan(
&i.WorkspaceAgentID,
&i.DisplayName,
&i.Key,
&i.Script,
&i.Value,
&i.Error,
&i.Timeout,
&i.Interval,
&i.CollectedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getWorkspaceAgentStartupLogsAfter = `-- name: GetWorkspaceAgentStartupLogsAfter :many
SELECT
agent_id, created_at, output, id
@ -5651,6 +5693,41 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
return i, err
}
const insertWorkspaceAgentMetadata = `-- name: InsertWorkspaceAgentMetadata :exec
INSERT INTO
workspace_agent_metadata (
workspace_agent_id,
display_name,
key,
script,
timeout,
interval
)
VALUES
($1, $2, $3, $4, $5, $6)
`
type InsertWorkspaceAgentMetadataParams struct {
WorkspaceAgentID uuid.UUID `db:"workspace_agent_id" json:"workspace_agent_id"`
DisplayName string `db:"display_name" json:"display_name"`
Key string `db:"key" json:"key"`
Script string `db:"script" json:"script"`
Timeout int64 `db:"timeout" json:"timeout"`
Interval int64 `db:"interval" json:"interval"`
}
func (q *sqlQuerier) InsertWorkspaceAgentMetadata(ctx context.Context, arg InsertWorkspaceAgentMetadataParams) error {
_, err := q.db.ExecContext(ctx, insertWorkspaceAgentMetadata,
arg.WorkspaceAgentID,
arg.DisplayName,
arg.Key,
arg.Script,
arg.Timeout,
arg.Interval,
)
return err
}
const insertWorkspaceAgentStartupLogs = `-- name: InsertWorkspaceAgentStartupLogs :many
WITH new_length AS (
UPDATE workspace_agents SET
@ -5758,6 +5835,37 @@ func (q *sqlQuerier) UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context,
return err
}
const updateWorkspaceAgentMetadata = `-- name: UpdateWorkspaceAgentMetadata :exec
UPDATE
workspace_agent_metadata
SET
value = $3,
error = $4,
collected_at = $5
WHERE
workspace_agent_id = $1
AND key = $2
`
type UpdateWorkspaceAgentMetadataParams struct {
WorkspaceAgentID uuid.UUID `db:"workspace_agent_id" json:"workspace_agent_id"`
Key string `db:"key" json:"key"`
Value string `db:"value" json:"value"`
Error string `db:"error" json:"error"`
CollectedAt time.Time `db:"collected_at" json:"collected_at"`
}
func (q *sqlQuerier) UpdateWorkspaceAgentMetadata(ctx context.Context, arg UpdateWorkspaceAgentMetadataParams) error {
_, err := q.db.ExecContext(ctx, updateWorkspaceAgentMetadata,
arg.WorkspaceAgentID,
arg.Key,
arg.Value,
arg.Error,
arg.CollectedAt,
)
return err
}
const updateWorkspaceAgentStartupByID = `-- name: UpdateWorkspaceAgentStartupByID :exec
UPDATE
workspace_agents

View File

@ -94,6 +94,38 @@ SET
WHERE
id = $1;
-- name: InsertWorkspaceAgentMetadata :exec
INSERT INTO
workspace_agent_metadata (
workspace_agent_id,
display_name,
key,
script,
timeout,
interval
)
VALUES
($1, $2, $3, $4, $5, $6);
-- name: UpdateWorkspaceAgentMetadata :exec
UPDATE
workspace_agent_metadata
SET
value = $3,
error = $4,
collected_at = $5
WHERE
workspace_agent_id = $1
AND key = $2;
-- name: GetWorkspaceAgentMetadata :many
SELECT
*
FROM
workspace_agent_metadata
WHERE
workspace_agent_id = $1;
-- name: UpdateWorkspaceAgentStartupLogOverflowByID :exec
UPDATE
workspace_agents