Skip to main content

Sandbox 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

info

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.

  1. match is not supported for defaultRouteGroup because it implicitly matches the sandbox whose specification it is embedded into.
  2. There are 2 additional special target formats that are supported for defaultRouteGroup.
TargetExample
Kubernetes Deploymenthttp://my-deployment.default.deploy:8080
Argo Rollouthttp://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

note

TTL was introduced in version v0.3.3 of the cli and sdks. 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.

AbbreviationMeaning
mminutes
hhours
ddays
wweeks

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.

note

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

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

caution

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

caution

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.