A patch envelope is EVE-OS's mechanism for delivering/updating data to a running edge app instance at runtime — without rebooting the VM, recreating the image, or redeploying the app. It is a container of one or more binary artifacts (blobs): base64-encoded objects that can be anything — a config file, a YAML, certs, a license key, a small binary, etc.
The core use case is decoupling mutable data/config from the immutable app image. Instead of baking config into the image (and re-rolling the image every time something changes), you attach a patch envelope to the app instance and update just that data. Typical scenarios:
You manage it from the controller (the PatchEnvelopeConfiguration API), and EVE exposes
it to the app locally.
You attach one or more binary artifacts to a patch envelope and present them to the app instance; the app then pulls them from the metadata service. So what can that artifact actually be?
Anything — it is an opaque blob to EVE. EVE does not parse, validate, or execute the artifact; it only delivers the bytes into the app's reach. So a binary artifact can be:
.exe, a shell script, a Python file.env.ext, .bin, .dat, …) — the extension is meaningless to EVE
EVE never runs it. For an .exe, EVE transfers the bytes; the guest app (e.g. a
Windows VM) is what pulls it and executes it. EVE is agnostic about what the blob is or which
OS consumes it.
Yes — that is the external artifact model (see inline vs. external artifacts
below), and it is the right choice for anything larger than the inline limit (e.g. an .exe).
description.json → download URL); external artifacts appear under VolumeRefs. EVE downloads the volume host-side, but the app is what retrieves/uses it — it is not auto-injected into the guest.The exact datastore types supported for patch-envelope external artifacts (HTTP/HTTPS, S3,
Azure blob, container registry, …) may be narrower than the full image-datastore list —
verify against thePatchEnvelopeConfigurationAPI for your zedcloud version.
The patch envelope metadata service is pull-only. There is no push, no
notification, no interrupt to the guest. So if the app wants to discover that a
new config exists, it has to poll description.json. There is no way around that.
Two different things are worth separating:
curl loop hammering the endpoint many times a second — not needed.So the accurate statement is: yes, the app must poll — you just choose the interval (every 30 s, every 5 min, whatever your freshness tolerance is), and you compare SHA hashes to avoid re-applying unchanged blobs. It is still polling; it is just cheap polling.
The only way to avoid polling entirely is to not have the app auto-discover updates — i.e. only fetch on startup, and force a re-fetch by some external action (redeploy/restart the instance, or bump the app so its entrypoint runs again). That is not the app “noticing” a new config — that is you pushing a lifecycle event.
description.json, SHA-compare, re-download on change). Pick a sane interval.There is no server-push option in the current patch-envelope design.
| Endpoint | Purpose |
|---|---|
GET http://169.254.169.254/eve/v1/patch/description.json | Lists patch envelopes available to this app instance — PatchId, blob filenames, SHA hashes, metadata, download URLs, and VolumeRefs |
GET http://169.254.169.254/eve/v1/patch/download/{PatchID} | Download all artifacts as a single ZIP |
GET http://169.254.169.254/eve/v1/patch/download/{PatchID}/{filename} | Download one artifact by name |
Note: the metadata server is only reachable by app instances attached to a local network
instance (the same169.254.169.254link-local service used for cloud-init/ECO metadata).
An app on a pure switch NI with no local-NI path will not see it.
The metadata service lives inside EVE on the edge node — it is not exposed outside the node. This has direct consequences for how the workload is networked:
169.254.169.254. A Switch NI is pure layer 2 (a bridge to the physical LAN) and has no path to an address that only exists inside EVE. So the app must have an interface on a Local NI to hit the metadata service.169.254.169.254 goes out the wrong interface and fails.ip route commands. Add a static route for the metadata address on the Local NI so the app always routes metadata traffic via that interface regardless of which one holds the default route. In the zedcloud_network_instance resource this is the static_routes block: static_routes {
prefix = "169.254.169.254/32"
gateway = "<Local NI gateway IP>"
}
(The NI also has propagate_connected_routes for auto-propagating its connected routes.)
How to detect changes without busy-polling: fetch description.json and compare the
SHA hashes of the blobs to what you already applied. If unchanged, do nothing. A
lightweight periodic check (e.g. every few minutes) is enough — no constant querying.
There are two flavors, which affects how the data reaches the device:
VolumeRefs in description.json. Use this for larger blobs (binaries, .exe, tarballs, datasets). These inherit the datastore's ACL/access requirements, so the datastore must be reachable and permissioned correctly.curl description.json once, download the artifact(s), write them where the app expects them, then start.description.json, compares SHAs, and re-downloads only on change. No continuous polling needed.169.254.169.254.