Skip to content
kix /docs
Install the CLI

Reference kix helpers

Reusable option sets

The option declarations, option types, and guard helpers that packages share: kix.options, kix.types.quantity, kix.mergeEnv, kix.guardArgs, and kix.checkSecretKeys.

These helpers give every package the same option shapes for images, resources, environment variables, monitoring, and probes, and the same checks for the values a package owns. Each default sits on its own field, so an instance that sets one field keeps the package’s other defaults.

This page is maintained by hand. Check kix/lib/vocab/compose.nix and kix/lib/vocab/quantity.nix when in doubt.

HelperDeclaresFields
kix.options.image { repository; tag; ... }one optionrepository, tag, digest, pullPolicy. See image.
kix.options.resources { requests ? { }; limits ? { }; }one optionrequests, limits, claims
kix.options.envone optionattribute set of variables
kix.options.ingressan option sethost, annotations
kix.options.monitoran option setenabled, interval. See monitor.
kix.options.healthCheckan option setenabled, retryFor. See healthCheck.

A helper that takes arguments returns an option. An option set is an attribute set of options, used as options.metrics = kix.options.monitor;. A toggle that turns a feature on is named enabled.

options.resources = kix.options.resources {
requests = { cpu = "100m"; memory = "128Mi"; };
limits.memory = "256Mi";
};

The arguments are the package’s defaults. They may set cpu, memory, and ephemeral-storage. Each one becomes the default of its field, so an instance that sets limits.cpu keeps the requests and the memory limit:

instances.apps.web.config.resources.limits.cpu = "1";
# requests = { cpu = "100m"; memory = "128Mi"; }; limits = { cpu = "1"; memory = "256Mi"; };

Setting a field to null removes its default. The value is a Kubernetes ResourceRequirements with unset fields absent, so it can go straight into a container’s resources:

FieldType
requests, limitscpu, memory, and ephemeral-storage as null or a quantity, plus any other resource name as a quantity
claimsnull, or a list of { name; request ? null; }

Other resource names are hugepages-<size> and extended resources whose name contains /, such as nvidia.com/gpu. Any other name, such as a misspelled limits.memroy, fails evaluation.

An attribute set whose values are a string, a fieldRef source such as { valueFrom.fieldRef.fieldPath = "metadata.name"; }, or a secretKeyRef source naming a Secret managed outside Kix with kix.untrackedRef. A credential that comes from a dependency is wired by the package. null removes a variable the package sets by default. An integer, such as PORT = 8080, fails evaluation; write "8080".

Render it with kix.mergeEnv, so the instance cannot replace a variable the package owns.

An option type for a Kubernetes quantity, such as "500m", "1.5Gi", or 2. It accepts a non-negative decimal or integer with an optional suffix: m, k, M, G, T, P, E, Ki, Mi, Gi, Ti, Pi, or Ei. Kubernetes also accepts signs and exponents (1e3); this type does not.

options.size = lib.mkOption {
type = kix.types.quantity;
default = "10Gi";
description = "Size of the data volume.";
};

kix.parseQuantity resource q returns q in millicores when resource is "cpu", and in bytes otherwise, rounded down to an integer. It returns null when q is not a quantity. Every value kix.types.quantity accepts parses.

kix.parseQuantity "cpu" "250m" # 250
kix.parseQuantity "memory" "512Mi" # 536870912

Kix computes quantities in signed 64-bit integers. A value above that range, such as "8Ei", or one with more than 18 significant digits, is an evaluation error, and kix.types.quantity refuses it. Leading zeros and trailing zeros after the decimal point do not count. The type checks the range in bytes, so a cpu value it accepts can still be out of range in millicores ("2Ei"); the limits-versus-requests check then fails and names the container field.

Each guard takes who, the text that starts its error. Use the instance’s <package> <namespace>/<instance>.

env = kix.mkEnvVars (kix.mergeEnv {
inherit who;
defaults.LOG_LEVEL = "info";
owned = [
{
vars.DB_HOST = database.out.fqdn;
from = "the database dependency";
fix = "Wire a different database instance through deps.database instead.";
}
];
} config.env);

Returns defaults, then the instance’s env, then every group’s vars. An instance may override or remove (null) a default. A variable in an owned group may not appear in env, even as null:

web apps/web: env sets DB_HOST, which comes from the database dependency. Wire a different database instance through deps.database instead.

A group may list names instead of vars for variables the package delivers another way, such as envFrom. They are refused the same way and not added.

args = baseArgs ++ kix.guardArgs {
inherit who;
owned."--metrics-bind-address" = "the probes and the metrics Service use :8080; remove it.";
} config.extraArgs;

Returns the list unchanged unless an argument sets an owned flag. An argument sets a flag when it equals the flag or starts with the flag and =, so --ingress-class-by-name=true does not set --ingress-class. A one-letter flag such as -c also matches an argument that starts with it, such as -c/etc/x, the attached-value form getopt and clap accept. For a Go program, whose single-dash flags can be whole words, an owned -v would therefore also refuse -vmodule=x. option (default "extraArgs") names the option in the error. Each hit is one line:

web apps/web: extraArgs sets "--metrics-bind-address=:9090", which the package owns: the probes and the metrics Service use :8080; remove it.
creds = kix.checkSecretKeys {
inherit who;
arg = "cloudCredentials";
dep = cloudCredentials;
keys = [ "cloud" ];
};

Returns dep once its out.keys declares every name in keys. With anyOf, a list of key groups, every name of at least one group must be declared. A null dep (an absent optional dependency) is returned as is. Read the secret through the returned value, so the check runs before any keyRef:

velero backup/velero: deps.cloudCredentials resolved to secret "aws", which declares no keys; this package reads cloud. Add them to that instance's keys (a SOPS secret lists them in keys), or wire another secret with deps.cloudCredentials = ref.<ns>.<instance>.

Every package keeps a way to set what it does not model. The option name says what it changes and how it merges:

Shape the package buildsOptionMerge
A Helm chartvalueslib.recursiveUpdate over the package’s values
A resource or custom resource specextraSpeckix.mergeGuarded over the package’s spec; the option description lists the paths the package owns
The program’s own configuration filesettingskix.mergeGuarded over the built-in configuration
A program’s command-line flagsextraArgsappended after the package’s flags, through kix.guardArgs
Anything elseinstance partsOverlays, resource extrasee partsOverlays

kix.mergeGuarded refuses an override of a path the package owns. It also refuses an override that sets an ancestor of an owned path to a value that is not an attribute set, because that value would replace the owned path too: with common.path_prefix owned, settings.common = null is an error. A package that offers settings drops null values after the merge (lib.filterAttrsRecursive (_: v: v != null)), so an instance removes a built-in key it does not own by setting it to null.