Skip to content

Architecture

Franklin García edited this page Sep 6, 2026 · 4 revisions

Architecture

Timonel sits between typed Kubernetes construction and Helm chart packaging.

Resource hierarchy

Use the highest-level typed abstraction that fits the resource:

  1. cdk8s-plus-33 for stable high-level Kubernetes constructs.
  2. cdk8s.ApiObject for a resource that needs a lower-level typed representation.
  3. Timonel resource helpers for recurring supported patterns, such as AWS storage or Karpenter.
  4. Rutter.addManifest(object, id) for CRDs or custom resources without a suitable construct.
  5. Raw YAML only for legacy compatibility.

This is intentionally different from a YAML-first Helm generator. Timonel does not ask you to give up the cdk8s construct tree.

Rutter owns a chart

Rutter creates a cdk8s.Chart. You can attach native constructs through getChart():

import * as kplus from 'cdk8s-plus-33';
import { Rutter } from 'timonel';

const rutter = new Rutter({
  meta: { name: 'orders', version: '1.0.0' },
});

new kplus.ConfigMap(rutter.getChart(), 'Config', {
  metadata: { name: 'orders-config' },
  data: { mode: 'production' },
});

If you already own a construct tree, pass a scope:

import { App } from 'cdk8s';
import { Rutter } from 'timonel';

const app = new App();
const chart = new Rutter({
  scope: app,
  meta: { name: 'orders', version: '1.0.0' },
});

Timonel does not ignore the supplied scope.

Synthesis pipeline

A normal write follows this path:

cdk8s/cdk8s-plus constructs
          |
          v
     cdk8s Chart
          |
          v
  Testing.synth(chart)
          |
          +--> optional PolicyEngine validation
          |
          +--> Helm-aware enrichment/serialization
          |
          v
     SynthAsset[]
          |
          v
   HelmChartWriter
          |
          v
       Helm chart

Rutter.toSynthArray() is asynchronous and always returns Promise<SynthAsset[]>. toSynthArraySync() exists only for backward compatibility and cannot be used with a policy engine.

Generated chart structure

A typical output is:

my-chart/
├── Chart.yaml
├── values.yaml
├── .helmignore
└── templates/
    ├── _helpers.tpl
    ├── Web.yaml
    └── Config.yaml

Environment values configured through envValues become files such as values-development.yaml and values-production.yaml.

Helm values and templates

valuesRef<T>() provides typed references to .Values and selected Helm built-ins. It is separate from Kubernetes resource typing: it models Helm expressions rather than a Kubernetes object schema.

For templated fields that cannot be represented directly by an upstream construct, use a focused object-form fallback and ValuesRef rather than dropping to raw YAML.

See Type-Safe Helm Helpers.

Policy validation

A PolicyEngine is optional. When supplied to Rutter, validation occurs after cdk8s synthesis and before Timonel's standard label enrichment. A failed policy result prevents chart generation.

This keeps validation out of the normal path for users who do not need it.

Umbrella charts

UmbrellaRutter composes multiple Rutter instances into a parent Helm chart. Each subchart is written under charts/<name>, while the parent Chart.yaml receives local dependencies.

The CLI also supports umbrella scaffolding and dependencies or inline synthesis modes. For programmatic code, prefer the simpler UmbrellaRutter API.

Compatibility APIs

The following remain for compatibility but are not the preferred architecture:

  • raw-string addManifest(yaml, id);
  • addTemplateManifest(yaml, id);
  • string-oriented Helm control helpers when valuesRef<T>() can express the operation;
  • toSynthArraySync().

Deprecation is intentional so existing consumers have a migration path before a future major release removes legacy surfaces.

Clone this wiki locally