Merged
Conversation
Walk the delegation chain from targets.json when a delegations block is present: fetch each delegation file from metadata/delegations/<name>.json, verify its hash/length against snapshot.json, verify its signature against the content key declared in the delegation keys map, then merge the delegated targets into the download set. Old flat-targets repos (no delegations block) continue to work unchanged.
Passing true to cargo_build_tosource ensures generated .rs files are formatted consistently, preventing them from appearing as modified after every cargo build.
Yocto builds do not have rustfmt available as a build-time tool, causing build-script-build to fail. cargo fmt --check runs before cargo build in CI so the committed formatted files are checked correctly regardless.
- perform_update gains auth_token: Option<&str>; all HTTP fetches (metadata, delegations, targets) use a make_request helper that injects Authorization: Bearer when a token is present - varlink AddFromUrl(url, authToken: ?string) — existing callers omitting authToken get None → plain HTTP unchanged - CLI runtime add reads AVOCADO_TUF_AUTH_TOKEN env var (keeps JWT out of process listings) - Sideload path (avocado deploy, no env var) is unaffected
…lvable generic RequestBuilder<B> requires an explicit type parameter in ureq 3.x. Inline the auth header match directly in fetch_url and fetch_url_bytes to let the compiler infer the body type from context.
cargo build regenerates these from the .varlink schema files (rustfmt=false).
All avocadoctl commands (ext, hitl, runtime, root-authority, and top-level aliases) now connect to the running varlink daemon socket and forward requests as RPC calls, rather than calling service functions directly. This ensures concurrent CLI invocations are queued and serialised by the daemon, preventing race conditions when multiple processes attempt to modify system state (merge extensions, activate runtimes, etc.) simultaneously. Changes: - src/config.rs: add optional `avocado.socket` config key; add Config::socket_address() helper (default: unix:/run/avocado/avocadoctl.sock) - src/varlink_client.rs (new): connect_or_exit(), exit_with_rpc_error(), and output-formatting helpers for all four varlink interfaces - src/main.rs: add --socket global flag; dispatch all commands through the generated VarlinkClient types; keep `serve` as a direct path (it starts the daemon); add AVOCADO_TEST_MODE bypass (handle_direct) so existing integration tests with mock executables continue to work without a live daemon - tests/ext_integration_tests.rs: add AVOCADO_TEST_MODE=1 to three tests that were invoking the CLI without it - tests/varlink_interface_tests.rs (new): 8 integration tests that start a real daemon on a temp socket and exercise the full varlink client→daemon→service path, including a concurrent-requests test and a no-daemon error-message test
avocado-extension.service and avocado-extension-initrd.service call avocadoctl refresh/unmerge, which now route through the varlink daemon socket. Add Before= ordering to avocadoctl.socket and avocadoctl.service so systemd guarantees the socket is listening before either extension service starts.
…rd ordering cycle The socket unit's implicit After=sysinit.target (from DefaultDependencies=yes) created an ordering cycle with avocado-extension-initrd.service, which must run Before=sysinit.target but Requires=avocadoctl.socket. Replace with an explicit After=local-fs.target anchor so both units can start in early boot.
avocadoctl.service declared Before=avocado-extension*.service, pulling it into the early boot graph. But PrivateTmp=yes (and DefaultDependencies=yes) create an implicit After=systemd-tmpfiles-setup dependency, which comes after the extension services — forming a cycle. The socket unit already declares Before=avocado-extension*.service, which is sufficient. The daemon is socket-activated on demand: the extension service connects to the ready socket, systemd queues the daemon startup, and the client waits until the daemon answers. No explicit ordering on the service unit needed.
…st use varlink path Three bugs fixed together: 1. All varlink client calls in main.rs used .recv() which requires .send() to have been called first. Use .call() (= send + recv) instead. This caused IteratorOldReply on every RPC — the varlink routing introduced in the previous commit never worked. 2. Tests in varlink_interface_tests.rs set AVOCADO_TEST_MODE=1 on the client process, causing it to bypass varlink entirely via handle_direct(). Remove it from client invocations so tests actually exercise the daemon → varlink → service path. 3. list_extensions() returned ConfigurationError when the extensions directory did not exist. Treat NotFound as an empty list — consistent with how the direct path behaves and what ext_integration_tests expects. Also improve exit_with_rpc_error to show Debug (full chain) output when --verbose.
- Inline format string literals (print_literal, uninlined_format_args) - Use .cloned() instead of .map(|s| s.clone())
…activation With DefaultDependencies=yes, avocadoctl.service implicitly gets After=sysinit.target. When socket-activated by avocado-extension-initrd.service (which runs Before=sysinit.target), systemd cannot start the daemon until sysinit completes — a deadlock that causes the extension service to time out. Removing DefaultDependencies avoids the implicit ordering constraint, allowing socket activation to start the daemon immediately in early boot. The Before= declarations are intentionally absent (removed in a prior commit) to prevent the separate ordering cycle that was present previously.
These sandboxing directives create a private mount namespace for the daemon. Loop mounts for extensions created inside the daemon are invisible to the host, causing systemd-sysext merge to see empty directories and fail silently.
ProtectHome=yes makes /home, /root, /run/user inaccessible by creating a mount namespace as a side effect. Loop mounts created by the daemon for extensions remain trapped in this namespace and are invisible to the host, so systemd-sysext still sees empty directories.
… daemon stdout status_extensions() was calling show_enhanced_status() which printed directly to stdout (captured by systemd journal) and returned an empty vector. The CLI client received no data and displayed "No extensions currently merged." regardless of actual state. Add collect_extension_status() that gathers the same data but returns structured ExtensionStatus values through the varlink reply.
The service layer functions (add_from_url, add_from_manifest, activate_runtime) did not call refresh_extensions after activating a runtime. The CLI direct path did this in commands/runtime.rs, but the varlink daemon path skipped it, leaving old extensions merged after a deploy.
The service layer unmounted NFS shares while extensions were still merged as sysext/confext overlays, leaving broken overlay state. Match the CLI path ordering: unmerge → cleanup dropins → reload → unmount → merge remaining.
…caller Thread OutputManager through the post-merge and pre-unmerge command chains so that log messages are captured in daemon mode and returned via varlink replies instead of being printed to the daemon's journal. Updated varlink interfaces to return log vectors from merge, unmerge, refresh, and runtime add/activate operations.
…nues Replace batch log buffering with channel-based streaming so that lifecycle events (on_merge, on_unmerge, depmod, etc.) are sent to the CLI caller as they happen rather than all at once after completion. - Add OutputManager::new_streaming(SyncSender) mode that sends each log message through an mpsc channel immediately - Add _streaming() service functions that spawn work on a thread and return (Receiver, JoinHandle) for the caller to drain - Use varlink's native more/continues protocol: server calls set_continues(true) and sends per-message replies, client iterates with .more() - Re-colorize [INFO]/[SUCCESS] prefixes on the client side via print_single_log() - Backward-compatible: wants_more() check falls back to batch mode for non-streaming clients - Remove unused capture mode (RefCell buffer) from OutputManager
Use consistent `{name} {version} ({8-char-id})` format everywhere:
runtime list, inspect, activate, remove, add, status, and ambiguous
match messages. Removes the `v` prefix and matches the web UI's
display_version format.
Always log key TUF metadata info (target counts, delegation status, manifest extensions). Warn when delegation has no targets or when extension images are missing after staging. Verbose flag still controls per-item detail logging.
Route .raw TUF targets to the artifacts CDN URL when available, falling back to the TUF repo targets/ path for local deploy. Always send auth token for artifact downloads. Fail activation when extension images are missing instead of warning.
Download failures and other runtime errors were silently returned via varlink without logging, making them invisible in avocadoctl's journal. Now drain_stream() and map_rt_error!() print errors to stderr before sending the varlink error reply.
…rge priority - Runtime list now shows active runtime first, then remaining by build date (newest first) - Extension status via varlink now sorts by merge_index (priority order) instead of alphabetically
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
more/continuesTest plan
cargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo test— 176 tests passing