Specification
Overview
A Signadot Sandbox specification describes a set of sandboxed Kubernetes workloads and a Route Group for managing routing associated with it.
The specification can be expressed in json
or yaml
formats,
as structured data, for example
name: my-sandbox
spec:
labels:
dev: jane
cluster: my-cluster
description: Testing sandboxes
forks:
- forkOf:
kind: Deployment
namespace: example
name: my-app
customizations:
images:
- image: example.com/my-app:dev-abcdef
env:
- name: EXTRA_ENV
value: foo
defaultRouteGroup: # CLI v0.3.7+ required (see sandbox specification for details)
endpoints:
- name: my-endpoint
target: http://my-app.example.svc:8080
This document details all the fields and constraints associated with a valid sandbox specification. A cheatsheet is available here.
Global constraints
The names of endpoints must be unique across the spec.
Any baseline workload can be referred to at most once in
the fields spec.forks[_].forkOf
and spec.locals[_].from
.
Update constraints
A sandbox may be updated. Only some fields are mutable, the rest are immutable. In addition, some constraints apply.
The field spec.labels
may be arbitrarily modified, provided
the labels are not used for PR integration.
Any field named endpoints
may be modified arbitrarily. As this field is of
type array, that means that one can add or remove or change endpoints.
Any entry in spec.forks
, identified by the key forkOf
may be modified
arbitrarily, but may or may not deleted, depending on the operator version.
Additionally, one may add entries to spec.forks
.
The field spec.local
can be arbitrarily updated subject to global constraints.
The entry spec.ttl
can be added, removed, or arbitrarily modified.
No other field may be modified. In particular, as the name
of a sandbox
acts as an identifier, one cannot rename a sandbox. Also, spec.resources
is
immutable, and spec.cluster
is immutable.
name
The name is a string used to identify the sandbox. The name must be unique amongst all sandboxes associated with the Signadot organisation used to create the sandbox.
A name must match the regular expression ^[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?$
and be no longer than 30 bytes in length.
The name is required and immutable.
spec
The sandbox spec is required and contains all components of the specification except the name. Some parts of the spec are mutable and some are immutable.
spec.cluster
The cluster associated with a sandbox is a string which identifies a cluster registered with Signadot by name. In general, the cluster should have the Signadot Operator installed. The cluster name should not exceed 255 bytes in length.
cluster
is required and immutable.
spec.defaultRouteGroup
spec.defaultRouteGroup
is supported in CLI v0.3.7+. This supersedes the previous
method of setting endpoints using spec.forks[].endpoints
and spec.endpoints
which is
now deprecated. It is recommended that you upgrade to this version of the CLI or above.
This is a specification of a default Route Group associated with the sandbox. The specification is similar to the Route Group, with the exception of 2 differences.
match
is not supported fordefaultRouteGroup
because it implicitly matches the sandbox whose specification it is embedded into.- There are 2 additional special target formats that are supported for
defaultRouteGroup
.
Target | Example |
---|---|
Kubernetes Deployment | http://my-deployment.default.deploy:8080 |
Argo Rollout | http://my-rollout.default.rollout:8080 |
These are available primarily for backwards compatibility with spec.forks[].endpoints
.
For new sandboxes, it is recommended that you use the new methods of specifying targets supported by route groups.
spec.description
The sandbox description is an optional string providing a short summary of what the sandbox is used for. The description must not exceed 255 bytes. The sandbox description is immutable.
spec.labels
Labels are a map from strings to strings, for example
spec:
labels:
dev: jane
feature: x
A label key must not exceed 255 bytes in length and must contain at least 1 character. Additionally, it must contain only the characters
A-Z // upercase alphabetic
a-z // lowercase alphabetic
0-9 // numeric
- // dash
_ // underscore
A label value can be an arbitrary string which also must not exceed 255 bytes in length and must contain at least one character. However, value contents are not otherwise restricted.
Sandbox labels are optional and mutable.
Futher information is available here.
spec.ttl
TTL was introduced in version v0.3.3 of the cli. Using earlier versions of these tools can drop the ttl field from the spec.
ttl
is a field placing a lifetime time limit on a sandbox. It is an object with
2 keys, duration
and offsetFrom
:
ttl:
duration: 1d
offsetFrom: createdAt # Supported values: `createdAt` (default), `updatedAt`
The duration takes the form <n><unit>
where <n>
is a base 10 unsigned
integer not exceeding 32 bits and <unit>
is a time unit abbreviation described
in the table below.
Abbreviation | Meaning |
---|---|
m | minutes |
h | hours |
d | days |
w | weeks |
When a sandbox lifetime has expired, the sandbox is deleted. As sandbox deletion requires synchronization with the cluster in which the sandbox resides, the delete operation can take up to a few minutes to complete. As a result, there can be a small amount of drift between the lifetime time limit and the effective completion of the delete operation.
Within a ttl
field, duration
is required.
The offsetFrom
(optional and mutable) specifies what the
TTL duration is relative to.
createdAt
(default): TTL with respect to sandbox creation time.updatedAt
: TTL with respect to last sandbox update time.
spec.forks
Forks is an array of descriptions of forked Kubernetes workloads dedicated to serving the sandbox. Each field of the description is detailed below, and as a whole, a fork details how to run the forked workload as a set of customizations applied to the workload's baseline configuration. Each fork can also contain specifications of associated endpoints.
When a fork is created, the baseline workload is cloned and the specified customizations are applied to it. Each Kubernetes service that is associated with the baseline workload is also cloned in the context of the sandbox, and these (one or more) Kubernetes services are used for request routing.
spec.forks[_].forkOf
forkOf
is required within a fork and defines what baseline workload
to fork. There should be at most one forkOf for a given workload, and
the fork should describe a valid workload running in the cluster under
the field cluster. One can add baseline workloads to fork to a spec
but one cannot remove baseline workloads from a spec.
An annotated example follows.
spec:
forks:
- forkOf:
# kind specifies the Kubernetes kind of workload to fork. It may be
# either 'Deployment' or 'ArgoRollout'.
kind: Deployment
# namespace within which the workload resides.
namespace: backend
# the name of the workload to fork
name: my-app
spec.forks[_].customizations
A customizations object specifies how to customize the baseline workload to the sandbox under specification.
customizations
is optional and mutable.
images
images
specifies a set of custom images to run in the forked workload in
place of the images configured for the baseline.
spec:
forks:
- customizations:
images:
- container: main
image: docker.io/my-company/my-service:dev
Each image item contains an optional container
field, which is a string field
that holds the name of a container in a pod spec in the workload to be
forked. The image
field is required and must house a valid docker reference
to an image. It is also mutable.
In the event that container
is empty or not specified, the main container
of the pod spec will be used. The main container is the first container in
the list of containers to run for a pod. Only one item without a container
may exist in the list of image specifications.
A container name must appear at most once in the list.
images
is optional and mutable; one can change the list of images
arbitrarily, provided the above constraints are respected.
env
env
specifies a set of environmental variables to set up for the containers
associated with a pod. The following example shows the different ways
environmental variables can be defined.
spec:
forks:
- forkOf:
# ...
customizations:
env:
- name: APP_ROOT
value: /app-dev
- container: main
name: DBHOST
valueFrom:
resource:
name: testdb
outputKey: provision.dbhost
# the valueFrom items above refer to elements of the spec shown below
- forkOf:
kind: Deployment
namespace: backend
name: sentiment-analysis
# resource whose plugin generates an output key 'dbhost'
resources:
- name: testdb
# ...
The first item is a simple string key, value pair, defining the environment variable APP_ROOT. No container is specified, so the main container is inferred. Containers are infered for any item without a container specified.
The second item defines DBHOST, making reference to a resource associated with the sandbox, which is made available by a resource plugin that provides an output key 'provision.dbhost'. The full documentation for resources is available here.
env
is optional and mutable.
patch
patch
is optional and mutable. Moreover, patch
is intended only as an escape hatch to accomodate uncommon
Kubernetes workload configurations. In most cases, patch
should not be used.
patch
specifies a patch to be applied to the forked workload specification after custom images
and environmental variables are set.
spec:
forks:
- customizations:
patch:
type: strategic # one of json, merge, strategic
value: '{"spec":{"template":{"spec":{"containers":[{"name":"main", "ports":[{"containerPort": 4242}]}]}}}}'
patch
contains two fields, type
and value
. type
must be one of
- "strategic", referring to a strategic merge patch
- "merge", referring to a json merge patch.
- "json", referring to a json patch.
The value
field provides the contents of the patch as a string, which may be a json string
as above or yaml:
spec:
forks:
- customizations:
patch:
type: strategic # one of json, merge, strategic
value: |
spec:
template:
spec:
containers:
- name: main
ports:
- containerPort: 4242
The examples above show a strategic merge patch which sets the containerPort to the container "main" to value 4242.
spec.forks[_].endpoints
This field is deprecated and has been replaced by spec.defaultRouteGroup.
The endpoints
field in a fork specifies an array of endpoints which result in
URLs which, in turn, resolve to the forked workload. One specifies the
name, port, and protocol for a fork endpoint:
forks:
- forkOf: ...
endpoints:
- name: my-app
port: 8080
protocol: http # or grpc
The name must be unique amongst all endpoints, even endpoints in other forks and host endpoints (see below). The name is required.
The port specifies the port number to which the resulting URL will resolve.
The protocol specifies what protocol is used at the given port within the fork. One
may specify either http
or grpc
.
Given an endpoint in a spec, Signadot will create URLs which allow accessing the fork at the given port using the specified protocol. These URLs are available via the Signadot API server when accessing the sandbox.
endpoints
is optional and mutable.
Further documentation about endpoints is available here.
spec.endpoints
This field is deprecated and has been replaced by spec.defaultRouteGroup.
The top level endpoints
field in a spec is an array of host endpoints.
Each host endpoint operates in the same fashion as a fork endpoint, as
specified above. However, in addition, one must specify the host to which the
resulting URL will resolve. The host is a string representing a host name
which will be resolved via DNS in the cluster in which the sandbox resides.
spec:
endpoints:
- name: event-store
host: event-store.backend.svc
port: 8080
protocol: http
endpoints
is optional and mutable.
Further documentation about endpoints is available here.
spec.local[_]
The local
field in a spec provides the specification for a list of
workloads to run locally on the workstation of the submitter of the spec.
The Signadot CLI is required for this feature. Unlike all other fields in a spec, it is not recommended to use sandboxes with local workloads in automated CI pipelines; it is rather intended for interactive use. Additionally, since sandboxes are shared across an organisation, it is recommended to follow a convention so that each user can name their sandboxes without conflicting with other users.
The local
field in a spec is optional and mutable.
Each local workload spec must provide definitions for a name
,
the workload to be forked (from
), and a mapping from workload ports
to local TCP addresses (mappings
).
The name
field is used to identify the local workload and must be
unique accross local workloads. The name is used to identify the
local workload in the sandbox status.
The from
field follows the same constraints as forkOf,
which defines the in-cluster workload to run locally. The set of in-cluster workloads
in the sandbox includes both local workloads and forks. No workload should appear
more than once in a given sandbox.
The mappings
field provide mappings from workload ports to tcp addresses to
which the local workstation can listen, such as "localhost:8080". The mappings
field must be present.
name: username-router # unique name for `user` accross organisation
spec:
local:
- name: router # string
from:
kind: Deployment
namespace: ns1
name: router
mappings:
- port: 8080 # workload port, int
toLocal: "localhost:8080" # string, tcp address in host:port form
spec.resources
The top level resources
field in a spec provides information about external resources
associated with a sandbox, such as a database or message queue.
resources
is an array of objects specifying the usage of a resource provided by
a resource plugin, which needs to be installed in the cluster associated with
the sandbox under specification. An example follows
spec:
resources:
- name: testdb
plugin: sd-mariadb
params:
dbname: testdb
A single resource item contains 3 elements: a name for the resource as viewed by the sandbox, a plugin giving the name of a resource plugin installed in the cluster for provisioning the resource, and a set of key, value string params.
The name must be unique amongst all names in the resource list.
Full documentation for sandbox resources are available
here and the field resources
is optional and
immutable.