Why Dependencies?

Most applications have either explicit or implicit dependencies between the different components that comprise them.

For example, given an app that comprises a Helm chart component and a Terraform component:

In this example, the helm chart requires that the database be provisioned before it is deployed. Otherwise, the database will not exist yet, and the database_url output will not be defined.

When deprovisioning the install, the helm chart must be deprovisioned before the database, to ensure no active dependencies exist, preventing the database from being shut down.

Defining Component Dependencies

To support this, you can define one or more dependencies on each component, telling Nuon what other components it relies on. Nuon will use your configuration to build a dependency graph, to ensure components are provisioned and deprovisioned in the correct order.

The dependency graph is directed and acyclic, which means circular dependencies are not supported. Nuon checks for cycles and will error if you attempt to define one.

TOML

If you’re using the TOML config, dependencies will be inferred from the order of the components in the file. Every component will automatically depend on the component defined before it. If you re-order the components in the file, the dependencies will be updated.

Taking the example above, you can make the Helm chart depend on the database by simply reversing their order in the file.

# Move the helm_chart component from up here...

[[components]]
name              = "database"
type              = "terraform_module"
terraform_version = "v1.6.3"
[components.connected_repo]
directory = "components/database"
repo      = "<your-org>/<your-repo>"
branch    = "main"

# to down here.
[[components]]
name       = "helm"
type       = "helm_chart"
chart_name = "helm"
[components.connected_repo]
directory = "components/helm"
repo      = "<your-org>/<your-repo>"
branch    = "main"
[components.values]
database_url = "{{.nuon.components.database.outputs.database_url}}"

Terraform

Terraform doesn’t care how you order resources in your configs, you must explicitly define dependencies when using the Terraform provider. While this requires a bit more work, it does give you full contol over the dependency graph.

To define the dependencies for a component, add a dependencies field referencing the IDs of the other components that it depends on.

resource "nuon_helm_chart_component" "helm" {
  name       = "helm"
  app_id     = nuon_app.<your-app>.id
  chart_name = "helm"

  connected_repo = {
    directory = "components/helm"
    repo      = "<your-org>/<your-repo>"
    branch    = "main"
  }

  value = {
    name  = "database_url"
    value = "{{.nuon.components.database.outputs.database_url}}"
  }

  dependencies = [
    nuon_terraform_module_component.database.id
  ]
}

resource "nuon_terraform_module_component" "terraform" {
  name   = "database"
  app_id = nuon_app.<your-app>.id
  terraform_version = "v1.6.3"

  connected_repo = {
    directory = "components/database"
    repo      = "<your-org>/<your-repo>"
    branch    = "main"
  }
}

Install Provisioning

When an install is provisioned, Nuon will generate a graph of the app based on the defined dependencies. Nuon will automatically deploy the latest build of each component to the install. In the previous example, this means that the database component would be deployed before the Helm chart.

For example, when you create a new install, each component will automatically be deployed:

nuon installs create

To check the status of each component on the install:

nuon installs components

Install Deprovisioning

When an install is deprovisioned, Nuon will generate a graph of all the deployed components on the install, and walk them in reverse, to deprovision them properly. In the previous example, this means the helm component would be deprovisioned before the database.