template

package
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNestedExpression = errors.New("nested CEL expressions must be quoted")

ErrNestedExpression is returned when nested CEL expressions are found.

Functions

func BaseCELExtensions added in v0.9.0

func BaseCELExtensions() []cel.EnvOption

BaseCELExtensions returns the CEL extensions used across OpenChoreo. This includes optional types, common utility extensions for strings, encoding, math, lists, sets, two-variable comprehensions, and OpenChoreo custom functions.

func CustomFunctions

func CustomFunctions() []cel.EnvOption

CustomFunctions returns the CEL environment options for custom template functions.

These functions provide additional capabilities beyond the standard CEL-go extensions, designed for use in CEL-based templates throughout OpenChoreo. All custom functions use the "oc_" prefix to avoid potential conflicts with upstream CEL-go.

Available Functions

oc_omit() - Remove fields, map keys, or array items from rendered output

oc_merge(map1, map2, ...mapN) - Shallow merge of multiple maps

oc_generate_name(...strings) - Generate valid Kubernetes resource names (≤253 chars)

oc_dns_label(...strings) - Generate valid Kubernetes DNS label names (≤63 chars)

oc_hash(string) - Generate 8-character hash from input string

oc_omit() - Conditional Omission

Returns a sentinel value that is removed during post-processing. Supports two use cases:

Use Case 1: Remove entire fields from YAML/JSON structure

metadata:
  annotations: ${has(spec.annotations) ? spec.annotations : oc_omit()}
  labels:
    version: ${has(spec.version) ? spec.version : oc_omit()}

Result when spec.annotations and spec.version are undefined:

metadata:
  labels: {}

Use Case 2: Remove map keys or array items within CEL expressions

# Conditional map keys
labels: ${{"app": metadata.name, "env": has(spec.env) ? spec.env : oc_omit()}}

# Conditional array items
args: ${["--port=8080", spec.debug ? "--debug" : oc_omit(), "--log=info"]}

oc_merge() - Shallow Map Merge

Merges multiple maps left-to-right, with later maps overriding earlier ones. IMPORTANT: This is a shallow merge - nested maps are replaced, not merged recursively.

# Basic merge
env: ${oc_merge(defaults, spec.env, environmentConfigs)}

# Inline map literals
resources: ${oc_merge({cpu: "100m", memory: "128Mi"}, spec.resources)}

# Variadic merge (3+ maps)
config: ${oc_merge(base, layer1, layer2, layer3)}

Shallow merge behavior:

base = {resources: {cpu: "100m", memory: "128Mi"}, replicas: 1}
override = {resources: {cpu: "200m"}}
result = {resources: {cpu: "200m"}, replicas: 1}
# Note: memory is LOST because resources map was replaced entirely

oc_generate_name() - Kubernetes Name Generation

Generates valid Kubernetes DNS subdomain names from arbitrary strings. Names are sanitized, truncated to 253 characters, and include an 8-character hash suffix for uniqueness.

# Variadic arguments
name: ${oc_generate_name(component.name, environment, "cache")}
# "payment-service", "prod", "cache" -> "payment-service-prod-cache-a1b2c3d4"

# Array input
name: ${oc_generate_name([metadata.namespace, metadata.name, "worker"])}

# Single string (sanitized)
name: ${oc_generate_name("My App!")}
# "My App!" -> "my-app-e5f6g7h8"

Hash suffix ensures uniqueness even when inputs sanitize to the same string:

oc_generate_name("my-app")   -> "my-app-abc12345"
oc_generate_name("My App!")  -> "my-app-def67890"  # Different hash

oc_dns_label() - Kubernetes DNS Label Name Generation

Same as oc_generate_name() but enforces a ≤63 character limit, suitable for Kubernetes DNS label names (e.g., hostname subdomain labels).

# Webapp hostname subdomain (≤63 chars)
hostnames:
  - ${oc_dns_label(endpointName, metadata.componentName, metadata.environmentName, metadata.componentNamespace)}.example.com

oc_hash() - String Hashing

Generates an 8-character hexadecimal hash from an input string using the FNV-32a algorithm. Useful for creating stable, deterministic identifiers or suffixes.

The hash is deterministic - the same input always produces the same output:

oc_hash("test")  -> "4fdcca5d"  # Always produces this hash
oc_hash("test")  -> "4fdcca5d"  # Same input, same output

All custom functions use the "oc_" prefix to avoid potential conflicts with upstream CEL-go.

func RemoveOmittedFields

func RemoveOmittedFields(data any) any

RemoveOmittedFields walks the rendered tree after CEL evaluation and strips the omit() sentinel. Templates using the reusable `omit()` helper stay compatible with the rendering pipeline's pruning semantics.

