This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package meta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"nadir/internal/oscmd"
|
||||
|
||||
"github.com/danielgtaylor/huma/v2"
|
||||
)
|
||||
|
||||
// RegisterUpdate wires POST /api/meta/update. It runs the equivalent of
|
||||
// `sudo nadir update` in a detached session and returns 202 immediately; the
|
||||
// systemctl restart that ends the updater drops in-flight connections, so the
|
||||
// caller should poll /api/health to confirm the new version is up.
|
||||
//
|
||||
// Authorization: requires (meta, root). Only roles with a wildcard grant
|
||||
// (the default admin role) match, since "meta" isn't a real module with a
|
||||
// declared permission vocabulary.
|
||||
func RegisterUpdate(api huma.API) {
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "meta-update",
|
||||
Method: "POST",
|
||||
Path: "/api/update",
|
||||
Summary: "Update nadir to the latest release",
|
||||
Description: "Equivalent to running `sudo nadir update` on the host: queries server.release_repo for the latest release, downloads the binary matching the host's architecture, atomically replaces the running binary, and restarts the systemd unit. Returns 202 immediately; the service restart drops in-flight connections, so poll /api/health to confirm the new version is up. Requires the wildcard admin role.",
|
||||
Tags: []string{"Meta"},
|
||||
Metadata: map[string]any{"module": "meta", "permission": "root"},
|
||||
Errors: []int{401, 403, 500},
|
||||
DefaultStatus: 202,
|
||||
}, func(ctx context.Context, _ *struct{}) (*oscmd.StatusOutput, error) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, huma.Error500InternalServerError("could not resolve own binary path", err)
|
||||
}
|
||||
cmd := exec.Command(exe, "update")
|
||||
// Detach from the server's process group so `systemctl restart nadir`
|
||||
// (the final step of `nadir update`) doesn't kill its own updater.
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, huma.Error500InternalServerError("could not start updater", err)
|
||||
}
|
||||
return oscmd.OK(), nil
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user