Skip to content
kix /docs
Install the CLI

How-to guide Debug dependency wiring

Use auto-instantiation with availablePackages, optional, and autoNamespace

Install default packages only when another instance needs them, and keep configured instances dormant until they are required.

Use auto-instantiation when a cluster has a standard package for a dependency, but should include it only when something needs it. Use an optional instance when you also need to configure that dormant provider.

This guide assumes you already have packages whose required build arguments describe their dependencies.

In the consuming package, make each dependency a required build argument. This application reads values from database and metrics:

how-to/auto-instantiation/application-package.nix
build =
{
self,
database,
metrics,
...
}:
{
configMap = scope.mkResource {
apiVersion = "v1";
kind = "ConfigMap";
name = scope.instanceName;
data = {
databaseResource = database.out.name;
metricsResource = metrics.out.name;
};
};
root = self.configMap;
};

View source on GitHub ↗

Required arguments create demand. Kix first looks for a matching instance or alias, then consults the cluster’s package catalog.

Add the package under the dependency name in availablePackages. Set autoNamespace if auto-instantiated packages should live in a shared namespace:

how-to/auto-instantiation/cluster.nix
# Catalog entries stay absent until a required package argument asks
# for one. autoNamespace chooses where Kix creates the instance.
availablePackages.database = {
package = databasePackage;
};
autoNamespace = "platform";

View source on GitHub ↗

When an instance requires database, Kix creates a database instance in platform with the package’s default configuration. Without autoNamespace, Kix creates it in the requesting instance’s namespace. A namespace set on the individual catalog entry takes precedence over autoNamespace.

An availablePackages entry is instantiated with default configuration. When the provider needs cluster-specific configuration, declare a normal instance and set optional = true:

how-to/auto-instantiation/cluster.nix
# This configured instance is dormant until another package requires
# an argument named `metrics`.
instances.platform.metrics = {
package = metricsPackage;
optional = true;
config.retentionDays = 14;
};

View source on GitHub ↗

Kix excludes this instance when nothing depends on metrics. A required metrics argument activates it with the configuration shown above. So does a consumer that wires it explicitly with deps.<arg> = ref.platform.metrics, whatever the argument is called.

Declare only the package you intend to run directly:

how-to/auto-instantiation/cluster.nix
# applicationPackage requires both `database` and `metrics`. That
# demand creates the catalog package and activates the optional one.
instances.apps.api = {
package = applicationPackage;
};

View source on GitHub ↗

The package’s required arguments pull both providers into the evaluated cluster. This also works transitively when an activated provider has required dependencies of its own.

Evaluate the cluster:

kix-examples/
❱ kix check how-to-auto-instantiation
 TOOL       RESULT  DETAILS                      
 eval       pass    14 manifests evaluated       
 scorecard  pass    0 errors, 3 warnings, 0 info

Inspect the dependency graph to confirm where the providers were created:

kix-examples/ offline capture
❱ kix graph how-to-auto-instantiation --format tree
Show outputHide output · 42 lines
CustomResourceDefinition/activations.kix.run
└── Activation/how-to-auto-instantiation-phi1mn14g2sg
CustomResourceDefinition/packageinstances.kix.run
├── PackageInstance/metrics@platform
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
├── PackageInstance/database@platform
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
├── PackageInstance/platform-storage@kube-system (import)
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
├── PackageInstance/platform-dns@kube-system (import)
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
└── PackageInstance/api@apps
    └── Activation/how-to-auto-instantiation-phi1mn14g2sg
Namespace/apps
├── ConfigMap/api@apps
│   └── PackageInstance/api@apps
│       └── Activation/how-to-auto-instantiation-phi1mn14g2sg
└── PackageInstance/api@apps
    └── Activation/how-to-auto-instantiation-phi1mn14g2sg
Namespace/kube-system
├── PackageInstance/platform-storage@kube-system (import)
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
└── PackageInstance/platform-dns@kube-system (import)
    └── Activation/how-to-auto-instantiation-phi1mn14g2sg
Namespace/platform
├── ConfigMap/metrics@platform
│   ├── ConfigMap/api@apps
│   │   └── PackageInstance/api@apps
│   │       └── Activation/how-to-auto-instantiation-phi1mn14g2sg
│   └── PackageInstance/metrics@platform
│       └── Activation/how-to-auto-instantiation-phi1mn14g2sg
├── ConfigMap/database@platform
│   ├── ConfigMap/api@apps
│   │   └── PackageInstance/api@apps
│   │       └── Activation/how-to-auto-instantiation-phi1mn14g2sg
│   └── PackageInstance/database@platform
│       └── Activation/how-to-auto-instantiation-phi1mn14g2sg
├── PackageInstance/metrics@platform
│   └── Activation/how-to-auto-instantiation-phi1mn14g2sg
└── PackageInstance/database@platform
    └── Activation/how-to-auto-instantiation-phi1mn14g2sg
14 resources, 24 dependencies

The graph contains database@platform, metrics@platform, and api@apps. Both provider ConfigMaps appear before the application ConfigMap that consumes their outputs.

Choose between catalog packages that answer one name

Section titled “Choose between catalog packages that answer one name”

A catalog entry answers its own name, the package’s meta.roles and meta.defaultAliases, and the entry’s aliases. When a required argument names something more than one entry answers, Kix stops the build. Here a second entry, postgres, lists database among its aliases:

kix-examples/ output excerpt
❱ kix check how-to-auto-instantiation
error: kix: dependency 'database' of apps/api has no instance, and 2 packages in availablePackages provide it:                                           
database (package name)                                                                                                                                
postgres (availablePackages.postgres.aliases)                                                                                                          
Kix does not choose between them. Declare the one this cluster uses as an optional instance, which is created only when something depends on it:         
instances.<namespace>.database = { package = packages.<one of the above>; optional = true; };                                                          
or remove the others from availablePackages.
(exit code: 1)

The error lists each entry and why it answers the name. To choose one, declare it as an optional instance named after the dependency. Kix looks for instances before the catalog, and still creates this one only when something depends on it:

cluster.nix
instances.platform.database = {
package = databasePackage;
optional = true;
};

Alternatively, remove the other entries from availablePackages.

When the name is a role the environment already provides, set cluster.roles.<role>.binding instead.

A name several entries answer is not an error while nothing requires it, so a catalog built from a whole package set still evaluates. An argument the consumer wires with deps.<arg> makes no demand on the catalog.