Skip to content
GitHub stars

Templates

LynqForm resource specs are Go text/template strings rendered at reconciliation time. Variables come from the LynqHub row; 200+ Sprig functions plus a handful of Lynq-specific helpers are available.

Time to working

Add your first variable substitution in 2 minutes. No new syntax to learn if you know Go templates.

How It Works

  • Every nameTemplate, spec, labelsTemplate, and annotationsTemplate field in a LynqForm is a Go text/template string.
  • Variables come from the LynqHub row (uid, activate, plus anything in extraValueMappings).
  • 200+ Sprig functions plus Lynq-specific helpers (trunc63, toHost, sha1sum) are available.

Template Syntax

yaml
# Variable substitution
nameTemplate: "{{ .uid }}-app"

# Pipeline (function applied to variable)
nameTemplate: "{{ .uid | trunc63 }}"

# Conditional
nameTemplate: "{{ if .region }}{{ .region }}-{{ end }}{{ .uid }}"

# Default value
nameTemplate: "{{ .uid }}-{{ .planId | default \"basic\" }}"

Examples

Deployment with Type-Safe Fields

yaml
deployments:
  - id: app
    nameTemplate: "{{ .uid }}-{{ .region | default \"default\" }}"
    spec:
      apiVersion: apps/v1
      kind: Deployment
      spec:
        replicas: "{{ .maxReplicas | default \"2\" | int }}"
        template:
          spec:
            automountServiceAccountToken: "{{ .autoMount | default \"true\" | bool }}"
            containers:
            - name: app
              image: "{{ .deployImage | default \"myapp:latest\" }}"
              ports:
              - containerPort: "{{ .appPort | default \"8080\" | int }}"
              env:
              - name: NODE_ID
                value: "{{ .uid }}"
              - name: REGION
                value: "{{ .region | default \"us-east-1\" }}"
              resources:
                limits:
                  cpu: "{{ .cpuLimit | default \"1.0\" | float }}"
                  memory: "{{ .memoryLimit | default \"512\" }}Mi"

Dynamic Labels

yaml
labelsTemplate:
  app: "{{ .uid }}"
  plan: "{{ .planId | default \"basic\" }}"
  region: "{{ .region | default \"global\" }}"
  managed-by: "lynq"

Stable Short Names

yaml
# SHA1 hash → 8 chars → unique, stable, URL-safe
nameTemplate: "{{ .uid | sha1sum | trunc 8 }}-app"

Conditional Resource Config

Use ternary for binary switches — it keeps template expressions readable inline:

yaml
env:
- name: DEBUG
  value: "{{ ternary \"true\" \"false\" (eq .planId \"enterprise\") }}"
- name: REPLICAS
  value: "{{ ternary \"5\" \"2\" (eq .planId \"enterprise\") }}"

For multi-tier values (e.g., enterprise/pro/basic each getting different limits), use extraValueMappings to map a pre-computed column and keep the template to a simple lookup:

yaml
# LynqHub extraValueMappings:
#   cpuLimit: cpu_limit_column  # DB stores "1000m", "500m", "200m"
env:
- name: CPU_LIMIT
  value: "{{ .cpuLimit | default \"200m\" }}"

Best Practices

  1. Always quote template expressions"{{ .uid }}" — YAML parser requires it
  2. Use default for optional variables{{ .image | default "nginx:stable" }}
  3. Truncate long names{{ .uid | trunc63 }} — Kubernetes 63-char limit
  4. Use type conversion for numeric/boolean Kubernetes fields{{ .replicas | int }}, {{ .enabled | bool }}
  5. Chain default before type conversion{{ .replicas | default "2" | int }}

See Also

PageContents
Syntax ReferenceVariables, custom functions, Sprig library, advanced techniques
Type Conversionint, float, bool for Kubernetes fields
Debugging & MigrationCommon errors, debugging tools
Resource LifecycleAdding, removing, and re-adopting resources at runtime
PoliciescreationPolicy, deletionPolicy, conflictPolicy
DependenciesResource ordering with dependIds