Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa1c87037b |
@@ -0,0 +1,46 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// An empty ApplyUpdatesCmd must stay an empty object on the wire, so an old
|
||||
// agent and a new server, or a new agent and an old server, agree that it
|
||||
// means "install everything, no reboot, no deadline".
|
||||
func TestApplyUpdatesCmdEmptyIsEmptyObject(t *testing.T) {
|
||||
b, err := json.Marshal(ApplyUpdatesCmd{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(b) != "{}" {
|
||||
t.Fatalf("got %s, want {}", b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchResultRoundTrip(t *testing.T) {
|
||||
in := AgentMessage{PatchResult: &PatchResult{
|
||||
CommandId: "c1", Status: PatchStatusOK, OutputTail: "done",
|
||||
PendingAfter: 0, RebootRequired: true, Rebooting: true,
|
||||
}}
|
||||
b, err := json.Marshal(in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var out AgentMessage
|
||||
if err := json.Unmarshal(b, &out); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.PatchResult == nil || *out.PatchResult != *in.PatchResult {
|
||||
t.Fatalf("round trip lost data: %+v", out.PatchResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInventoryBootTimeOnWire(t *testing.T) {
|
||||
b, _ := json.Marshal(InventoryReport{BootTimeUnix: 1757800000})
|
||||
var m map[string]any
|
||||
_ = json.Unmarshal(b, &m)
|
||||
if m["boot_time_unix"] != float64(1757800000) {
|
||||
t.Fatalf("boot_time_unix missing: %s", b)
|
||||
}
|
||||
}
|
||||
+36
-1
@@ -123,6 +123,7 @@ type InventoryReport struct {
|
||||
Partitions []PartitionReport `json:"partitions,omitempty"`
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
RebootRequired bool `json:"reboot_required,omitempty"`
|
||||
BootTimeUnix int64 `json:"boot_time_unix,omitempty"` // every report; proves a reboot happened
|
||||
}
|
||||
type InventoryReportResponse struct{}
|
||||
|
||||
@@ -161,7 +162,40 @@ type ReportChecksRequest struct {
|
||||
}
|
||||
type ReportChecksResponse struct{}
|
||||
|
||||
type ApplyUpdatesCmd struct{}
|
||||
// ApplyUpdatesCmd installs pending OS updates. The zero value means what the
|
||||
// command always meant: every pending update, no reboot, no deadline. That is
|
||||
// what keeps old servers and new agents, and new servers and old agents,
|
||||
// compatible - but only in that direction for Scope: an agent that predates
|
||||
// these fields installs everything even when asked for security only, which
|
||||
// is why the control plane gates on agent version before sending a scope.
|
||||
type ApplyUpdatesCmd struct {
|
||||
Scope string `json:"scope,omitempty"` // "" or PatchScopeAll | PatchScopeSecurity
|
||||
RebootIfRequired bool `json:"reboot_if_required,omitempty"` // reboot only if the OS reports one is owed
|
||||
DeadlineUnix int64 `json:"deadline_unix,omitempty"` // 0 = none; the agent caps the upgrade at 2h
|
||||
}
|
||||
|
||||
const (
|
||||
PatchScopeAll = "all"
|
||||
PatchScopeSecurity = "security"
|
||||
|
||||
PatchStatusOK = "ok"
|
||||
PatchStatusFailed = "failed"
|
||||
PatchStatusUnsupported = "unsupported"
|
||||
PatchStatusBusy = "busy"
|
||||
)
|
||||
|
||||
// PatchResult answers an ApplyUpdatesCmd. Rebooting is sent immediately before
|
||||
// the agent restarts the host, so the control plane knows to wait for a
|
||||
// post-boot inventory report rather than a second result.
|
||||
type PatchResult struct {
|
||||
CommandId string `json:"command_id"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
OutputTail string `json:"output_tail,omitempty"` // at most 64KB, newest bytes
|
||||
PendingAfter int32 `json:"pending_after"` // -1 when the post-apply check failed
|
||||
RebootRequired bool `json:"reboot_required,omitempty"`
|
||||
Rebooting bool `json:"rebooting,omitempty"`
|
||||
}
|
||||
|
||||
type OpenProxyCmd struct {
|
||||
ProxyId string `json:"proxy_id"`
|
||||
@@ -240,6 +274,7 @@ type AgentMessage struct {
|
||||
StepOutput *StepOutputChunk `json:"step_output,omitempty"`
|
||||
|
||||
WorkloadLogsResult *WorkloadLogsResult `json:"workload_logs_result,omitempty"`
|
||||
PatchResult *PatchResult `json:"patch_result,omitempty"`
|
||||
}
|
||||
|
||||
type AgentReady struct{}
|
||||
|
||||
@@ -109,6 +109,7 @@ message AgentMessage {
|
||||
StepResult step_result = 5;
|
||||
StepOutputChunk step_output = 6;
|
||||
WorkloadLogsResult workload_logs_result = 7;
|
||||
PatchResult patch_result = 8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,9 +169,9 @@ message InventoryReport {
|
||||
uint64 swap_used = 7;
|
||||
repeated PartitionReport partitions = 8;
|
||||
string kernel = 9;
|
||||
// Set on static snapshots only. The agent never reboots; it reports that one
|
||||
// is owed and leaves the decision to a person or a workflow.
|
||||
// Set on static snapshots only. The agent reboots a host only when an ApplyUpdatesCmd asks it to and the OS reports a reboot is owed.
|
||||
bool reboot_required = 10;
|
||||
int64 boot_time_unix = 11; // every report; proves a reboot happened
|
||||
}
|
||||
|
||||
message InventoryReportResponse {
|
||||
@@ -220,7 +221,19 @@ message ReportChecksResponse {
|
||||
}
|
||||
|
||||
message ApplyUpdatesCmd {
|
||||
string scope = 1; // "" or "all" | "security"
|
||||
bool reboot_if_required = 2; // reboot only if the OS reports one is owed
|
||||
int64 deadline_unix = 3; // 0 = none; the agent caps the upgrade at 2h
|
||||
}
|
||||
|
||||
message PatchResult {
|
||||
string command_id = 1;
|
||||
string status = 2; // ok | failed | unsupported | busy
|
||||
string message = 3;
|
||||
string output_tail = 4; // at most 64KB, newest bytes kept
|
||||
int32 pending_after = 5; // -1 when the post-apply check failed
|
||||
bool reboot_required = 6;
|
||||
bool rebooting = 7; // sent just before the agent reboots itself
|
||||
}
|
||||
|
||||
message ServerCommand {
|
||||
|
||||
Reference in New Issue
Block a user