Types

type CELMatch added in v0.9.0

type CELMatch struct {
	FullExpr  string // The complete ${...} expression including delimiters
	InnerExpr string // The CEL expression content without ${ and }
}

CELMatch represents a CEL expression found in a template string.

func FindCELExpressions added in v0.9.0

func FindCELExpressions(str string) ([]CELMatch, error)

FindCELExpressions locates all ${...} expression markers within a string.

This function performs brace-balanced parsing to handle nested curly braces correctly. For example, in "${merge({a: 1}, {b: 2})}", the parser counts opening and closing braces to identify the complete expression boundary.

The algorithm uses a brace counter that increments on '{' and decrements on '}'. When the counter returns to zero, we've found the matching closing brace.

Returns:

  • FullExpr: the complete ${...} expression including delimiters
  • InnerExpr: the CEL expression content without ${ and }

Example:

  • Input: "image:${spec.image}:${spec.tag}"
  • Output: [{FullExpr: "${spec.image}", InnerExpr: "spec.image"}, {FullExpr: "${spec.tag}", InnerExpr: "spec.tag"}]

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine evaluates CEL backed templates that can contain inline expressions, map keys, and nested structures.

func NewEngine

func NewEngine() *Engine

NewEngine creates a new CEL template engine with default cache settings.

func NewEngineWithOptions

func NewEngineWithOptions(opts ...EngineOption) *Engine

NewEngineWithOptions creates a new CEL template engine with custom options. Use this for testing and benchmarking different caching strategies, or to add custom CEL extensions.

Example:

// Disable all caching for baseline benchmark
engine := template.NewEngineWithOptions(template.DisableCache())

// Add custom CEL extensions
engine := template.NewEngineWithOptions(template.WithCELExtensions(context.CELExtensions()...))

func (*Engine) Render

func (e *Engine) Render(data any, inputs map[string]any) (any, error)

Render walks the provided structure and evaluates CEL expressions against the supplied inputs.

type EngineCache

type EngineCache struct {
	// contains filtered or unexported fields
}

EngineCache provides caching for CEL environments and compiled programs. It maintains two levels of caching: - Environment cache: LRU cache of CEL environments by variable names - Program cache: LRU cache of compiled programs by (env, expression)

Cache Architecture:

Level 1: ENV Cache (LRU, max 100 entries)
  └─ envKey: ["trait", "metadata", ..."] → CEL Environment

Level 2: PROGRAM Cache (LRU, max 2000 entries)
  └─ (envKey + expression) → Compiled CEL Program

For a deployment with 5 CTs and 50 traits, expect ~875 cached programs. The 2000 entry limit provides 2x headroom and protects against edge cases like dynamic template updates or multi-tenancy scenarios.

func (*EngineCache) GetEnv

func (c *EngineCache) GetEnv(key string) (*cel.Env, bool)

GetEnv retrieves a cached CEL environment by its cache key. Returns (nil, false) if caching is disabled.

func (*EngineCache) GetProgram

func (c *EngineCache) GetProgram(envKey, expression string) (cel.Program, bool)

GetProgram retrieves a cached compiled CEL program. Returns (nil, false) if caching is disabled.

func (*EngineCache) ProgramCacheSize

func (c *EngineCache) ProgramCacheSize() int

ProgramCacheSize returns the number of entries in the program cache. Returns 0 if caching is disabled. Useful for testing and monitoring cache effectiveness.

func (*EngineCache) SetEnv

func (c *EngineCache) SetEnv(key string, env *cel.Env)

SetEnv stores a CEL environment in the cache. No-op if caching is disabled.

func (*EngineCache) SetProgram

func (c *EngineCache) SetProgram(envKey, expression string, program cel.Program)

SetProgram stores a compiled CEL program in the cache. No-op if caching is disabled.

type EngineOption

type EngineOption func(*Engine)

EngineOption configures the template engine. Used for cache configuration, custom CEL extensions, and testing.

func DisableCache

func DisableCache() EngineOption

DisableCache disables all caching (both environment and program caches). Use this for benchmarking to measure the cost of caching vs compilation.

Example:

engine := template.NewEngineWithOptions(template.DisableCache())

func DisableProgramCacheOnly

func DisableProgramCacheOnly() EngineOption

DisableProgramCacheOnly disables only the program cache, keeping environment cache enabled. Use this to measure the impact of program compilation caching separately from environment caching.

Example:

engine := template.NewEngineWithOptions(template.DisableProgramCacheOnly())

func WithCELExtensions added in v0.9.0

func WithCELExtensions(extensions ...cel.EnvOption) EngineOption

WithCELExtensions adds custom CEL environment options to the engine. Use this to register custom functions, macros, and types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL