Using References

References let a you define a value once and point at it from everywhere it is needed, instead of repeating it. This page explains how to use references in the deployment configuration.

You can edit the configuration of a deployment in the configuration editor, refer toConfiguring a Deployment for details.

Why References Exist

A deployment configuration exists at two levels:

Level

Shape

Purpose

Project Configuration

A set of named configuration blocks: a JSON object whose top-level keys are block names, each block being a configuration object.

Values defined once for the whole project deployment.

Component Configuration

A single configuration object.

One component's own values.

The project level is intentionally composed of a series of named blocks, since these names are exactly what a component refers to when it makes a reference to them.

A component must never repeat a shared value or record a secret. It simply references them, and the platform resolves the reference at runtime.

Using a Reference: $references

$references is a reserved property on any configuration object, at any nesting level. Its value is an array of reference entries. It is not itself a configuration value, and no configuration option may use that key.

Two types of references exist:

Reference Type

Shape

Description

Secret Reference

{ "secretName": "<name>", "key": "<key>" }

Take the value from the named cluster secret.

Project-configuration Reference

{ "bundleDeploymentName": "<name>" | "SELF", "key": "<block>" }

Take the value from a block of a project deployment configuration.

Where each type is allowed:

  • Project configuration: secret references only. The blocks inside the project configuration are what components reference. It does not itself reference other blocks.

  • Component configuration: both types.

Example: Project configuration defines the shared block, taking the password from a secret

JSON
{
  "database": {
    "host": "pg.acme.internal",
    "port": 1234,
    "$references": [{ "secretName": "dashboard-db", "key": "password" }]
  },
  "apiBaseUrl": { "url": "https://dashboard.acme/api" }
}

Component configuration referencing it:

JSON
{
  "logger": { "level": "debug" },
  "db": {
    "$references": [{ "bundleDeploymentName": "SELF", "key": "database" }]
  },
  "upstream": {
    "$references": [{ "bundleDeploymentName": "SELF", "key": "apiBaseUrl" }]
  },
  "$references": [{ "secretName": "service-jwt", "key": "signingKey" }]
}

The component's db object ends up with host, port and password.

Note the chain: the component references the project block, the project block references the secret. The component never names the secret, so changing it is a one-place change.
Note also the $references at the root of the component object: references are not restricted to nested objects.

Combining References With Fixed Values

An object may carry direct values, multiple references, and nothing else at the same time. When more than one source supplies the same option, resolution follows a fixed order:

default < referenced < direct

  • default: Embedded in the component's own image, not specified anywhere in the configuration.

  • referenced: Pulled in through $references.

  • direct: Written verbatim in that configuration object.

Example:

Writing "host": "localhost" next to a $references entry that also supplies host wins: the direct value overrides the referenced one.

A Reserved Value: SELF

SELF is a reserved value that stands in place of a project deployment name and means the project deployment this configuration belongs to.

It exists because of a timing problem: a component's configuration is written when the project is built, while the deployment it becomes part of is named when someone deploys it. The developer cannot know that name during development, so he cannot use it. SELF is how a developer can say my own deployment without knowing the deployment’s name.

Rules that are important in practice:

  • SELF is the one spelling that carries the meaning.
    Deployment names admit lowercase characters only, so SELF can never collide with a real name.
    Writing self refers to an ordinary deployment actually called self.

  • Writing a concrete name instead reaches a different deployment.
    This is useful when your project is deployed alongside another whose values it needs. That deployment then has to exist on the same platform.

  • SELF reference is resolved to a name once, before the configuration is stored.
    When the project is deployed, every SELF is rewritten to the actual project deployment's name. Everything that follows, every re-read layer, the resolved configuration, and the links between components and configuration entries, relies exclusively on names during deployment.

  • Consequence in the Control Hub: 
    The initial configuration shown in the editor displays the real deployment name, not SELF, even though the developer wrote SELF. The content of the reference is preserved. Its spelling, however, is not.

  • An operator may type SELF in the editor.
    It is stored against their own project deployment by name, exactly as an initial one is.

Meaning in the Configuration Editor

  • References are shown as declared, never resolved.
    The editor displays the entries under $references exactly as they are, it does not substitute the values behind them. Resolution to concrete values happens in the platform Runtime when the resolved configuration is applied. Secret values therefore never appear in the editor, and never in the sources or the published project version either.

  • Existence is not validated when you save.
    Neither a referenced deployment nor a referenced key is checked at save time. The reference is stored as written and fails at runtime if the secret, block, or key is not there. Validation in the editor covers JSON well-formedness and the configuration schema, not the targets.

  • The operator's values are a separate layer.
    What you edit is the user configuration. It will be combined with the initial configuration: Your custom values will override the values from the initial configuration.

  • $references is an array, and arrays replace rather than merge.
    If your user configuration sets $references on an object, it supersedes the shipped $references array for that object as a whole. You cannot add a single entry to it, you restate the list.

  • A reference can be added by the operator too.
    References are not a build-time-only device. You can introduce a secret reference or a project-configuration reference in the editor exactly as a developer would in the shipped file.

đź“—