Imported from CallePuzzle/jsonnet-lib-manifests (
AGENTS.md). Install upstream withnpx skills add CallePuzzle/jsonnet-lib-manifests. Copyright stays with the author.
AGENTS.md
Guidance for AI coding agents working in this repository. Assumes no prior knowledge of the project.
Project overview
This is a Jsonnet library (published/consumed as a jsonnet-bundler package) that generates Kubernetes manifests for node/container workloads, plus a few Argo CD helper resources. It is not an application — the top-level .libsonnet files are reusable building blocks that downstream projects import and parameterize.
- Language: Jsonnet
- Dependency/tooling ecosystem: jsonnet-bundler (
jb), Grafana Tanka (tk),jsonnet - License: Apache-2.0 (see
LICENSE)
Dependencies are declared in jsonnetfile.json and vendored into vendor/ (gitignored). jsonnetfile.lock.json is committed and pins each dependency to a specific git SHA, so CI and consumers are reproducible. The same SHAs are written in jsonnetfile.json (as a fallback for tools that don't read the lockfile):
github.com/grafana/jsonnet-libs/ksonnet-util(kausal utilities, e.g.k.util.serviceFor)github.com/jsonnet-libs/docsonnet/doc-utilgithub.com/jsonnet-libs/k8s-libsonnet/1.32(typed Kubernetes API builders)
Repository layout and module division
Each top-level file is an independent, composable module. The recurring pattern is: an object with a hidden values:: field of parameters, and one or more visible output fields built from those values. Consumers override parameters with values+:: (see the tests for examples).
app.libsonnet— top-level composition: builds a full app (workload + HPA + optional Service + optional Ingress) from shared params. Service is emitted only whenvalues.port != null; Ingress only whenvalues.port != nullandvalues.serverAlias != null(the Ingress targets the generated Service); HPA only whenutils.hasHpa(...)is true.workload.libsonnet— the KubernetesDeployment(namespace, labels, annotations, security context, image pull secrets, init containers,deploymentMixin). Replicas are set tonullwhen an HPA is active. EmptypullSecret/containersInit/podAnnotationsare omitted from the rendered output. Pod security context only whenuserIdis set;pullSecrettakes Kubernetes objects ([{ name: '...' }]), not strings.workload-extra.libsonnet—HorizontalPodAutoscaler(autoscaling/v2, CPU utilization), emitted only whenutils.hasHpa(...)is true.selfHealis configurable.minReplicas: 0is allowed (scale-to-zero, requires HPAScaleToZero). Thehpaoutput isnull(not an empty object) when inactive, so Tanka drops it.container.libsonnet— the main container spec (ports, resources, probes, env, security context,containerMixin). Has its own localvalues::defaults.readinessProbe/livenessProbe/startupProbe/env/envFromare only emitted when non-null/non-empty.params.libsonnet— shared default parameters imported byapp,workload,workload-extra, andingress. Required values useerror '... not set'(e.g.name,image,namespace). Optional resources arenullby default:port,serverAlias.userIdis consumed byworkload/containerbut defaults tonull— consumers must set it to enable the non-root security contexts.ingress.libsonnet— nginx Ingress with a single host rule fromserverAlias/serverAliasPath. HardcodesingressClassName: 'nginx'and embeds the host in the resource name (<name>-<serverAlias>).argocd-app.libsonnet— raw (untyped, plain-object) Argo CDApplicationresource.sourceonly includes the fields the consumer actually configured (no nullpath/chart/plugin).path,chartandpluginare pairwise mutually exclusive and produce a runtime error if combined;pluginalone is valid.autoSyncaddspruneandselfHeal;targetRevisiondefaults to'HEAD'. HelmchartValuesgo throughstd.native('regexSubst')(Tanka-only) to keeptk diffclean.argocd-repository.libsonnet— Argo CD repositorySecret(supports basic auth, SSH key, or unauthenticated git). Setting only one ofusername/passwordis a runtime error. IfsshPrivateKeyis set together withusername/password, the SSH key takes precedence.secret-stringData.libsonnet— generic KubernetesSecretwithstringDataand an Argo CD sync-wave annotation.syncWaveis configurable (default'10').utils.libsonnet— small helpers (currently justhasHpa).lib/k.libsonnet— local alias that re-exports the k8s-libsonnet 1.32 entrypoint, so modules canimport 'k.libsonnet'.
Import style varies: modules import k.libsonnet via the lib/ path (resolved through the vendor/jb path), while app.libsonnet imports kausal.libsonnet by its full legacy github path (legacyImports: true in jsonnetfile.json).
Build and test commands
There is no build step — Jsonnet is interpreted. Tooling commands:
jb install -q # install/vendor dependencies
tk fmt . # format (CI runs this)
tk lint . # lint (CI runs this)
tk show test/argocd-app --dangerous-allow-redirect # render test manifests
tk show test/svelte-template --dangerous-allow-redirect
tk show test/secret-stringData --dangerous-allow-redirect
tk show test/svelte-minimal --dangerous-allow-redirect
Testing strategy
Tests are Tanka environments under test/, each with a spec.json (Tanka environment config) and a main.jsonnet that imports the library modules and overrides values+:: with concrete parameters. Several tests include assert statements that validate the rendered output (namespaces, omitted fields, configurable sync-waves, etc.) — tk show will fail at evaluation time if the assertions don't hold.
test/argocd-app/— exercisesargocd-app.libsonnetwith all three source kinds (path,chartwith helm values,plugin-only) andargocd-repository.libsonnet(withsshPrivateKey).test/svelte-template/— exercises the fullapp.libsonnetcomposition (deployment, HPA, ingress, service) and asserts all four resources sharevalues.namespace.test/secret-stringData/— exercisessecret-stringData.libsonnetwith the default and a customsyncWave, asserting both values land in the annotation.test/svelte-minimal/— exercises theapp.libsonnetcomposition withport: nulland noserverAlias/HPA, asserting that Service, Ingress and HPA are not emitted, plus a second app withserverAliasbut noportasserting that no Ingress is emitted without a Service.
"Passing" means tk show renders without errors (including assertion failures). CI (.github/workflows/test.yaml, runs on PRs to main) installs Tanka 0.26.0 and Jsonnet, then runs jb install, tk fmt, tk lint, and tk show on all four test environments. When modifying a module, extend or run the corresponding test environment to verify rendering.
Code style conventions
- Follow the existing Jsonnet idiom: 2-space indent,
localbindings at the top of the file/object, builder-style chaining with+(e.g.deployment.metadata.withLabels(...)). - Parameter objects are hidden fields (
values::); required parameters are expressed aserror '<name> not set'(or'... is required'in the argocd modules — match the module you're editing). - Conditional fields use
if ... then {...} else {}merged with+(see_serviceinapp.libsonnet,args/command/_portincontainer.libsonnet). - Extension points for consumers:
containerMixin,deploymentMixin,labels,annotations— preserve these when editing. - Run
tk fmt .before committing; CI enforces formatting and linting.
Security considerations
- Modules that produce Secrets (
argocd-repository.libsonnet,secret-stringData.libsonnet) take credentials as Jsonnet values — never commit real credentials intotest/fixtures or parameter defaults (existing tests use placeholder strings like'ssh-private-key'). - Non-root execution is opt-in: set
userIdand both pod and container security contexts are emitted (runAsUser/fsGroup); whenuserIdisnullthe security contexts are omitted. Do not reintroduce unconditional security contexts or hidden non-root defaults.