Resources
For a full working code example covering all the concepts described below, see https://github.com/signadot/examples.
Resources are ephemeral entities whose lifecycle is managed as part of a sandbox. Resources are typically used to isolate sandbox environments when there are stateful components involved like databases and message queues. A resource does not necessarily represent physical infrastructure. For example:
- A resource can represent an ephemeral MySQL StatefulSet within your Kubernetes cluster
- A resource can represent an ephemeral schema within an Amazon RDS cluster
- A resource can represent an ephemeral topic within RabbitMQ / Kafka.
As a user of resources, there is a high level interface provided via the Signadot APIs that can be used to both request resources and associate them with forked workloads running within your sandbox.
Creating and Deleting Resources
Resource creation and deletion is managed by a Resource Plugin. Each resource plugin can be thought of as a piece of infrastructure that is responsible for managing that specific type of resource. Resource Plugins are installed using the signadot CLI.
Once a resource plugin is installed, it can be referenced by a sandbox during
creation. When this is done, the create
workflow of the resource plugin is
invoked to stand up the resource. When the sandbox is deleted, the
corresponding delete
workflow is called that in turn destroys the
ephemeral resource that was created.
Usage
For example, a sandbox that requests a maria-db resource in order to set up an
isolated dependency for a customer
microservice is shown below. In this
cluster, it is assumed that there is a Resource
Plugin called hotrod-mariadb
installed which will be
used to provision and deprovision the maria-db resource.
- CLI
- Java
- Python
# customer-sandbox.yaml
# usage: signadot sandbox apply -f customer-sandbox.yaml
name: customer
spec:
cluster: ...
resources:
- name: customerdb
plugin: hotrod-mariadb
params:
dbname: customer
forks:
forkOf:
kind: Deployment
namespace: hotrod
name: customer
customizations:
env:
- name: MYSQL_HOST # set MYSQL_HOST to that provided by the plugin
valueFrom:
resource:
name: customerdb
outputKey: provision.host
- name: MYSQL_PORT
valueFrom:
resource:
name: provision.customerdb
outputKey: port
- name: MYSQL_ROOT_PASSWORD
valueFrom:
resource:
name: customerdb
outputKey: provision.root-password
// see working example in https://github.com/signadot/examples/blob/main/sdk/java/src/test/java/ResourcesTest.java
SandboxFork customerServiceFork = new SandboxFork()
.forkOf(new SandboxForkOf().kind("Deployment").namespace("hotrod").name("customer"))
.customizations(new SandboxCustomizations()
.addImagesItem(...)
// Dynamic env vars are derived from the resource and set on the forked pod within the sandbox.
// This allows the forked pod to connect to the maria-db resource that was provisioned.
.env(Arrays.asList(
new SandboxEnvVar().name("MYSQL_HOST").valueFrom(new SandboxEnvValueFrom().resource(
new SandboxEnvValueFromResource().name("customerdb").outputKey("provision.host")
)),
new SandboxEnvVar().name("MYSQL_PORT").valueFrom(new SandboxEnvValueFrom().resource(
new SandboxEnvValueFromResource().name("customerdb").outputKey("provision.port")
)),
new SandboxEnvVar().name("MYSQL_ROOT_PASSWORD").valueFrom(new SandboxEnvValueFrom().resource(
new SandboxEnvValueFromResource().name("customerdb").outputKey("provision.root-password")
))
)
)
.addEndpointsItem(...);
SandboxResource customerDBResource = new SandboxResource()
.name("customerdb")
.plugin("hotrod-mariadb")
.putParamsItem("dbname", "customer");
Sandbox request = new Sandbox()
.spec(new SandboxSpec()
.cluster(...)
.description(...)
.addForksItem(customerServiceFork)
.addResourcesItem(customerDBResource));
# see working example in https://github.com/signadot/examples/blob/main/sdk/python/tests/integration/resources_test.py
customer_service_fork = SandboxFork(
fork_of=SandboxForkOf(
kind="Deployment",
name="customer",
namespace="hotrod"
),
customizations=SandboxCustomizations(
images=[...],
# Dynamic env vars are derived from the resource and set on the forked pod within the sandbox.
# This allows the forked pod to connect to the maria-db resource that was provisioned.
env=[
SandboxEnvVar(
name="MYSQL_HOST",
value_from=SandboxEnvValueFrom(
resource=SandboxEnvValueFromResource(name="customerdb", output_key="provision.host")
)
),
SandboxEnvVar(
name="MYSQL_PORT",
value_from=SandboxEnvValueFrom(
resource=SandboxEnvValueFromResource(name="customerdb", output_key="provision.port")
)
),
SandboxEnvVar(
name="MYSQL_ROOT_PASSWORD",
value_from=SandboxEnvValueFrom(
resource=SandboxEnvValueFromResource(name="customerdb", output_key="provision.root-password")
)
)
]
),
endpoints=[...]
)
request = Sandbox(
spec=SandboxSpec(
description="Python SDK: Create sandbox with ephemeral db resource spun up using hotrod-mariadb plugin",
cluster=cls.SIGNADOT_CLUSTER_NAME,
resources=[SandboxResource(name="customerdb", plugin="hotrod-mariadb",
params={"dbname": "customer"})],
forks=[customer_service_fork]
)
)
There are some input parameters that the Resource Plugin's provision workflow
takes in order to set up the ephemeral resource. In the above case, the
resource
request is specified in the call to create a sandbox which specifies
that the hotrod-mariadb
plugin must be used, and passes the input parameter
dbname
with value customer
to it.
Once the ephemeral resource has been set up, the "outputs" are typically things like the credentials required to access that resource. These outputs are available as special environment variables that can be supplied to any of the forks within the Sandbox as shown above. By making use of these credentials, the workload within the sandbox can connect to the isolated ephemeral resource in place of a shared entity that may be in the baseline environment. The inputs and outputs associated with each Resource Plugin are specific to them and typically documented in the description of the plugin that is available via the Signadot Dashboard.