ReqManagedAgents.Provisioner.Environments (ReqManagedAgents v0.9.0)

Copy Markdown View Source

Environments as immutable images: content-addressed by spec digest, built once, reused forever, superseded by NEW images (never mutated), destroyed only by explicit prune.

The provider-side name is <base>_<digest8>repo@digest — so a name collision can only ever mean "this exact image already exists", and recovery by name is definitionally version-correct even with an empty store.

Summary

Functions

Build-if-absent for an environment image. Returns {:ok, %Handle{}}.

Explicit image GC: archives <base>_* environment versions beyond the newest keep: (REQUIRED — there is no default for a permanent operation), never touching tagged digests or already-archived versions. Returns {:ok, %{archived: names, kept: names}} or {:error, {:partial, archived_names, {failed_name, reason}}}.

Resolve "base:tag" to the tagged image's handle. Never falls back: {:error, :unknown_tag} when the tag doesn't exist, {:error, {:untracked_digest, digest}} when the tag points at a digest whose provision entry is gone (e.g. pruned store) — re-ensure the spec to heal.

Point base:tag at an image digest (or a handle's digest). A movable pointer — retagging replaces it. Tagged digests are protected from prune/3.

Functions

ensure_environment(client, env_spec, opts \\ [])

@spec ensure_environment(
  term(),
  ReqManagedAgents.Environment.Spec.t() | map(),
  keyword()
) ::
  {:ok, ReqManagedAgents.Provisioner.Environment.Handle.t()} | {:error, term()}

Build-if-absent for an environment image. Returns {:ok, %Handle{}}.

When the spec declares runtimes, the RETURNED %Handle{} additionally carries bootstrap: %{script: ..., instructions: ...} — DERIVED from the spec on every call (all paths: fresh create, recovery, store hit), never stored. The persisted handle stays exactly three fields (bootstrap is excluded from the Jason.Encoder derivation); only the in-memory struct returned here carries it. Sessions execute the script via the agent's bash on first need; the library only renders it.

Opts: :name (repository base, default "env"), :store ({module, store_opts}), :create_fun / :list_fun (test seams; default to ReqManagedAgents.Client calls on the given client).

prune_environments(client, base, opts \\ [])

Explicit image GC: archives <base>_* environment versions beyond the newest keep: (REQUIRED — there is no default for a permanent operation), never touching tagged digests or already-archived versions. Returns {:ok, %{archived: names, kept: names}} or {:error, {:partial, archived_names, {failed_name, reason}}}.

resolve(ref, opts \\ [])

Resolve "base:tag" to the tagged image's handle. Never falls back: {:error, :unknown_tag} when the tag doesn't exist, {:error, {:untracked_digest, digest}} when the tag points at a digest whose provision entry is gone (e.g. pruned store) — re-ensure the spec to heal.

ref must be of the form "base:tag" — a ref without a colon raises ArgumentError. The split is on the FIRST colon only, so tag names may themselves contain colons ("a:b:c" resolves tag "b:c" under base "a").

The resolved handle's :bootstrap is always nil — no env spec is in scope here to derive it from; call ensure_environment/3 with the spec when the bootstrap content is needed.

tag(base, tag, digest_or_handle, opts \\ [])

Point base:tag at an image digest (or a handle's digest). A movable pointer — retagging replaces it. Tagged digests are protected from prune/3.