feat(storage,agent): add label attribute
arcad/emissary/pipeline/head Something is wrong with the build of this commit Details

This commit is contained in:
wpetit 2023-04-01 13:28:18 +02:00
parent c638fe102b
commit d2bcdd2999
11 changed files with 51 additions and 7 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@ dist/
/tools /tools
/tmp /tmp
/state.json /state.json
/emissary.sqlite /emissary.sqlite*
/.gitea-release /.gitea-release
/agent-key.json /agent-key.json
/apps /apps

View File

@ -7,6 +7,7 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/command/agent" "forge.cadoles.com/Cadoles/emissary/internal/command/agent"
"forge.cadoles.com/Cadoles/emissary/internal/command/api" "forge.cadoles.com/Cadoles/emissary/internal/command/api"
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/format"
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/spec" _ "forge.cadoles.com/Cadoles/emissary/internal/imports/spec"
) )

View File

@ -10,6 +10,7 @@ import (
type UpdateAgentOptions struct { type UpdateAgentOptions struct {
Status *int Status *int
Label *string
Options []OptionFunc Options []OptionFunc
} }
@ -21,6 +22,12 @@ func WithAgentStatus(status int) UpdateAgentOptionFunc {
} }
} }
func WithAgentLabel(label string) UpdateAgentOptionFunc {
return func(opts *UpdateAgentOptions) {
opts.Label = &label
}
}
func WithUpdateAgentsOptions(funcs ...OptionFunc) UpdateAgentOptionFunc { func WithUpdateAgentsOptions(funcs ...OptionFunc) UpdateAgentOptionFunc {
return func(opts *UpdateAgentOptions) { return func(opts *UpdateAgentOptions) {
opts.Options = funcs opts.Options = funcs
@ -39,6 +46,10 @@ func (c *Client) UpdateAgent(ctx context.Context, agentID datastore.AgentID, fun
payload["status"] = *opts.Status payload["status"] = *opts.Status
} }
if opts.Label != nil {
payload["label"] = *opts.Label
}
response := withResponse[struct { response := withResponse[struct {
Agent *datastore.Agent `json:"agent"` Agent *datastore.Agent `json:"agent"`
}]() }]()

View File

@ -22,6 +22,11 @@ func UpdateCommand() *cli.Command {
Usage: "Set `STATUS` to selected agent", Usage: "Set `STATUS` to selected agent",
Value: -1, Value: -1,
}, },
&cli.StringFlag{
Name: "label",
Usage: "Set `LABEL` to selected agent",
Value: "",
},
), ),
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
baseFlags := clientFlag.GetBaseFlags(ctx) baseFlags := clientFlag.GetBaseFlags(ctx)
@ -43,6 +48,11 @@ func UpdateCommand() *cli.Command {
options = append(options, client.WithAgentStatus(status)) options = append(options, client.WithAgentStatus(status))
} }
label := ctx.String("label")
if label != "" {
options = append(options, client.WithAgentLabel(label))
}
client := client.New(baseFlags.ServerURL, client.WithToken(token)) client := client.New(baseFlags.ServerURL, client.WithToken(token))
agent, err := client.UpdateAgent(ctx.Context, agentID, options...) agent, err := client.UpdateAgent(ctx.Context, agentID, options...)

View File

@ -7,6 +7,7 @@ func agentHints(outputMode format.OutputMode) format.Hints {
OutputMode: outputMode, OutputMode: outputMode,
Props: []format.Prop{ Props: []format.Prop{
format.NewProp("ID", "ID"), format.NewProp("ID", "ID"),
format.NewProp("Label", "Label"),
format.NewProp("Thumbprint", "Thumbprint"), format.NewProp("Thumbprint", "Thumbprint"),
format.NewProp("Status", "Status"), format.NewProp("Status", "Status"),
format.NewProp("CreatedAt", "CreatedAt"), format.NewProp("CreatedAt", "CreatedAt"),

View File

@ -21,6 +21,7 @@ const (
type Agent struct { type Agent struct {
ID AgentID `json:"id"` ID AgentID `json:"id"`
Label string `json:"label"`
Thumbprint string `json:"thumbprint"` Thumbprint string `json:"thumbprint"`
KeySet *SerializableKeySet `json:"keyset,omitempty"` KeySet *SerializableKeySet `json:"keyset,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"` Metadata map[string]any `json:"metadata,omitempty"`

View File

@ -68,6 +68,7 @@ func WithAgentQueryThumbprints(thumbprints ...string) AgentQueryOptionFunc {
type AgentUpdateOptionFunc func(*AgentUpdateOptions) type AgentUpdateOptionFunc func(*AgentUpdateOptions)
type AgentUpdateOptions struct { type AgentUpdateOptions struct {
Label *string
Status *AgentStatus Status *AgentStatus
Metadata *map[string]any Metadata *map[string]any
KeySet *jwk.Set KeySet *jwk.Set
@ -97,3 +98,9 @@ func WithAgentUpdateThumbprint(thumbprint string) AgentUpdateOptionFunc {
opts.Thumbprint = &thumbprint opts.Thumbprint = &thumbprint
} }
} }
func WithAgentUpdateLabel(label string) AgentUpdateOptionFunc {
return func(opts *AgentUpdateOptions) {
opts.Label = &label
}
}

View File

@ -127,7 +127,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
count := 0 count := 0
err := r.withTx(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `SELECT id, thumbprint, status, created_at, updated_at FROM agents` query := `SELECT id, label, thumbprint, status, created_at, updated_at FROM agents`
limit := 10 limit := 10
if options.Limit != nil { if options.Limit != nil {
@ -195,7 +195,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
metadata := JSONMap{} metadata := JSONMap{}
if err := rows.Scan(&agent.ID, &agent.Thumbprint, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil { if err := rows.Scan(&agent.ID, &agent.Label, &agent.Thumbprint, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -315,7 +315,7 @@ func (r *AgentRepository) Get(ctx context.Context, id datastore.AgentID) (*datas
err := r.withTx(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := ` query := `
SELECT "id", "thumbprint", "keyset", "metadata", "status", "created_at", "updated_at" SELECT "id", "label", "thumbprint", "keyset", "metadata", "status", "created_at", "updated_at"
FROM agents FROM agents
WHERE id = $1 WHERE id = $1
` `
@ -325,7 +325,7 @@ func (r *AgentRepository) Get(ctx context.Context, id datastore.AgentID) (*datas
metadata := JSONMap{} metadata := JSONMap{}
var rawKeySet []byte var rawKeySet []byte
if err := row.Scan(&agent.ID, &agent.Thumbprint, &rawKeySet, &metadata, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil { if err := row.Scan(&agent.ID, &agent.Label, &agent.Thumbprint, &rawKeySet, &metadata, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return datastore.ErrNotFound return datastore.ErrNotFound
} }
@ -395,6 +395,12 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
index++ index++
} }
if options.Label != nil {
query += fmt.Sprintf(`, label = $%d`, index)
args = append(args, *options.Label)
index++
}
if options.Metadata != nil { if options.Metadata != nil {
query += fmt.Sprintf(`, metadata = $%d`, index) query += fmt.Sprintf(`, metadata = $%d`, index)
args = append(args, JSONMap(*options.Metadata)) args = append(args, JSONMap(*options.Metadata))
@ -403,7 +409,7 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
query += ` query += `
WHERE id = $1 WHERE id = $1
RETURNING "id", "thumbprint", "keyset", "metadata", "status", "created_at", "updated_at" RETURNING "id", "label", "thumbprint", "keyset", "metadata", "status", "created_at", "updated_at"
` `
row := tx.QueryRowContext(ctx, query, args...) row := tx.QueryRowContext(ctx, query, args...)
@ -411,7 +417,7 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
metadata := JSONMap{} metadata := JSONMap{}
var rawKeySet []byte var rawKeySet []byte
if err := row.Scan(&agent.ID, &agent.Thumbprint, &rawKeySet, &metadata, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil { if err := row.Scan(&agent.ID, &agent.Label, &agent.Thumbprint, &rawKeySet, &metadata, &agent.Status, &agent.CreatedAt, &agent.UpdatedAt); err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return datastore.ErrNotFound return datastore.ErrNotFound
} }

View File

@ -145,6 +145,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
type updateAgentRequest struct { type updateAgentRequest struct {
Status *datastore.AgentStatus `json:"status" validate:"omitempty,oneof=0 1 2 3"` Status *datastore.AgentStatus `json:"status" validate:"omitempty,oneof=0 1 2 3"`
Label *string `json:"label" validate:"omitempty"`
} }
func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) { func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) {
@ -166,6 +167,10 @@ func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) {
options = append(options, datastore.WithAgentUpdateStatus(*updateAgentReq.Status)) options = append(options, datastore.WithAgentUpdateStatus(*updateAgentReq.Status))
} }
if updateAgentReq.Label != nil {
options = append(options, datastore.WithAgentUpdateLabel(*updateAgentReq.Label))
}
agent, err := s.agentRepo.Update( agent, err := s.agentRepo.Update(
ctx, ctx,
datastore.AgentID(agentID), datastore.AgentID(agentID),

View File

@ -0,0 +1 @@
ALTER TABLE agents DROP COLUMN label;

View File

@ -0,0 +1 @@
ALTER TABLE agents ADD COLUMN label TEXT DEFAULT "";