Placeholder expressions
Placeholder expressions let you add dynamic elements into the configuration of the Platform Orchestrator.
Placeholder expressions are identified through their ${
prefix and }
suffix and follow a strict syntax as shown on this page, e.g. ${context.env_id}
for “the ID of the current environment”.
Note that not all locations support all kinds of placeholders. Errors will be thrown if the placeholder is not supported or cannot be resolved. Refer to the list below to see which placeholder expression may be used where and find more usage details in the sections further down.
List of placeholders
Placeholder expression | Usable in | Description |
---|---|---|
${context.env_id} |
Manifest:
|
The environment ID of the current deployment (details) |
${context.env_type_id} |
Manifest:
|
The environment type ID of the current deployment (details) |
${context.org_id} |
Manifest:
|
The organization ID of the current deployment (details) |
${context.project_id} |
Manifest:
|
The project ID of the current deployment (details) |
${context.res_class} |
Module:
|
The resource class of the resource (details) |
${context.res_id} |
Module:
|
The resource ID of the resource (details) |
${context.res_type} |
Module:
|
The resource type of the resource (details) |
${resources.<alias>.outputs.<traversal>} |
Module:
|
Extract output from a resource in the dependencies (details) |
${select.<function chain>.outputs.<traversal>} |
Module:
|
Extract outputs from multiple nodes in the resource graph (details) |
Context placeholders
These placeholders allow the behavior or results of a deployment or a module to change depending on its context.
The following context placeholders are available in the deployment manifest, module inputs, and resource parameters (params
) in dependencies or coprovisioning:
${context.org_id}
- The organization ID${context.project_id}
- The project ID${context.env_id}
- The environment ID${context.env_type_id}
- The environment type ID
The following context placeholders are more restrictive and only accessible within the definition of a module since they require knowledge of the resource graph node being provisioned. Specifically, they can be used in module inputs and resource parameters (params
) in dependencies or coprovisioning:
${context.res_type}
- The resource type of the resource provisioned by this module${context.res_class}
- The resource class of the resource. The default value is “default” but may be different if specified on resource creation${context.res_id}
- The resource ID of the resource. This depends on the location of the resource, whether the ID was set specifically or inherited
When used as params
in dependencies
, they will resolve to the value of the dependent (child) resource.
When used as params
in coprovisioning
, they will resolve to the value of the coprovisioned resource.
Resource placeholders
Resource placeholders are used in modules to refer to outputs of any resource defined in the module dependencies
section. The outputs may then be used as module inputs as well as in params
to other resources in the dependencies or coprovisioning section of the module:
dependencies:
some-resource:
type: some-resource-type
another-resource:
type: another-resource-type
params:
# Resource placeholder referring to the output "x" of the resource aliased as "some-resource"
some-param: "${resources.some-resource.outputs.x}"
The resource placeholder first refers to the resource alias, some-resource
in the example, which is the key of the resource in the dependencies
section and only used locally in the module. The resource placeholder then defines the output value to reference, x
in the example.
The syntax of a resource placeholder is of the form resources.<alias>.outputs.<traversal>
, e.g.
${resources.my-resource.outputs.something.key}
This resource placeholder refers to the key
field in the something
output of the resource defined by the my-resource
alias in the module.
An error will be thrown if no resource is specified by the alias or if the traversal cannot be resolved.
Selector placeholders
Selector placeholders are an advanced concept used in modules that allow extracting outputs from multiple nodes in the resource graph at the same time. The outputs may then be used as module inputs as well as in params
to other resources in the dependencies or coprovisioning section of the module.
The selector uses a chain of functions to traverse the graph. It starts at the resource node defined by the current module, this being the input to the first function in the chain. It then passes the resources found by each function to the next function in the chain which evaluates them one by one.
The syntax of a selector placeholder is select.<function chain>.outputs.<traversal>
, e.g.
${select.dependencies('dns.default#@').consumers('route').outputs.name}
This selector placeholder
- Selects all
dependencies
of the current resource which have the resource typedns
, classdefault
, and the same (@
) resource ID as the current resource - Selects all
consumers
of the resources from step 1. which have a resource typeroute
, regardless of class and ID
flowchart LR
currentResource --> dns2(DNS<br/>class: internal<br/>ID: main)
route1(Route<br/>class: something<br>ID: anything) -->|2#46; consumers| dns1
currentResource(Current resource<br/>class: default<br/>ID: main) -->|1#46; dependencies| dns1(DNS<br/>class: default<br/>ID: main)
route2(Route<br/>class: default<br>ID: main) --> dns2
class route1 highlight
linkStyle 1,2 stroke:#2156f6,stroke-width:4px
The selector always returns an array with zero ([]
) or more items as a result.
list
, set
, tuple
) or any
.The following functions are supported:
Selector function “dependencies”
The dependencies
function selects all nodes in the resource graph on which the input nodes depend and that match the filter. Only direct dependencies are considered.
flowchart LR
inputResource(Input resource) -->|"${select.dependencies(...)...}"| someResource(Some resource)
inputResource --> anotherResource(Another resource)
class someResource highlight
The function requires a filter which must be surrounded by single quotes: dependencies('filter')
. The filter must start with the resource type to match followed by optional class and ID filters. The class filter is prefixed with a .
. The ID filter must be at the end and is prefixed with a #
.
Examples:
dependencies('type-a')
will filter for all direct dependencies with resource typetype-a
, regardless of class or IDdependencies('type-a.default')
will constrain the selection to only those resources with classdefault
, regardless of IDdependencies('type-a#workloads.example.dep')
will constrain the selection to only resources with the IDworkloads.example.dep
, regardless of class
An @
symbol may be used to insert the current resource’s class or ID:
dependencies('type-a.@#@')
will filter for only the node with resource typetype-a
and exactly the class and ID of the current resource node for which this expression is evaluated
Selector function “consumers”
The consumers
function selects all nodes in the resource graph that depend on the input nodes and that match the filter. Only direct dependencies are considered.
flowchart LR
someResource(Some resource) -->|"${select.consumers(...)...}"| inputResource(Input resource)
anotherResource(Another resource) --> inputResource
class someResource highlight
The function requires a filter which must be surrounded by single quotes: consumers('filter')
. The filter operates exactly the same way as the filter parameters in the dependencies function above.
The “@” symbol in a function chain
A @
symbol is resolved locally for each function in a function chain. It refers to the resource node that is currently being handled by the function. Further down in the chain, this will not be the resource in whose module the selector is declared.
E.g. in this selector
${select.dependencies('dns.default#@').consumers('route.@').outputs.name}
the @
symbol is resolved like this:
dependencies('dns.default#@')
handles the resource of the current module, so the@
resolves to the ID of the resource in whose module this selector is definedconsumers('route.@')
handles thedns
resource(s) found via thedependencies
function, so the@
resolves to the class of thedns
resource currently being handled
Examples
Given this resource graph:
flowchart LR
workload(Workload<br/>type: workload<br/>class: default<br/>ID: main) --> type1(Type 1<br/>type: type1<br/>class: default<br>ID: workloads.main.type-1)
workload --> type2(Type 2<br/>type: type2<br/>class: default<br>ID: workloads.main.type-2)
type2 --> type3_1(Type 3-1<br/>type: type3<br/>class: default<br>ID: my-type-3)
type2 --> type3_2("Type 3-2<br/>type: type3<br/>class: default<br>ID: workloads.main-type-2<br/>(inherited ID)")
This placeholder in the the type2
module returns an array with two elements being the some_output
values of both type3
resources:
${select.dependencies('type3').outputs.some_output}
This placeholder in the type1
module returns an array with one element being the some_output
value of the type3
resource with ID my-type-3
:
${select.consumers('workload').dependencies('type2').dependencies('type3#my-type-3').outputs.some_output}
This modification of the same placeholder now returns the value of the type3
resource with ID workloads.main.type-2
instead by using the @
symbol which is evaluated for the type2
resource:
${select.consumers('workload').dependencies('type2').dependencies('type3#@').outputs.input_echo}