Skip to content

feat(agent): run agent.update and agent.restart one time only - #34

Merged
nabil1440 merged 3 commits into
agent/28-metricsfrom
agent/29-commands
Sep 28, 2026
Merged

nabil1440 merged 3 commits into
agent/28-metricsfrom
agent/29-commands

Conversation

@nabil1440

@nabil1440 nabil1440 commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Layer 4 of 7 of the monitoring agent (#31 → #37).

Summary

  • This PR lets FlyWP update and restart the agent without SSH.
  • The agent asks for commands after each report, and keeps a list of the commands that it ran. It does not run a command two times.
  • For an update, the agent downloads the release and examines its sha256. If the sha256 is not correct, the old binary continues.
  • The agent replaces its binary and stops. systemd starts the new binary, and the new process sends the result.
  • The agent does not run a command that it does not know. The README states the contract version: v0.2.1.

Change

  • internal/agent/commands.go: the poll, the list of the commands that ran (ran.json, 48 hours), agent.restart, agent.update and command.unknown.
  • internal/release: the update code of fly update moved here from internal/utils, with Download (https, sha256, size limit) and Install.
  • README: the pin line and a section about the agent.

Adversarial review

The first version was refuted. These items are fixed in this PR:

  • agent.update never downgrades (maintainer decision). The same version sends command.completed. An older target sends command.failed with the reason, so the control plane sees that its version was not installed. A bad release is fixed with a newer release.
  • Versions compare with semver. Two dev tags of one release, or a version that is not semver, have no order: then only the exact version skips the update.
  • A download follows a redirect only to https.
  • At start, the agent removes old downloads that a crash left.
  • The new binary is made executable through the open file, and it is synced to the disk before and after the rename.

Tests

  • Under testing/synctest: a restart runs one time also when the command stays open, no downgrade (release, dev tag), an update from an older or unordered version, a failed update, the result from the new process, an unknown verb, a list that cannot be saved.
  • End-to-end: the real binary downloads a new build, checks its sha256, replaces itself, and the new process sends command.completed.

Closes #29

@nabil1440
nabil1440 added this pull request to stack #38 September 22, 2026 10:40
@nabil1440 nabil1440 self-assigned this Sep 22, 2026
@nabil1440 nabil1440 changed the title agent/29 commands feat(agent): run agent.update and agent.restart one time only Sep 22, 2026
- Poll GET /agent/v1/commands after each report, and run the new commands
  one at a time, oldest first. Send the results at once.
- Keep a list of the commands that ran (ran.json, 48 hours) and skip them:
  the poll sends each open command again until its result arrives.
- agent.restart: record the command, then exit; systemd starts the agent
  again, and the new process sends command.completed.
- agent.update: skip the download when the agent already runs the target
  (or a newer release). Else download the archive next to the binary,
  compare its sha256, and put the new binary in place with a rename. A
  failure sends command.failed and keeps the old binary. After the exit,
  the new process compares its version with the target and sends the result.
- A dev tag (v0.2.0-dev.<sha>) matches only the same tag: dev tags have no
  order.
- Do not run an unknown verb; send command.unknown.
- Move the update code of fly update to internal/release, and add Download
  and Install for the agent.
- README: the contract pin line and the monitoring agent section.

Refs #29
… safely

Fixes from the adversarial review of this layer.

- agent.update skips the download only when the agent runs exactly the
  target version. Before, an older target reported command.completed and
  installed nothing, so a rollback looked done. The control plane decides
  the version; after the update, a newer release still completes it.
- An update download follows a redirect only to https (or loopback).
- At start, remove downloads that a crash left next to the binary, when
  they are older than one hour.
- Make the new binary executable through the open file, not through its
  path: the directory can belong to an other user. Sync the binary and the
  directory, so a power loss cannot leave an empty binary.

Refs #29
Maintainer decision: when the agent already runs the target version or a
newer one, it does not update.

- The same version sends command.completed, as before.
- An older target sends command.failed with the reason ("the agent runs
  v0.2.1, newer than v0.2.0; it does not downgrade"), so the control plane
  sees that its version was not installed. A bad release is fixed with a
  newer release; an older version needs the install job.
- Versions compare with semver. Two dev tags of one release
  (v0.2.0-dev.<sha>) have no order, and a version that is not semver has no
  order: then only the exact version skips the update.
- The new process after an update uses the same comparison for its result.

Refs #29
@nabil1440
nabil1440 merged commit 6871233 into develop Sep 28, 2026
1 of 2 checks passed
@nabil1440
nabil1440 deleted the agent/29-commands branch September 28, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enhancement: Run agent.update and agent.restart one time only

1 participant