Template Libraries¶
Template libraries are modular, composable configuration packages that extend HAProxy functionality. Each library provides specific features that can be enabled or disabled based on your requirements.
Overview¶
HAPTIC uses a library-based architecture where YAML configuration files are merged at Helm render time. This enables:
- Modularity: Enable only the features you need
- Extensibility: Add custom configuration via extension points
- Maintainability: Each library focuses on a specific concern
- Customization: Override or extend library behavior through values.yaml
Available Libraries¶
| Library | Default | Purpose |
|---|---|---|
| Base | Always enabled | Core HAProxy configuration, extension point definitions |
| SSL | Enabled | TLS certificate management, HTTPS frontend |
| Ingress | Enabled | Kubernetes Ingress resource support |
| Gateway API | Enabled | Gateway API (HTTPRoute, GRPCRoute) support |
| HAProxy Annotations | Enabled | haproxy.org/* annotation support |
| HAProxy Ingress | Enabled | HAProxy Ingress Controller compatibility |
| Path Regex Last | Disabled | Performance-first path matching order |
Enabling and Disabling Libraries¶
Configure libraries in your values.yaml:
controller:
templateLibraries:
base:
enabled: true # Always enabled (cannot be disabled)
ssl:
enabled: true # TLS/HTTPS support
ingress:
enabled: true # Kubernetes Ingress
gateway:
enabled: true # Gateway API
haproxytech:
enabled: true # haproxy.org annotations
haproxyIngress:
enabled: true # HAProxy Ingress compatibility
pathRegexLast:
enabled: false # Performance optimization (opt-in)
Library Merge Order¶
Libraries are merged in a specific order, with later libraries overriding earlier ones:
1. base.yaml (lowest priority)
2. ssl.yaml
3. ingress.yaml
4. gateway.yaml
5. haproxytech.yaml
6. haproxy-ingress.yaml
7. path-regex-last.yaml
8. values.yaml (highest priority - your configuration)
Your custom configuration in controller.config always takes precedence.
Extension Points¶
Extension points are the core mechanism for library extensibility. The base library defines hook points where other libraries (or your custom configuration) can inject content.
How Extension Points Work¶
The base library uses include_matching("prefix-*") to automatically include all template snippets matching a glob pattern:
{# In base.yaml #}
{%- from "util-macros" import include_matching -%}
{{ include_matching("backends-*") }}
This includes all snippets with names starting with backends-:
backends-ingress(from ingress library)backends-gateway(from gateway library)backends-custom(from your values.yaml)
Available Extension Points¶
| Extension Point | Prefix Pattern | Where Included | Purpose |
|---|---|---|---|
| Features | features-* |
Early in config | Feature initialization, SSL setup |
| Global Top | global-top-* |
After defaults |
Userlists, peers, global elements |
| Frontend Matchers | frontend-matchers-advanced-* |
Frontend routing | Method, header, query matching |
| Frontend Filters | frontend-filters-* |
HTTP frontend | Request/response processing |
| Custom Frontends | frontends-* |
After HTTP frontend | HTTPS, TCP frontends |
| Custom Backends | backends-* |
Before default backend | Backend definitions |
| Backend Directives | backend-directives-* |
Within backends | Per-backend configuration |
| Host Map | map-host-* |
host.map | Host routing entries |
| Path Exact Map | map-path-exact-* |
path-exact.map | Exact path entries |
| Path Prefix Exact Map | map-path-prefix-exact-* |
path-prefix-exact.map | Prefix exact entries |
| Path Prefix Map | map-path-prefix-* |
path-prefix.map | Prefix path entries |
| Path Regex Map | map-path-regex-* |
path-regex.map | Regex path entries |
| Weighted Backend Map | map-weighted-backend-* |
weighted-multi-backend.map | Weighted routing |
Injecting Custom Configuration¶
Add custom snippets in your values.yaml to inject configuration at extension points:
controller:
config:
templateSnippets:
# Inject into frontend (matches frontend-filters-*)
frontend-filters-security:
template: |
# Block admin paths from external IPs
http-request deny if { path_beg /admin } !{ src 10.0.0.0/8 }
# Inject into backends (matches backends-*)
backends-maintenance:
template: |
backend maintenance
http-request return status 503 content-type text/html string "<h1>Maintenance</h1>"
# Inject into host map (matches map-host-*)
map-host-custom:
template: |
# Custom host routing
legacy.example.com legacy.example.com
Snippet Priority¶
Control execution order with the priority field (lower numbers execute first):
controller:
config:
templateSnippets:
features-init-early:
priority: 10 # Runs early
template: |
{# Initialize something first #}
features-init-late:
priority: 200 # Runs after other features-* snippets
template: |
{# Finalize after other initialization #}
Default priority is 100 if not specified.
Which Libraries Use Which Extension Points¶
| Library | Extension Points Used |
|---|---|
| Base | Defines all extension points |
| SSL | features-*, frontends-*, backends-*, global-top-* |
| Ingress | features-*, backends-*, map-host-*, map-path-* |
| Gateway | features-*, backends-*, map-*, frontend-matchers-advanced-*, frontend-filters-* |
| HAProxy Annotations | global-top-*, backend-directives-*, frontend-filters-* |
| HAProxy Ingress | map-path-regex-* |
| Path Regex Last | Overrides frontend-routing-logic (not an extension point pattern) |
Custom Libraries¶
You can create custom libraries by providing template snippets that implement extension point patterns:
# values.yaml
controller:
config:
# Add watched resources for your custom library
watchedResources:
configmaps:
apiVersion: v1
resources: configmaps
indexBy: ["metadata.namespace", "metadata.name"]
# Implement extension points
templateSnippets:
# Process ConfigMaps and generate backends
backends-configmap-routes:
template: |
{%- for cm in resources.configmaps.List() %}
{%- if cm.metadata.labels.get("routing", "") == "enabled" %}
backend cm_{{ cm.metadata.namespace }}_{{ cm.metadata.name }}
# Generate backend from ConfigMap data
server app {{ cm.data.target }}
{%- endif %}
{%- endfor %}
# Generate host map entries
map-host-configmap-routes:
template: |
{%- for cm in resources.configmaps.List() %}
{%- if cm.metadata.labels.get("routing", "") == "enabled" %}
{{ cm.data.hostname }} {{ cm.data.hostname }}
{%- endif %}
{%- endfor %}
Library Architecture¶
┌─────────────────────────────────────────────────────────────┐
│ values.yaml │
│ (highest priority) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Optional Libraries (if enabled) │
│ path-regex-last.yaml haproxy-ingress.yaml gateway.yaml │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Core Libraries │
│ haproxytech.yaml ingress.yaml ssl.yaml │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ base.yaml │
│ (defines extension points, lowest priority) │
└─────────────────────────────────────────────────────────────┘
See Also¶
- Base Library - Extension point definitions
- Gateway API Library - Gateway API features
- HAProxy Annotations Library - HAProxy annotations