akua / examples / 13-subpackage-helm

13-subpackage-helm

This example shows package composition across a local path dependency. The root `package.k` imports `pkgs.webserver` and calls `webserver.render(webserver.Input{...})`; the `webserver` sub-package...

Composes an Akua sub-package that owns its own Helm chart dependency. The root package passes typed inputs down through pkgs.webserver while the sub-package resolves and renders its chart.

This example shows package composition across a local path dependency. The root package.k imports pkgs.webserver and calls webserver.render(webserver.Input{...}); the webserver sub-package declares a Helm chart dependency in its own akua.toml. At render time, Akua resolves the sub-package chart context and exposes it to the sub-package implementation.

What's here

filepurpose
package.kRoot package that delegates rendering to pkgs.webserver.
akua.tomlDeclares webserver = { path = "./deps/webserver" }.
deps/webserver/Sub-package with its own Helm chart dependency.
inputs.example.yamlNamespace input passed from the root to the sub-package.
rendered/Reference output committed for integration tests.

Render

akua render --out ./rendered

The interesting part is the import boundary: root package inputs remain typed at the call site, and chart resolution stays local to the sub-package that declared the chart.

package.k

import akua.ctx
import pkgs.webserver as ws

# Root Package: composes the `webserver` sub-package, which itself
# renders a local Helm chart. Demonstrates that `charts.*` context
# propagates through `pkgs.<alias>` composition — a sub-package can
# declare its own Helm chart dep and have it resolved at render time.
#
# Render:
#
#   akua render --out ./rendered
schema Input:
    """Public inputs for the subpackage-helm root Package."""
    namespace: str = "demo"
    """Kubernetes namespace passed down into the sub-package's chart render."""

input: Input = ctx.input()

# Delegate entirely to the sub-package. The synthesized `pkgs.webserver`
# stub owns the `render` lambda; `ws.Input` type-checks here — typos
# surface as KCL compile errors, not runtime failures.
resources = ws.render(ws.Input {
    namespace = input.namespace
})

Rendered output

000-deployment-web-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: web
  name: web-nginx
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx:1.27
        name: nginx
        ports:
        - containerPort: 80

Source: examples/13-subpackage-helm/