When writing architect.yml files, you can reference information about the runtime or environment, details that are otherwise unique to each deployed environment, through Architect’s expression syntax. Encoding component’s with these references can help limit the manual configuration needs of your services and make them portable from environment to environment.

Available contexts

There are several context groups that contain important, dynamic information about your component and its future deployed environment. Below are the context categories available for reference:

Context nameDescription
dependenciesReferences to the dynamic outputs of each dependency and their interfaces
secretsDynamic values for the secrets declared by your component
servicesReferences to the dynamic outputs of each service and their interfaces
databasesReferences to the dynamic outputs of each database

dependencies context

The dependencies context contains dynamic information about the dependencies of the component. This context can primarily be used to refer to the internal addresses of dependency interfaces.

PropertyTypeDescription
dependenciesobjectInformation about the component’s dependencies
dependencies.<dependency>objectInformation about the specified dependency
dependencies.<dependency>.interfacesobjectInformation about the dependency’s interfaces
dependencies.<dependency>.interfaces.<interface>objectInformation about the specified interface of the dependency. See the interface values for more details.
dependencies.<dependency>.interfaces.<interface>.ingressobjectInformation about the specified interface of the dependency. See the interface values for more details.

ingresses context

The ingresses context contains information about the external exposed interfaces.

PropertyTypeDescription
ingressesobjectInformation on the ingress rules of the component
ingresses.<interface>objectInformation on an ingress rule matching the interface. See the interface values for more details.

secrets context

The secrets context contains all the values assigned to each secret declared by your component.

PropertyTypeDescription
secretsobjectA dictionary containing the secret values
secrets.<key>stringResolves to the value of the specified secret

services context

The services context contains dynamic information about all the services inside the component. This context can primarily be used to refer to the interfaces of other services inside the component.

PropertyTypeDescription
servicesobjectInformation about each service inside the component
services.<service>objectInformation specific to one of the named services inside the component
services.<service>.interfacesobjectInformation about the specified service’s interfaces
services.<service>.interfaces.<interface>objectInformation about the specified service interface. See the interface values for more details.
services.<service>.interfaces.<interface>.ingressobjectInformation about the specified service interface. See the interface values for more details.

databases context

The databases context contains dynamic information about all the databases inside the component. This context is primarily used to refer to the address and credentials of each database instance.

PropertyTypeDescription
databasesobject
databases.<name>object
databases.<name>.urlstringFully resolvable URL of the database (alias: connection_string)
databases.<name>.hoststringHostname of the database
databases.<name>.portintPort the database is exposed on
databases.<name>.protocolstringProtocol the database responds to
databases.<name>.usernamestringUsername used to authenticate with the database
databases.<name>.passwordstringPassword used to authenticate with the database
databases.<name>.databasestringThe database (e.g. namespace) on the instance to be connected to

interface values

Interface values are referenced in many places, dependencies and services with a set of uniform values available to reference. These values include:

PropertyTypeDescription
urlstringThe fully composed URL of the reference interface. This will take the format, <protocol>://<username>:<password>@<host>:<port><path>.
protocolstringThe protocol of the interface being referenced. This will always be the specific value assigned to the interface by the developer.
usernamestringThe username of the interface being referenced. Not all interfaces have usernames, so this will be an empty string if none is set.
passwordstringThe password of the interface being referenced. Not all interfaces have passwords, so this will be an empty string if none is set.
hoststringThe host value of the interface being referenced. This value is usually dynamic to accomodate the differences between service discovery solutions available to each environment.
portintThe port value of the interface being referenced. This will not always be the specific port that the interface is listening on as many container clusters leverage port mapping to ensure that there are no port collisions when sharing hardware in a cluster.
pathstringThe path value of the interface being referenced. Not all interfaces have paths, so this will be an empty string if none is set.

Interpolation

Interpolation is used in the architect.yml component configuration file to reference values in contexts defined by Architect. Common use cases for interpolation include referencing the address of another service within the component, the address of a dependent component, a secret of the component, an ingress of a service, and more. An interpolation reference always starts with ${{ and ends with }}. When the component is deployed with either architect dev or architect deploy, any interpolation references in the component file will be populated with real values.

Examples of common use cases

Referencing a secret

Secrets will frequently be defined in the component configuration file and will be populated when the component is deployed. It will then be referenced in a part of a service, such as the environment block.

# architect.yml
name: app

secrets:
  api_key:

services:
  app:
    environment:
      API_KEY: ${{ secrets.api_key }}
...

Referencing the internal address of another service

Services within the same component will often need to reference one another within the same network. In the example below, the “app” service references the internal address of the “api” service.

# architect.yml
name: my-component

services:
  app:
    environment:
      API_ADDRESS: ${{ services.api.interfaces.main.url }}

  api:
    interfaces:
      main:
        port: 8080
...

Referencing the external address of another service

Services within the same component will sometimes need to reference one another from outside of the network. A common case is when a frontend application needs to make calls to an API from a browser. In the example below, the “app” service references the external, public-facing address of the “api” service. The external address of the API service is generated automatically by Architect when the component is deployed.

# architect.yml
name: my-component

services:
  app:
    environment:
      API_ADDRESS: ${{ services.api.interfaces.main.ingress.url }}

  api:
    interfaces:
      main:
        port: 8080
        ingress:
          subdomain: api
...

Referencing the address of a dependency

In certain cases, a component will reference another Architect component as a dependency, and an address of a service within that dependency will need to be referenced. Take the following example of two components, where the “api” component is a dependency of the “app” component.

# architect.yml of the api component
name: api

services:
  api:
    interfaces:
      main:
        port: 8080
        ingress:
          subdomain: api
...
# architect.yml of the app component
name: app

dependencies:
  api: latest

services:
  app:
    environment:
      API_ADDRESS: ${{ dependencies.api.services.api.interfaces.main.ingress.url }}
...

Example of a simple component with interpolation

The following example component uses the Docker image built by our “node-rest-api” example project and connects the API to a Postgres database. ${{ services.database.interfaces.main.url }} is used to allow the database to connect to the API. When the component is deployed, the interpolation reference will be replaced by an automatically-generated network address where the database service can be reached. Secrets are passed to each service with secret interpolation such as ${{ secrets.db_name }}. The secret interpolation references will be replaced by actual secret values when the component is deployed.

# architect.yml
name: api-example

secrets:
  db_user:
    default: architect
  db_pass:
    default: secret
  db_name:
    default: api-db

services:
  # Application service
  api:
    image: registry.gitlab.com/architect-io/docker-files/sample-backend:latest
    interfaces:
      main:
        port: 8080
        ingress:
          subdomain: api
    environment:
      DB_ADDR: ${{ services.database.interfaces.main.url }}/${{ secrets.db_name }}
      DB_USER: ${{ secrets.db_user }}
      DB_PASS: ${{ secrets.db_pass }}
      PORT: 8080

  # Database service
  database:
    image: postgres:12
    interfaces:
      main:
        port: 5432
        protocol: postgresql
    environment:
      POSTGRES_USER: ${{ secrets.db_user }}
      POSTGRES_PASSWORD: ${{ secrets.db_pass }}
      POSTGRES_DB: ${{ secrets.db_name }}