`GET /v1/orgs/{org}/policies/preview/context`.
const url = 'https://api.updawg.net/v1/orgs/example/policies/preview/context';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.updawg.net/v1/orgs/example/policies/preview/contextEverything preview reads besides the document, so that the portal can run
the same engine in the browser on every keystroke instead of asking this
endpoint each time (DAWG-93). Capped at the same number of hosts, oldest
first, so the two answer about the same fleet.
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Organization slug.
Responses
Section titled “Responses”The policies in force and the fleet a preview evaluates. ⚠️ Check engine against the engine you run it with: a different version may decide differently, and the preview endpoint is the answer then.
Everything a preview reads besides the document: what the server hands the portal so the portal can preview without asking again on every keystroke.
object
[ENGINE_VERSION] of the server that answered. A portal whose engine
reports a different one must not preview with it.
At most the server’s preview cap, oldest first.
One host and the updates it has outstanding.
object
A host as the engine sees it.
object
The groups this host belongs to, by name.
An enrolled host.
The host’s labels. A map rather than pairs, because a host cannot have one label twice and the type should say so.
object
Whether the host is already waiting for a reboot, before any of these updates are applied. Not a selector today; carried because a proposal that will add a second reboot requirement to a host already needing one is worth showing, and because leaving it out of the input would make adding it later a change to every caller.
One pending update, already classified against advisory data.
This is host_updates after evaluate_host has run (DAWG-56, DAWG-68):
the kind is decided, the advisories are attributed, and the severity is
whatever they said.
Ord is derived, and the field order is the sort order
The engine sorts the contents of a proposal so that two evaluations of the same fleet produce byte-identical output. Sorting on the package name alone is not enough: two updates for the same package compare equal, the sort is no longer a total order, and the caller’s input order leaks into the result. A property test found that within a minute of being written, which is more than the comment asserting the opposite had managed.
package is therefore first, and the rest of the fields follow so that any
two distinguishable updates have a defined order. Reordering the fields
changes the sort; nothing else depends on it.
object
Which advisories this update would fix. Empty is not the same as unassessed: it means nothing published covers this package version.
Ord is derived so this can key an ordered collection — the policy engine
groups proposals by kind in a BTreeMap and needs a total order to produce
the same output twice. The order itself is the declaration order and carries
no meaning; nothing should read severity into it.
Whether applying this one needs a reboot to take effect. From
domain::classify::needs_reboot, which reads it off the package rather
than off the kind — a kernel security update is classified security,
so the kind cannot be trusted to carry this.
None means nobody rated it, not “rated as harmless”.
This is an Option rather than a Severity for the reason
domain::Severity spends twenty lines on: Debian publishes a rating for
almost nothing, so on a Debian fleet unrated is the common case, and a
policy that quietly treated it as a level would be making a judgement
nobody made. [crate::SeverityMatch] is where that distinction is
enforced.
How many hosts the organization has.
Every live policy, disabled ones included: a disabled policy still holds its name and can still be edited.
A live policy, as the identity checks need it.
object
A policy.
Which version is in force.
The enabled ones, compiled, in evaluation order: what the engine runs.
One policy, as the engine sees it.
object
A policy.
When a policy is willing to let work happen.
object
Empty means every day. The design document’s example lists three.
Local wall-clock time in timezone, not UTC. A window written 02:00
is meant to stay at two in the morning through a clock change, which is
the entire reason this field is not an offset.
Higher wins. The column defaults to 100, which is what the design document’s example uses.
Named rollout strategies a rule may refer to. The engine only carries the name through to the intent — staged rollouts are epic 09, and what a stage does is not a decision this function makes.
object
A named rollout strategy.
Carried through the engine untouched: all the engine does is refuse to name
one that does not exist. What a stage selects is [crate::rollout::plan]
(DAWG-107); advancing through them is the worker’s rollout_tick.
object
object
object
Exactly this many more hosts (DAWG-107). Unlike percent, counted from
this stage, because “the next five” is how a count is meant.
Which hosts this stage covers, when it is selected by label rather than by proportion.
object
The host is in any of these groups. Empty means “any group”.
The host carries all of these labels, with exactly these values. Empty means “any labels”.
object
Bring the rollout up to this share of its hosts, counted from the
start: 25 then 100 is a quarter, then everybody else. Hosts an
earlier stage already took count towards it.
Evaluated in order. The first rule that matches an update decides it.
One rule inside a policy.
object
What a rule decided should happen.
When an approved proposal may start.
None means “whatever this action implies” — see
[Rule::requested_approval]. It is an Option rather than a defaulted
value because the sensible default depends on the action, and a rule
that says action: auto_merge and nothing else must not acquire an
approval requirement that turns it into a proposal.
object
Ignored when required is false. Zero is meaningless and the schema
rejects it; the engine treats anything below one as one rather than as
“no approvers needed”, because rounding towards asking is the safe
direction.
What an update has to look like for a rule to catch it.
Every field is a filter, and they are ANDed. A Match with nothing set
catches every update, which is how the example policy’s last-resort rules
are written.
A step that may be required before a proposal applies.
What to do about a host that needs a reboot afterwards.
The name of one of the policy’s rollouts.
A step that may be required before a proposal applies.
Which hosts a policy applies to.
An empty selector matches every host
Deliberately, because “the org-wide default policy” has to be writable and the natural way to write it is to say nothing. It is also the way to apply a policy to the whole fleet by accident, so the schema (DAWG-86) should warn on it and the portal’s preview (DAWG-94) should show the host count before anybody saves.
object
The host is in any of these groups. Empty means “any group”.
The host carries all of these labels, with exactly these values. Empty means “any labels”.
object
The row in policy_versions this came from. It travels into every
proposal so “why was this proposed” stays answerable after an edit.
Example
{ "hosts": [ { "updates": [ { "kind": "security", "severity": "none" } ] } ], "policies": [ { "maintenance_window": { "days": [ "tue" ], "timezone": "Europe/London" }, "rules": [ { "action": "propose", "apply": "asap", "batch": "daily", "match": { "kind": [ "security" ], "packages": [ "openssl*" ], "severity": { "levels": [ "none" ] } }, "preflight": "optional", "reboot": "never", "snapshot": "optional" } ] } ]}No session.
object
Example generated
{ "detail": "example", "status": 1, "title": "example", "type": "example"}Not permitted for this role.
object
Example generated
{ "detail": "example", "status": 1, "title": "example", "type": "example"}No such organization, or not yours.
object
Example generated
{ "detail": "example", "status": 1, "title": "example", "type": "example"}The organization’s data is in another region (wrong-region, DAWG-159). detail names that region’s API; send the request there.
object
Example generated
{ "detail": "example", "status": 1, "title": "example", "type": "example"}Over the organization’s request limit. Retry-After says when to try again; RateLimit-Limit is the burst.
object
Example generated
{ "detail": "example", "status": 1, "title": "example", "type": "example"}