mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
parent
e7334e66e4
commit
926c6bd433
4 changed files with 52 additions and 30 deletions
|
|
@ -269,9 +269,12 @@ process or unit may seed later recovery attempts, but it must not be logged or
|
|||
treated as recovered update state. That fallback must still run when an
|
||||
operator supplies the update URL explicitly but token, identity, feature-flag,
|
||||
or trust continuity remains recoverable only from a legacy v5 process or
|
||||
service. Windows stale-agent update commands remain on the existing token-gated
|
||||
install transport until the Windows installer owns an equivalent saved-state
|
||||
update mode.
|
||||
service. Because v5.1.x agents were launched by Go flag parsing, that legacy
|
||||
fallback must treat single-dash and double-dash agent flag spellings as the
|
||||
same recovered state while preserving the same fail-closed URL-plus-token
|
||||
threshold. Windows stale-agent update commands remain on the existing
|
||||
token-gated install transport until the Windows installer owns an equivalent
|
||||
saved-state update mode.
|
||||
Agent Fleet Doctor diagnostics extend that same read-only lifecycle triage
|
||||
surface: `GET /api/agents/diagnostics` may explain stale versions, missing
|
||||
reports, profile deployment drift, expected Docker/Kubernetes telemetry gaps,
|
||||
|
|
@ -1354,7 +1357,7 @@ surface and no new `internal/api/` lifecycle handler.
|
|||
|
||||
1. Update this contract when agent lifecycle ownership changes. Routes added under the shared `internal/api/` extension point that are clearly outside lifecycle ownership (for example `POST /api/ai/patrol/preflight`, the `patrol_preflight` snapshot field added to `/api/settings/ai`, the auto-trigger preflight dispatch on settings save, the startup-seed dispatch in `NewAISettingsHandler`, and the cached-preflight integration into the Patrol `tools` readiness check — all owned by ai-runtime) do not extend this subsystem's contract; they live in their owning subsystem.
|
||||
2. Keep shared API proof routing aligned whenever install, register, or profile payloads change.
|
||||
3. Update runtime and settings tests in the same slice when lifecycle behavior changes. Shell installer lifecycle changes must keep `scripts/installtests/install_sh_test.go` covering explicit flags, persisted connection state, legacy running-process/service recovery, and secure token-file service argument rendering for update re-entry.
|
||||
3. Update runtime and settings tests in the same slice when lifecycle behavior changes. Shell installer lifecycle changes must keep `scripts/installtests/install_sh_test.go` covering explicit flags, persisted connection state, legacy running-process/service recovery, legacy single-dash v5 agent flag recovery, and secure token-file service argument rendering for update re-entry.
|
||||
4. Keep host-agent test hooks, command-client factories, and timing overrides
|
||||
instance-scoped under `internal/hostagent/agent.go`; lifecycle-owned
|
||||
registration and update paths must not depend on package-global mutable test
|
||||
|
|
|
|||
|
|
@ -279,7 +279,10 @@ TLS floor in the dynamic config.
|
|||
raw token in process arguments. That fallback remains required when the
|
||||
operator supplies `--url` on the update command but token, identity,
|
||||
feature-flag, or trust continuity still exists only in legacy process or
|
||||
service state.
|
||||
service state. Because v5.1.x agents used Go's single-dash flag spelling,
|
||||
the installer-owned recovery path must accept both single-dash and
|
||||
double-dash forms for recovered agent args without weakening the existing
|
||||
missing-state failure behavior.
|
||||
The shell installer must disclose `--enable-commands` as Pulse command
|
||||
execution, disabled by default, and must name both Patrol actions and
|
||||
Proxmox LXC Docker inventory as the operator-visible reasons to enable it.
|
||||
|
|
@ -732,7 +735,7 @@ TLS floor in the dynamic config.
|
|||
|
||||
1. Update this contract when canonical deployment or installer entry points move
|
||||
2. Keep deployment runtime and shared API proof routing aligned in `registry.json`
|
||||
3. Preserve explicit coverage for installer parity, update planning, and deployment bootstrap behavior when these surfaces change. Shell installer update recovery changes must keep `scripts/installtests/install_sh_test.go` covering both persisted `connection.env` recovery and legacy running-process/service recovery, including the rule that upgraded service args use `--token-file` instead of raw `--token`.
|
||||
3. Preserve explicit coverage for installer parity, update planning, and deployment bootstrap behavior when these surfaces change. Shell installer update recovery changes must keep `scripts/installtests/install_sh_test.go` covering both persisted `connection.env` recovery and legacy running-process/service recovery, including single-dash v5 agent flags and the rule that upgraded service args use `--token-file` instead of raw `--token`.
|
||||
4. Keep stable and prerelease packet lineage explicit when `docs/releases/` or
|
||||
`VERSION` changes: preserve already-shipped RC packets under dedicated
|
||||
historical filenames before reusing canonical stable names, keep
|
||||
|
|
|
|||
|
|
@ -1524,10 +1524,19 @@ strip_recovered_arg_quotes() {
|
|||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
normalize_recovered_agent_arg_key() {
|
||||
local key="$1"
|
||||
|
||||
key="${key#--}"
|
||||
key="${key#-}"
|
||||
printf '%s\n' "$key"
|
||||
}
|
||||
|
||||
apply_recovered_agent_arg_value() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
|
||||
key=$(normalize_recovered_agent_arg_key "$key")
|
||||
value=$(strip_recovered_arg_quotes "$value")
|
||||
|
||||
case "$key" in
|
||||
|
|
@ -1615,81 +1624,81 @@ recover_connection_state_from_arg_stream() {
|
|||
fi
|
||||
|
||||
case "$arg" in
|
||||
--url|--pulse-url|--token|--token-file|--interval|--agent-id|--hostname|--cacert|--health-addr|--state-dir|--kubeconfig|--proxmox-type|--disk-exclude)
|
||||
pending_key="${arg#--}"
|
||||
--url|--pulse-url|--token|--token-file|--interval|--agent-id|--hostname|--cacert|--health-addr|--state-dir|--kubeconfig|--proxmox-type|--disk-exclude|-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-cacert|-health-addr|-state-dir|-kubeconfig|-proxmox-type|-disk-exclude)
|
||||
pending_key=$(normalize_recovered_agent_arg_key "$arg")
|
||||
;;
|
||||
--url=*|--pulse-url=*|--token=*|--token-file=*|--interval=*|--agent-id=*|--hostname=*|--cacert=*|--health-addr=*|--state-dir=*|--kubeconfig=*|--proxmox-type=*|--disk-exclude=*)
|
||||
--url=*|--pulse-url=*|--token=*|--token-file=*|--interval=*|--agent-id=*|--hostname=*|--cacert=*|--health-addr=*|--state-dir=*|--kubeconfig=*|--proxmox-type=*|--disk-exclude=*|-url=*|-pulse-url=*|-token=*|-token-file=*|-interval=*|-agent-id=*|-hostname=*|-cacert=*|-health-addr=*|-state-dir=*|-kubeconfig=*|-proxmox-type=*|-disk-exclude=*)
|
||||
key="${arg%%=*}"
|
||||
value="${arg#*=}"
|
||||
apply_recovered_agent_arg_value "${key#--}" "$value"
|
||||
apply_recovered_agent_arg_value "$key" "$value"
|
||||
;;
|
||||
--enable-host|--enable-host=true)
|
||||
--enable-host|-enable-host|--enable-host=true|-enable-host=true)
|
||||
if [[ "$HOST_EXPLICIT" != "true" ]]; then ENABLE_HOST="true"; fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-host=false|--disable-host)
|
||||
--enable-host=false|-enable-host=false|--disable-host|-disable-host)
|
||||
if [[ "$HOST_EXPLICIT" != "true" ]]; then ENABLE_HOST="false"; fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-docker|--enable-docker=true)
|
||||
--enable-docker|-enable-docker|--enable-docker=true|-enable-docker=true)
|
||||
if [[ "$DOCKER_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_DOCKER="true"
|
||||
DOCKER_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-docker=false|--disable-docker)
|
||||
--enable-docker=false|-enable-docker=false|--disable-docker|-disable-docker)
|
||||
if [[ "$DOCKER_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_DOCKER="false"
|
||||
DOCKER_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-kubernetes|--enable-kubernetes=true)
|
||||
--enable-kubernetes|-enable-kubernetes|--enable-kubernetes=true|-enable-kubernetes=true)
|
||||
if [[ "$KUBERNETES_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_KUBERNETES="true"
|
||||
KUBERNETES_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-kubernetes=false|--disable-kubernetes)
|
||||
--enable-kubernetes=false|-enable-kubernetes=false|--disable-kubernetes|-disable-kubernetes)
|
||||
if [[ "$KUBERNETES_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_KUBERNETES="false"
|
||||
KUBERNETES_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-proxmox|--enable-proxmox=true)
|
||||
--enable-proxmox|-enable-proxmox|--enable-proxmox=true|-enable-proxmox=true)
|
||||
if [[ "$PROXMOX_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_PROXMOX="true"
|
||||
PROXMOX_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-proxmox=false|--disable-proxmox)
|
||||
--enable-proxmox=false|-enable-proxmox=false|--disable-proxmox|-disable-proxmox)
|
||||
if [[ "$PROXMOX_EXPLICIT" != "true" ]]; then
|
||||
ENABLE_PROXMOX="false"
|
||||
PROXMOX_EXPLICIT="true"
|
||||
fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--insecure)
|
||||
--insecure|-insecure)
|
||||
INSECURE="true"
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enable-commands)
|
||||
--enable-commands|-enable-commands)
|
||||
ENABLE_COMMANDS="true"
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--enroll)
|
||||
--enroll|-enroll)
|
||||
ENROLL="true"
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--kube-include-all-pods)
|
||||
--kube-include-all-pods|-kube-include-all-pods)
|
||||
KUBE_INCLUDE_ALL_PODS="true"
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
--kube-include-all-deployments)
|
||||
--kube-include-all-deployments|-kube-include-all-deployments)
|
||||
KUBE_INCLUDE_ALL_DEPLOYMENTS="true"
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -644,6 +644,9 @@ func TestInstallSHSupportsSavedStateUpdateMode(t *testing.T) {
|
|||
`recover_connection_state_from_running_agent`,
|
||||
`recover_connection_state_from_systemd_unit`,
|
||||
`recover_connection_state_from_arg_stream`,
|
||||
`normalize_recovered_agent_arg_key() {`,
|
||||
`-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-cacert|-health-addr|-state-dir|-kubeconfig|-proxmox-type|-disk-exclude)`,
|
||||
`--enable-host|-enable-host|--enable-host=true|-enable-host=true)`,
|
||||
`recover_connection_state_from_env_stream`,
|
||||
`recovered_connection_state_ready() {`,
|
||||
`update_connection_state_incomplete() {`,
|
||||
|
|
@ -696,6 +699,7 @@ func TestInstallSHRecoversV5ProcessArgsForSavedStateUpdate(t *testing.T) {
|
|||
DISK_EXCLUDES=()
|
||||
RUNTIME_TOKEN_FILE="/var/lib/pulse-agent/token"
|
||||
` + extractInstallShellFunction(t, "strip_recovered_arg_quotes") + `
|
||||
` + extractInstallShellFunction(t, "normalize_recovered_agent_arg_key") + `
|
||||
` + extractInstallShellFunction(t, "apply_recovered_agent_arg_value") + `
|
||||
` + extractInstallShellFunction(t, "recovered_connection_state_ready") + `
|
||||
` + extractInstallShellFunction(t, "recover_connection_state_from_arg_stream") + `
|
||||
|
|
@ -778,6 +782,7 @@ func TestInstallSHRejectsPartialRecoveredProcessConnectionState(t *testing.T) {
|
|||
KUBE_INCLUDE_ALL_DEPLOYMENTS="false"
|
||||
DISK_EXCLUDES=()
|
||||
` + extractInstallShellFunction(t, "strip_recovered_arg_quotes") + `
|
||||
` + extractInstallShellFunction(t, "normalize_recovered_agent_arg_key") + `
|
||||
` + extractInstallShellFunction(t, "apply_recovered_agent_arg_value") + `
|
||||
` + extractInstallShellFunction(t, "recovered_connection_state_ready") + `
|
||||
` + extractInstallShellFunction(t, "recover_connection_state_from_arg_stream") + `
|
||||
|
|
@ -845,6 +850,7 @@ func TestInstallSHCombinesRecoveredProcessArgsAndEnvConnectionState(t *testing.T
|
|||
KUBE_INCLUDE_ALL_DEPLOYMENTS="false"
|
||||
DISK_EXCLUDES=()
|
||||
` + extractInstallShellFunction(t, "strip_recovered_arg_quotes") + `
|
||||
` + extractInstallShellFunction(t, "normalize_recovered_agent_arg_key") + `
|
||||
` + extractInstallShellFunction(t, "apply_recovered_agent_arg_value") + `
|
||||
` + extractInstallShellFunction(t, "recovered_connection_state_ready") + `
|
||||
` + extractInstallShellFunction(t, "recover_connection_state_from_arg_stream") + `
|
||||
|
|
@ -920,6 +926,7 @@ func TestInstallSHUpdateModeMergesExplicitURLWithRunningV5ProcessState(t *testin
|
|||
DISK_EXCLUDES=()
|
||||
RUNTIME_TOKEN_FILE="/var/lib/pulse-agent/token"
|
||||
` + extractInstallShellFunction(t, "strip_recovered_arg_quotes") + `
|
||||
` + extractInstallShellFunction(t, "normalize_recovered_agent_arg_key") + `
|
||||
` + extractInstallShellFunction(t, "apply_recovered_agent_arg_value") + `
|
||||
` + extractInstallShellFunction(t, "recovered_connection_state_ready") + `
|
||||
` + extractInstallShellFunction(t, "update_connection_state_incomplete") + `
|
||||
|
|
@ -932,17 +939,17 @@ func TestInstallSHUpdateModeMergesExplicitURLWithRunningV5ProcessState(t *testin
|
|||
recover_connection_state_from_existing_agent() {
|
||||
recover_connection_state_from_arg_stream <<'ARGS'
|
||||
/usr/local/bin/pulse-agent
|
||||
--url
|
||||
-url
|
||||
http://192.168.2.96:7655
|
||||
--token
|
||||
-token
|
||||
deadbeef
|
||||
--interval
|
||||
-interval
|
||||
30s
|
||||
--enable-host
|
||||
--enable-docker
|
||||
--agent-id
|
||||
-enable-host
|
||||
-enable-docker
|
||||
-agent-id
|
||||
machine-1
|
||||
--hostname
|
||||
-hostname
|
||||
docker1
|
||||
ARGS
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue