Resource hooks
One of the most powerful features of datacenters is the ability for developers to request cloud resources that get fulfilled uniquely by the datacenter. These resources represent a contract between Components and Datacenters that allows them both to work together to create and deploy cloud software.
When Components get deployed, Architect extracts all the relevant cloud resources and queues them up for the datacenter to fulfill with its own modules. The way the datacenter "hooks" into these resource claims to fulfill them is with declarations inside the environment block of the datacenter configuration.
In doing so, the modules have full access to the resource inputs, but are required to also provide back the resource "outputs". By providing the relevant output values, datacenters don't need to have any knowledge of the relationship between the resources, allowing the process of fulfilling the requests to be as simple as possible. If a deployment expects one of its environment variables to be populated with the address of a peer service, the datacenter simply needs to cite the url as an output of the service hook and doesn't actually care what other resources are going to consume the value. Instead, Architect will ensure the relevant resources get the correct output values.
Supported resource types
The resources Architect supports are limited only to resources relevant to applications. Infrastructure resources like VPCs, kubernetes clusters, DNS zones, etc. are only relevant to applications if they end up being used to fulfill core resource claims. For example, a service can be fulfilled by a kubernetes cluster or a separate service mesh - the application doesn't care which so long as it gets a resolvable URL at the end.
Below is a full list of the supported resource types, along with the relevant input/output specs:
database
The database resource represents a request for a specific type/version of database. These requests
can be fulfilled by a shared database cluster just as easily as they can be by individual database
clusters. It's up to the datacenter to decide the specifics.
Example
environment {
database {
when = node.inputs.databaseType == "postgres"
module "dbCluster" {
source = "./db/cluster"
inputs = {
# ...
}
}
outputs = {
host = module.dbCluster.host
port = module.dbCluster.port
username = module.dbCluster.username
}
}
}
Inputs
Loading...
Outputs
Loading...
databaseUser
The databaseUser resource type represents a request for a unique set of credentials. Architect
generates these requests on behalf of components whenever it detects that different applications are
asking for access to the same database.
Example
environment {
databaseUser {
when = node.inputs.databaseType == "postgres"
module "pgUser" {
source = "./pg/user"
inputs = {
rootUser = node.inputs.username
rootPass = node.inputs.password
}
}
outputs = {
username = module.dbCluster.username
password = module.dbCluster.password
}
}
}
Inputs
Loading...
Outputs
Loading...
deployment
The deployment resource represents a request to deploy and maintain one or more replicas of an
application. For those familiar with Kubernetes, this is a near identical concept to the
Deployment resource.
Example
environment {
deployment {
module "deployment" {
build = "./k8s-deployment"
inputs = merge(node.inputs, {
namespace = module.namespace.id
kubeconfig = module.k8s.kubeconfig
})
}
}
}
Inputs
Loading...
Outputs
Loading...
service
The service resource represents an application's need to expose an application for internal network traffic. These are common for internal APIs.
Example
environment {
service {
module "service" {
build = "./k8s-service"
inputs = merge(node.inputs, {
name = "${node.component}--${node.name}"
namespace = module.namespace.id
kubeconfig = module.k8s.kubeconfig
})
}
outputs = {
protocol = node.inputs.protocol || "http"
host = module.service.host
port = module.service.port
url = "${nodes.inputs.protocol}://${module.service.host}:${module.service.port}"
}
}
}
Inputs
Loading...
Outputs
Loading...
ingress
Ingress resources represent an application's need to expose an application for external traffic. This is common for web applications and external APIs.
Example
environment {
ingress {
module "ingressRule" {
build = "./ingressRule"
inputs = merge(node.inputs, {
name = "${node.component}--${node.name}"
namespace = module.namespace.id
kubeconfig = module.k8s.kubeconfig
dns_zone = variable.dns_zone
ingress_class_name = module.nginxController.ingress_class_name
})
}
module "dnsRecord" {
build = "./dns-record"
environment = {
DIGITALOCEAN_TOKEN = variable.do_token
}
inputs = {
domain = variable.dns_zone
type = "A"
value = module.ingressRule.load_balancer_ip
subdomain = node.inputs.subdomain
}
}
outputs = {
protocol = module.ingressRule.protocol
host = module.ingressRule.host
port = module.ingressRule.port
username = module.ingressRule.username
password = module.ingressRule.password
url = module.ingressRule.url
path = module.ingressRule.path
subdomain = node.inputs.subdomain
dns_zone = node.inputs.dns_zone
}
}
}
Inputs
Loading...
Outputs
Loading...
cronjob
Cronjobs represent a request to run a script on a schedule.
Example
environment {
cronjob {
module "cronjob" {
build = "./cronjob"
inputs = merge(node.inputs, {
namespace = module.namespace.id
kubeconfig = module.k8s.kubeconfig
})
}
outputs = {
data = node.inputs.data
}
}
}
Inputs
Loading...
Outputs
Loading...
secret
Secret resources represent an application's need to store sensitive data for their applications. These are often component inputs or outputs.
Example
environment {
secret {
module "secret" {
build = "./secret"
plugin = "opentofu"
inputs = {
filename = "${var.secretsDir}--${environment.name}--${node.component}--${node.name}.json"
content = node.inputs.data
}
}
outputs = {
data = node.inputs.data
}
}
}
Inputs
Loading...
Outputs
Loading...
dockerBuild
This resource type is only used when deploying components from source. Each node represents a job that builds a docker image from the component source. This is common for ephemeral and preview environments.
Example
environment {
dockerBuild {
module "build" {
build = "./docker-build"
environment = {
DOCKER_HOST = "unix:///var/run/docker.sock"
}
volume {
host_path = "/var/run/docker.sock"
mount_path = "/var/run/docker.sock"
}
inputs = {
image = "${node.component}-${node.name}"
context = node.inputs.context
dockerfile = node.inputs.dockerfile
args = node.inputs.args
target = node.inputs.target
}
}
outputs = {
image = module.build.image
}
}
}
Inputs
Loading...
Outputs
Loading...