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.
Declare the dependencies
Section titled “Declare the dependencies”In the consuming package, make each dependency a required build argument. This
application reads values from database and metrics:
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; };Required arguments create demand. Kix first looks for a matching instance or alias, then consults the cluster’s package catalog.
Add a default package to the catalog
Section titled “Add a default package to the catalog”Add the package under the dependency name in availablePackages. Set
autoNamespace if auto-instantiated packages should live in a shared
namespace:
# 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";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.
Keep a configured provider dormant
Section titled “Keep a configured provider dormant”An availablePackages entry is instantiated with default configuration. When
the provider needs cluster-specific configuration, declare a normal instance
and set optional = true:
# This configured instance is dormant until another package requires # an argument named `metrics`. instances.platform.metrics = { package = metricsPackage; optional = true; config.retentionDays = 14; };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.
Add the consumer
Section titled “Add the consumer”Declare only the package you intend to run directly:
# applicationPackage requires both `database` and `metrics`. That # demand creates the catalog package and activates the optional one. instances.apps.api = { package = applicationPackage; };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.
Check the result
Section titled “Check the result”Evaluate the cluster:
❱ 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 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 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:
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.