Resource Plugins Spec
Overview
This document provides a reference for a ResourcePlugin specification.
Purpose
A ResourcePlugin is an entity used to attach external resources, such as databases, to sandboxes. When a sandbox is created it may define resources to be made available for the sandbox, using a resource plugin. For example, a sandbox spec may contain the following:
spec:
resource:
- name: testdb
plugin: mariadb
params:
- dbname: test
In this case, a ResourcePlugin named mariadb is expected to provide a database
named test for the associated Sandbox.
ResourcePlugins are versioned with semver. The plugin
field above resolves to the latest published version of mariadb; sandboxes
may pin to a specific version using the name@version form (see
plugin on a sandbox resource).
Concepts
ResourcePlugins define 2 phases called create and delete. Each phase is
a workflow which in turn is a sequence of steps. Data can flow between the
steps, from a sandbox resource declaration to a step, and from a
step to runtime sandboxed workloads. The rest of this document discusses
the format of a ResourcePlugin specification in detail using these concepts.
Format
A ResourcePlugin specification can be expressed in json or yaml formats, as structured data. Here is an example:
name: hello-db@1.0.0
spec:
description: say hello and goodbye
runner:
image: ubuntu
create:
- name: say-hello
inputs:
- name: dbname
valueFromSandbox: true
as:
env: DBNAME
script: |
#!/usr/bin/env bash
echo hello $DBNAME
delete:
- name: say-goodbye
script: |
#!/usr/bin/env bash
echo goodbye
As the resource plugin yaml format coordinates data that may be useful to store in separate file, such as scripts, CLI template embeddings may be a useful way to store the yaml.
Update constraints
A published ResourcePlugin is identified by its (bare-name, version) pair,
and once published that pair is immutable. To roll out changes, publish a new
version (bump the @semver suffix on name) rather than re-applying
an existing one — re-applying an already-published version is rejected with an
error that names the existing version and prompts the caller to add or bump
the @semver suffix on name:. See the
CLI reference for the exact
wording, including the dedicated message for bare-name (default-version) plugins.
A specific plugin version cannot be deleted while any sandbox references that exact version. Older versions may be deleted once no sandbox pins them, even if newer versions of the same plugin exist and are still in use.
name
The name is the ResourcePlugin's identity. It carries both the bare name and
an optional version as a single token of the form bareName[@semver]:
name: my-plugin— bare. Publishes (or refers to) the default version0.0.0. Suitable when you don't care about versioning yet; responses for these plugins continue to render the name plainly without an@suffix, so the API surface stays identical to its pre-versioning shape.name: my-plugin@1.2.0— concrete semver. The version is canonicalized at the API boundary, so@v1.0.0and@1.0are accepted and stored as@1.0.0.
The bare name must match the regular expression ^[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]$
and be no longer than 253 bytes. Together with the (possibly default) version,
it must be unique amongst all ResourcePlugins in the Signadot organisation;
the same bare name may be published at many versions.
The literal string latest is not accepted as a written version
(name: my-plugin@latest is rejected on PUT). It is only meaningful as a
query-time alias on read and delete paths — see
CLI usage — and never appears in
responses, which always carry a concrete version (or the bare name when that
version is the default 0.0.0).
name is required.
spec
spec.description
The ResourcePlugin description is an optional string providing a short summary of what it is used for. The description must not exceed 255 bytes.
spec.runner
The runner specifies how the plugin phases are executed, namely the image,
namespace, and pod template overlay.
The runner is required.
spec.runner.image
The image must specify a valid docker reference to an image and is
required.
spec.runner.namespace
The namespace specifies the namespace in which the plugin phases are
executed. It is optional and when unspecified defaults to the default
namespace.
spec.runner.podTemplateOverlay
The podTemplateOverlay provides an optional string representation of a base pod
template spec on which the plugin phases are executed.
This spec is used as a basis on which a Pod is created, by appending
an init container, adding a sidecar, and rewriting the main container
command to implement the steps specified under the create and delete
phases (specified below).
A podTemplateOverlay can be useful for specifying a service account, secret mounts, resource limits, and other runtime configuration.
A podTemplateOverlay must meet the following constraints:
- If
restartPolicyis specified, it must be "Never". - If an image or namespace is specified, it must not conflict with
spec.runner.imageorspec.runner.namespace. - If an init container is specified, it must not be named
signadot-execunit-input-manager. - No container may be named
signadot-execunit-output-manager. - Finally, the name must be not specified or empty; the name will be determined by the Signadot Operator.
spec.{create,delete} (phase workflow)
create and delete represent plugin phase workflows to execute. Each
phase defines a workflow as a sequence of steps, represented as an array.
The create phase workflow is executed during sandbox startup, before
sandboxed workloads are spun up. The delete phase workflow is executed
during Sandbox termination, after sandboxed workloads have terminated.
The scheduling of each workflow is determined by dependencies between steps.
If a step a consumes output of a step b, then a will run after b has
completed. Otherwise, steps are scheduled to run in Kubernetes in parallel.
Workflows must contain at least one step.
Outputs from delete phase workflows cannot be inputs to ResourcePlugin steps
in create phase workflows, and I/O cycles are forbidden.
spec.{create,delete}[_] (step)
A step defines a unit of work to be scheduled, including its inputs and
outputs. Each step is run with the resource plugin runner in spec.runner.
First, inputs are injected into the main container. Then, the main container
process runs to termination, running the script specified in the step. If
the main container sucessfully terminates, then the outputs are exported for
consumption by any step or sandbox workload which may consume it.
A step is fully described here.