mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
Let --report-ip lead host identity and pass it through the installer
An explicit --report-ip is the user naming the primary address on a multi-NIC host, but identityFromHost appended it after the auto-detected interface addresses while every consumer of ResourceIdentity.IPAddresses treats the first entry as primary, so the override never changed what the Machines table displayed. Prepend it instead. The install script also rejected --report-ip as an unknown argument even though the agent supports the flag, forcing hand edits to the service unit that a later --update run would drop. Accept the flag, render it into the service ExecStart, persist it in connection state, and recognise it during saved-state and arg-stream recovery so updates preserve it. Refs #829 Contract-Neutral: behavioral fix: user-specified report-ip leads host identity addresses and the installer passes --report-ip through; no public contract change (#829)
This commit is contained in:
parent
b853638980
commit
f8c5c55d11
5 changed files with 47 additions and 4 deletions
|
|
@ -93,7 +93,10 @@ func resourceFromProxmoxNode(node models.Node, linkedHost *models.Host) (Resourc
|
|||
func identityFromHost(host models.Host) ResourceIdentity {
|
||||
ips, macs := collectInterfaceIDs(host.NetworkInterfaces)
|
||||
if host.ReportIP != "" {
|
||||
ips = append(ips, host.ReportIP)
|
||||
// --report-ip is the user naming the primary address on a multi-NIC
|
||||
// host, and consumers treat the first entry as primary, so it must
|
||||
// lead the list rather than trail the auto-detected ones (#829).
|
||||
ips = append([]string{host.ReportIP}, ips...)
|
||||
}
|
||||
|
||||
return ResourceIdentity{
|
||||
|
|
|
|||
|
|
@ -1752,6 +1752,22 @@ func TestCollectInterfaceIDsOrdersPhysicalInterfacesFirst(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestIdentityFromHostReportIPLeadsAddresses(t *testing.T) {
|
||||
host := models.Host{
|
||||
Hostname: "multi-nic",
|
||||
ReportIP: "192.168.1.9",
|
||||
NetworkInterfaces: []models.HostNetworkInterface{
|
||||
{Name: "eth0", Addresses: []string{"2.2.2.10/24"}},
|
||||
{Name: "eth1", Addresses: []string{"192.168.1.9/24"}},
|
||||
},
|
||||
}
|
||||
|
||||
identity := identityFromHost(host)
|
||||
if len(identity.IPAddresses) == 0 || identity.IPAddresses[0] != "192.168.1.9" {
|
||||
t.Fatalf("expected --report-ip to lead identity addresses, got %v", identity.IPAddresses)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectInterfaceIDsAllVirtualStillCollects(t *testing.T) {
|
||||
interfaces := []models.HostNetworkInterface{
|
||||
{Name: "docker0", Addresses: []string{"172.17.0.1/16"}},
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ SERVER_FINGERPRINT="${PULSE_SERVER_FINGERPRINT:-}"
|
|||
OBSERVERS_FILE="${PULSE_OBSERVERS_FILE:-}"
|
||||
AGENT_ID=""
|
||||
HOSTNAME_OVERRIDE=""
|
||||
REPORT_IP=""
|
||||
ENABLE_COMMANDS="false"
|
||||
HEALTH_ADDR="${PULSE_HEALTH_ADDR:-}"
|
||||
HEALTH_ADDR_SET="false"
|
||||
|
|
@ -331,6 +332,7 @@ Options:
|
|||
--enable-proxmox Force enable Proxmox integration
|
||||
--agent-id <id> Custom agent identifier
|
||||
--hostname <name> Override hostname reported to Pulse
|
||||
--report-ip <ip> IP address to report to Pulse (for multi-NIC systems)
|
||||
--state-dir <path> Override persistent state directory
|
||||
--disk-exclude <path> Exclude mount point (repeatable)
|
||||
--insecure Skip TLS verification (auto-enabled for http:// URLs)
|
||||
|
|
@ -1530,6 +1532,7 @@ build_exec_arg_items() {
|
|||
if [[ "$KUBE_INCLUDE_ALL_DEPLOYMENTS" == "true" ]]; then EXEC_ARG_ITEMS+=(--kube-include-all-deployments); fi
|
||||
if [[ -n "$AGENT_ID" ]]; then EXEC_ARG_ITEMS+=(--agent-id "$AGENT_ID"); fi
|
||||
if [[ -n "$HOSTNAME_OVERRIDE" ]]; then EXEC_ARG_ITEMS+=(--hostname "$HOSTNAME_OVERRIDE"); fi
|
||||
if [[ -n "$REPORT_IP" ]]; then EXEC_ARG_ITEMS+=(--report-ip "$REPORT_IP"); fi
|
||||
if [[ -n "$STATE_DIR" ]]; then EXEC_ARG_ITEMS+=(--state-dir "$STATE_DIR"); fi
|
||||
# Add disk exclude patterns (use ${arr[@]+"${arr[@]}"} for bash 3.2 compatibility with set -u)
|
||||
for pattern in ${DISK_EXCLUDES[@]+"${DISK_EXCLUDES[@]}"}; do
|
||||
|
|
@ -1749,6 +1752,9 @@ recover_connection_state() {
|
|||
if [[ -z "$HOSTNAME_OVERRIDE" ]]; then
|
||||
HOSTNAME_OVERRIDE=$(read_connection_state_value "$file" "PULSE_HOSTNAME")
|
||||
fi
|
||||
if [[ -z "$REPORT_IP" ]]; then
|
||||
REPORT_IP=$(read_connection_state_value "$file" "PULSE_REPORT_IP")
|
||||
fi
|
||||
if [[ "$INSECURE" != "true" ]]; then
|
||||
local saved_insecure=""
|
||||
saved_insecure=$(read_connection_state_value "$file" "PULSE_INSECURE_SKIP_VERIFY")
|
||||
|
|
@ -1817,6 +1823,10 @@ apply_recovered_agent_arg_value() {
|
|||
if [[ -z "$HOSTNAME_OVERRIDE" ]]; then HOSTNAME_OVERRIDE="$value"; fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
report-ip)
|
||||
if [[ -z "$REPORT_IP" ]]; then REPORT_IP="$value"; fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
;;
|
||||
cacert)
|
||||
if [[ -z "$CURL_CA_BUNDLE" ]]; then CURL_CA_BUNDLE="$value"; fi
|
||||
RECOVERED_AGENT_ARG_STATE="true"
|
||||
|
|
@ -1888,10 +1898,10 @@ recover_connection_state_from_arg_stream() {
|
|||
fi
|
||||
|
||||
case "$arg" in
|
||||
--url|--pulse-url|--token|--token-file|--interval|--agent-id|--hostname|--cacert|--server-fingerprint|--observers-file|--health-addr|--state-dir|--kubeconfig|--proxmox-type|--disk-exclude|-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-cacert|-server-fingerprint|-observers-file|-health-addr|-state-dir|-kubeconfig|-proxmox-type|-disk-exclude)
|
||||
--url|--pulse-url|--token|--token-file|--interval|--agent-id|--hostname|--report-ip|--cacert|--server-fingerprint|--observers-file|--health-addr|--state-dir|--kubeconfig|--proxmox-type|--disk-exclude|-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-report-ip|-cacert|-server-fingerprint|-observers-file|-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=*|--server-fingerprint=*|--observers-file=*|--health-addr=*|--state-dir=*|--kubeconfig=*|--proxmox-type=*|--disk-exclude=*|-url=*|-pulse-url=*|-token=*|-token-file=*|-interval=*|-agent-id=*|-hostname=*|-cacert=*|-server-fingerprint=*|-observers-file=*|-health-addr=*|-state-dir=*|-kubeconfig=*|-proxmox-type=*|-disk-exclude=*)
|
||||
--url=*|--pulse-url=*|--token=*|--token-file=*|--interval=*|--agent-id=*|--hostname=*|--report-ip=*|--cacert=*|--server-fingerprint=*|--observers-file=*|--health-addr=*|--state-dir=*|--kubeconfig=*|--proxmox-type=*|--disk-exclude=*|-url=*|-pulse-url=*|-token=*|-token-file=*|-interval=*|-agent-id=*|-hostname=*|-report-ip=*|-cacert=*|-server-fingerprint=*|-observers-file=*|-health-addr=*|-state-dir=*|-kubeconfig=*|-proxmox-type=*|-disk-exclude=*)
|
||||
key="${arg%%=*}"
|
||||
value="${arg#*=}"
|
||||
apply_recovered_agent_arg_value "$key" "$value"
|
||||
|
|
@ -2021,6 +2031,11 @@ recover_connection_state_from_env_stream() {
|
|||
if [[ -z "$HOSTNAME_OVERRIDE" ]]; then HOSTNAME_OVERRIDE="$value"; fi
|
||||
RECOVERED_AGENT_ENV_STATE="true"
|
||||
;;
|
||||
PULSE_REPORT_IP=*)
|
||||
value="${env_line#*=}"
|
||||
if [[ -z "$REPORT_IP" ]]; then REPORT_IP="$value"; fi
|
||||
RECOVERED_AGENT_ENV_STATE="true"
|
||||
;;
|
||||
PULSE_INSECURE_SKIP_VERIFY=true)
|
||||
INSECURE="true"
|
||||
RECOVERED_AGENT_ENV_STATE="true"
|
||||
|
|
@ -2409,6 +2424,7 @@ save_connection_info() {
|
|||
write_connection_state_value "$conn_tmp" "PULSE_TOKEN_FILE" "$RUNTIME_TOKEN_FILE"
|
||||
write_connection_state_value "$conn_tmp" "PULSE_AGENT_ID" "$AGENT_ID"
|
||||
write_connection_state_value "$conn_tmp" "PULSE_HOSTNAME" "$HOSTNAME_OVERRIDE"
|
||||
write_connection_state_value "$conn_tmp" "PULSE_REPORT_IP" "$REPORT_IP"
|
||||
if [[ "$INSECURE" == "true" ]]; then
|
||||
write_connection_state_value "$conn_tmp" "PULSE_INSECURE_SKIP_VERIFY" "true"
|
||||
fi
|
||||
|
|
@ -2477,6 +2493,7 @@ while [[ $# -gt 0 ]]; do
|
|||
--uninstall) UNINSTALL="true"; shift ;;
|
||||
--agent-id) AGENT_ID="$2"; shift 2 ;;
|
||||
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
|
||||
--report-ip) REPORT_IP="$2"; shift 2 ;;
|
||||
--state-dir) STATE_DIR="$2"; STATE_DIR_SOURCE="explicit"; shift 2 ;;
|
||||
--kube-include-all-pods) KUBE_INCLUDE_ALL_PODS="true"; shift ;;
|
||||
--kube-include-all-deployments) KUBE_INCLUDE_ALL_DEPLOYMENTS="true"; shift ;;
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ func renderLifecycleService(t *testing.T, stateDir, stateSource, unitPath, pulse
|
|||
PULSE_TOKEN=""
|
||||
AGENT_ID=""
|
||||
HOSTNAME_OVERRIDE=""
|
||||
REPORT_IP=""
|
||||
INSECURE="false"
|
||||
SERVER_FINGERPRINT=""
|
||||
CURL_CA_BUNDLE=""
|
||||
|
|
@ -211,6 +212,7 @@ func renderLifecycleService(t *testing.T, stateDir, stateSource, unitPath, pulse
|
|||
KUBE_INCLUDE_ALL_DEPLOYMENTS="false"
|
||||
AGENT_ID=""
|
||||
HOSTNAME_OVERRIDE="state-lifecycle-host"
|
||||
REPORT_IP=""
|
||||
DISK_EXCLUDES=()
|
||||
CURL_CA_BUNDLE=""
|
||||
RUNTIME_TOKEN_FILE=""
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ func TestInstallSHSupportsSavedStateUpdateMode(t *testing.T) {
|
|||
`recover_connection_state_from_arg_stream`,
|
||||
`recover_token_from_default_agent_token_file() {`,
|
||||
`normalize_recovered_agent_arg_key() {`,
|
||||
`-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-cacert|-server-fingerprint|-observers-file|-health-addr|-state-dir|-kubeconfig|-proxmox-type|-disk-exclude)`,
|
||||
`-url|-pulse-url|-token|-token-file|-interval|-agent-id|-hostname|-report-ip|-cacert|-server-fingerprint|-observers-file|-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() {`,
|
||||
|
|
@ -2582,6 +2582,7 @@ func TestInstallSHConnectionEnvPersistsCanonicalStateDirWithoutTokenValue(t *tes
|
|||
RUNTIME_TOKEN_FILE="$STATE_DIR/token"
|
||||
AGENT_ID="agent-custom"
|
||||
HOSTNAME_OVERRIDE="host-custom"
|
||||
REPORT_IP="192.168.1.9"
|
||||
INSECURE="false"
|
||||
SERVER_FINGERPRINT=""
|
||||
CURL_CA_BUNDLE=""
|
||||
|
|
@ -2601,6 +2602,9 @@ func TestInstallSHConnectionEnvPersistsCanonicalStateDirWithoutTokenValue(t *tes
|
|||
!strings.Contains(got, "PULSE_TOKEN_FILE='"+filepath.Join(stateDir, "token")+"'") {
|
||||
t.Fatalf("connection.env did not persist canonical state paths:\n%s", got)
|
||||
}
|
||||
if !strings.Contains(got, "PULSE_REPORT_IP='192.168.1.9'") {
|
||||
t.Fatalf("connection.env did not persist the report IP:\n%s", got)
|
||||
}
|
||||
if strings.Contains(got, "PULSE_TOKEN='") || strings.Contains(got, "deadbeef") {
|
||||
t.Fatalf("connection.env leaked the token value:\n%s", got)
|
||||
}
|
||||
|
|
@ -2643,6 +2647,7 @@ func TestInstallSHStateWritesReplaceSymlinksAtomically(t *testing.T) {
|
|||
ENROLL="false"
|
||||
AGENT_ID="agent-one"
|
||||
HOSTNAME_OVERRIDE="host-one"
|
||||
REPORT_IP=""
|
||||
INSECURE="false"
|
||||
SERVER_FINGERPRINT=""
|
||||
CURL_CA_BUNDLE=""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue