Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
60cda66
Retrieve timezone field in NodeByNodeId function
sghf Jan 14, 2026
28206c6
Add /feed/action endpoint
sghf Jan 15, 2026
19790ff
Rename post_feed_action_begin.go to post_feed_action.go
sghf Jan 15, 2026
f7f9def
Add PUT /feed/action endpoint
sghf Jan 15, 2026
26290dd
Add worker for end_action
sghf Jan 15, 2026
73491e1
Update FindActionID to include action parameter in query
sghf Jan 15, 2026
8f98266
Add UpdateActionErrors and UpdateDashActionErrors functions
sghf Jan 15, 2026
34e7d1d
Fix parameter in UpdateActionErrors function
sghf Jan 16, 2026
17607ae
Fix type for svcEnv (sql.NullString)
sghf Jan 16, 2026
1ac4aac
Add "action" in index
sghf Jan 16, 2026
08a114a
Add cron parameter to InsertSvcAction
sghf Jan 16, 2026
c953ccf
Refactor /feed/action handling
sghf Jan 16, 2026
3a469c2
Remove debug logs
sghf Jan 16, 2026
6e2449c
Add the "alert_package_differences_in_cluster" scheduler task
cvaroqui Jan 14, 2026
f586eda
Fix the logging of errors emitted by the worker tasks
cvaroqui Jan 15, 2026
a46aaec
Fix the timeout of some scheduler tasks
cvaroqui Jan 15, 2026
2f11c38
Don't schedule tasks with no period
cvaroqui Jan 15, 2026
205c326
Add the UpdateVirtualAsset(ctx, svcID, nodeID) db helper
cvaroqui Jan 15, 2026
f45ec0d
Add the DashboardUpdatePkgDiffForNode(ctx, nodeID) db helper
cvaroqui Jan 15, 2026
f98187f
Reimplement the DashboardUpdatePkgDiffForNode() db helper
cvaroqui Jan 16, 2026
462afde
Remove the "alert_package_differences_in_cluster" scheduler task
cvaroqui Jan 16, 2026
6a2d0fb
Add the "scrub_static" scheduler task
cvaroqui Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 110 additions & 1 deletion api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ servers:

info:
title: opensvc collector api
version: 1.0.8
version: 1.0.9

paths:
/feed/daemon/ping:
Expand Down Expand Up @@ -197,6 +197,64 @@ paths:
tags:
- agent

/feed/action:
put:
description: |
End an action for a given object path
operationId: PutFeedActionEnd
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Action'
responses:
202:
description: action end accepted
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
403:
$ref: '#/components/responses/403'
500:
$ref: '#/components/responses/500'
security:
- basicAuth: [ ]
- bearerAuth: [ ]
tags:
- agent
post:
description: |
Begin an action for a given object path
operationId: PostFeedAction
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Action'
responses:
202:
description: action begin accepted
content:
application/json:
schema:
$ref: '#/components/schemas/ActionRequestAccepted'
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
403:
$ref: '#/components/responses/403'
500:
$ref: '#/components/responses/500'
security:
- basicAuth: [ ]
- bearerAuth: [ ]
tags:
- agent

/version:
get:
operationId: GetVersion
Expand Down Expand Up @@ -292,6 +350,55 @@ components:
type: string
description: the opensvc client data version

ActionRequestAccepted:
type: object
required:
- uuid
properties:
uuid:
type: string

Action:
type: object
required:
- path
- action
- version
- begin
- cron
- session_uuid
- argv
- uuid
- end
- actionlogfile
- status
properties:
path:
type: string
action:
type: string
version:
type: string
description: the opensvc client data version
begin:
type: string
cron:
type: boolean
session_uuid:
type: string
argv:
type: array
items:
type: string
uuid:
type: string
end:
type: string
actionlogfile:
type: string
status:
type: string

NodeDisks:
type: object
properties:
Expand Down Expand Up @@ -558,3 +665,5 @@ components:
items:
type: string
description: object name


99 changes: 68 additions & 31 deletions api/codegen_server_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions api/codegen_type_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions apihandlers/post_feed_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package apihandlers

import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/google/uuid"
"github.com/labstack/echo/v4"

"github.com/opensvc/oc3/api"
"github.com/opensvc/oc3/cachekeys"
)

// {
// "action": "thaw",
// "argv": [
// "foo",
// "thaw",
// "--local"
// ],
// "begin": "2026-01-12 10:57:12",
// "cron": false,
// "path": "foo",
// "session_uuid": "b9d795bc-498e-4c20-aada-9feec2eaa947",
// "version": "2.1-1977"
// }

// PostFeedAction handles POST /action/begin
func (a *Api) PostFeedAction(c echo.Context) error {
keyH := cachekeys.FeedActionH
keyQ := cachekeys.FeedActionQ
keyPendingH := cachekeys.FeedActionPendingH

log := getLog(c)

nodeID := nodeIDFromContext(c)
if nodeID == "" {
log.Debug("node auth problem")
return JSONNodeAuthProblem(c)
}

ClusterID := clusterIDFromContext(c)
if ClusterID == "" {
return JSONProblemf(c, http.StatusConflict, "Refused", "authenticated node doesn't define cluster id")
}

var payload api.PostFeedActionJSONRequestBody
if err := c.Bind(&payload); err != nil {
return JSONProblem(c, http.StatusBadRequest, "Failed to json decode request body", err.Error())
}

if !strings.HasPrefix(payload.Version, "2.") && !strings.HasPrefix(payload.Version, "3.") {
log.Error(fmt.Sprintf("unexpected version %s", payload.Version))
return JSONProblemf(c, http.StatusBadRequest, "BadRequest", "unsupported data client version: %s", payload.Version)
}

b, err := json.Marshal(payload)
if err != nil {
return JSONProblem(c, http.StatusInternalServerError, "Failed to re-encode config", err.Error())
}

reqCtx := c.Request().Context()

uuid := uuid.New().String()
idx := fmt.Sprintf("%s@%s@%s:%s", payload.Path, nodeID, ClusterID, uuid)

s := fmt.Sprintf("HSET %s %s", keyH, idx)
if _, err := a.Redis.HSet(reqCtx, keyH, idx, b).Result(); err != nil {
s = fmt.Sprintf("%s: %s", s, err)
log.Error(s)
return JSONProblem(c, http.StatusInternalServerError, "", s)
}

if err := a.pushNotPending(reqCtx, keyPendingH, keyQ, idx); err != nil {
log.Error(fmt.Sprintf("can't push %s %s: %s", keyQ, idx, err))
return JSONProblemf(c, http.StatusInternalServerError, "redis operation", "can't push %s %s: %s", keyQ, idx, err)
}

log.Debug("action begin accepted")
return c.JSON(http.StatusAccepted, api.ActionRequestAccepted{Uuid: uuid})
}
Loading
Loading