Blueprint Composition
Teabar blueprints can extend and combine other blueprints, enabling modular, reusable infrastructure definitions. This promotes DRY (Don’t Repeat Yourself) principles and standardization across your organization.
Why Composition?
Instead of duplicating configuration across blueprints:
❌ Without Composition:
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ cicd-workshop │ │ k8s-training │ │ security-lab │
│ ─────────────────── │ │ ─────────────────── │ │ ─────────────────── │
│ • Network config │ │ • Network config │ │ • Network config │
│ • Base cluster │ │ • Base cluster │ │ • Base cluster │
│ • Monitoring │ │ • Monitoring │ │ • Monitoring │
│ • GitLab │ │ • Dashboard │ │ • Falco │
│ • Runners │ │ • Exercises │ │ • Trivy │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
↓ Duplication ↓ Duplication ↓ Duplication Use composition for shared foundations:
✅ With Composition:
┌─────────────────────┐
│ base-environment │
│ ─────────────────── │
│ • Network config │
│ • Base cluster │
│ • Monitoring │
└──────────┬──────────┘
│ extends
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ cicd-workshop │ │ k8s-training │ │ security-lab │
│ + GitLab │ │ + Dashboard │ │ + Falco │
│ + Runners │ │ + Exercises │ │ + Trivy │
└─────────────────┘ └─────────────────┘ └─────────────────┘ Extending Blueprints
Use extends to inherit from one or more base blueprints:
Basic Extension
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: cicd-workshop
version: 1.0.0
spec:
# Extend a base blueprint
extends:
- name: teabar/base-kubernetes
version: "1.x"
# Add workshop-specific resources
resources:
helm:
- name: gitlab
chart: gitlab/gitlab
namespace: gitlab Multiple Inheritance
Extend multiple blueprints (processed in order):
spec:
extends:
# First: base infrastructure
- name: teabar/base-kubernetes
version: "1.x"
# Second: monitoring stack
- name: teabar/monitoring-stack
version: "2.x"
# Third: organization standards
- name: acme/company-standards
version: "1.x" Note
Version Constraints
Specify version constraints for stability:
| Constraint | Meaning | Example |
|---|---|---|
1.0.0 | Exact version | Only 1.0.0 |
1.x | Any 1.*.* | 1.0.0, 1.5.2, 1.99.0 |
1.2.x | Any 1.2.* | 1.2.0, 1.2.15 |
>=1.2.0 | Minimum version | 1.2.0 or higher |
>=1.0.0 <2.0.0 | Range | 1.* versions only |
extends:
# Pin to exact version for production
- name: teabar/base-kubernetes
version: "1.5.2"
# Allow minor updates
- name: teabar/monitoring-stack
version: "2.x"
# Allow patches only
- name: acme/company-standards
version: "1.0.x" Merge Behavior
Understanding how blueprints merge is key to effective composition.
Resource Merging
Resources are merged by type and name:
# Base blueprint: teabar/base-kubernetes
resources:
clusters:
- name: main
nodes:
workers: 2
addons:
metricsServer: true
# Your blueprint
extends:
- name: teabar/base-kubernetes
resources:
clusters:
- name: main # Same name = merge
nodes:
workers: 5 # Override workers
addons:
ingressNginx: true # Add new addon
- name: secondary # Different name = add new
nodes:
workers: 3 Result:
resources:
clusters:
- name: main
nodes:
workers: 5 # Overridden
addons:
metricsServer: true # From base
ingressNginx: true # Added
- name: secondary # New cluster
nodes:
workers: 3 Variable Merging
Variables merge by name, with child overriding parent:
# Base blueprint
variables:
- name: cluster_version
type: string
default: "1.28"
- name: worker_count
type: integer
default: 3
# Child blueprint
extends:
- name: base
variables:
- name: worker_count # Override default
default: 5
- name: enable_monitoring # Add new variable
type: boolean
default: true Result:
variables:
- name: cluster_version # From base
type: string
default: "1.28"
- name: worker_count # Overridden
type: integer
default: 5
- name: enable_monitoring # Added
type: boolean
default: true Deep Merging
Nested objects are deep-merged:
# Base
resources:
helm:
- name: app
values:
replicas: 2
image:
repository: nginx
tag: "1.24"
# Child
resources:
helm:
- name: app
values:
replicas: 5 # Override
image:
tag: "1.25" # Override nested
pullPolicy: Always # Add nested Result:
resources:
helm:
- name: app
values:
replicas: 5
image:
repository: nginx # Preserved from base
tag: "1.25" # Overridden
pullPolicy: Always # Added List Behavior
Lists are replaced by default, not merged:
# Base
resources:
dns:
- name: api
type: A
- name: web
type: A
# Child - REPLACES the entire list
resources:
dns:
- name: gitlab
type: A Result: Only gitlab DNS entry (api and web are gone).
To preserve base list items, reference them explicitly or use named resources.
Override Strategies
Complete Override
Replace an entire resource:
extends:
- name: teabar/base-kubernetes
resources:
clusters:
- name: main
_override: replace # Completely replace, don't merge
provider: aws
type: eks
nodes:
workers: 10 Selective Override
Override specific fields only:
extends:
- name: teabar/base-kubernetes
resources:
clusters:
- name: main
# Only these fields are overridden, rest inherited
nodes:
workers: 10 Disable Inherited Resources
Remove an inherited resource:
extends:
- name: teabar/full-stack
resources:
helm:
- name: prometheus
_enabled: false # Don't deploy prometheus from base Creating Base Blueprints
Organization Standards Blueprint
Create a blueprint enforcing your organization’s standards:
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: acme-standards
version: 1.0.0
description: ACME Corp standard environment configuration
spec:
# Standard variables all environments should have
variables:
- name: cost_center
type: string
required: true
ui:
label: "Cost Center"
description: "Required for billing"
- name: owner_email
type: string
required: true
constraints:
pattern: ".*@acme\.com$"
ui:
label: "Owner Email"
# Standard environment settings
environment:
# All environments must have TTL
ttl: 72h
# Standard labels
labels:
company: acme
managed-by: teabar
# Standard resources
resources:
# Company CA certificate
secrets:
- name: acme-ca
type: external
spec:
provider: vault
path: pki/ca
# Standard network policies
manifests:
- name: default-network-policy
template: |
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress Reusable Component Blueprint
Create blueprints for common components:
apiVersion: teabar.dev/v1
kind: Blueprint
metadata:
name: gitlab-component
version: 1.0.0
description: GitLab CE deployment component
spec:
variables:
- name: gitlab_version
type: string
default: "16.8"
- name: registry_enabled
type: boolean
default: true
- name: runner_count
type: integer
default: 2
resources:
helm:
- name: gitlab
chart: gitlab/gitlab
version: "7.x"
namespace: gitlab
values:
global:
edition: ce
hosts:
domain: "{{ .Environment.Domain }}"
registry:
enabled: "{{ .Variables.registry_enabled }}"
# GitLab runners
manifests:
- name: gitlab-runners
count: "{{ .Variables.runner_count }}"
template: |
# Runner configuration... Composition Patterns
Layer Pattern
Stack blueprints in layers:
# infrastructure-layer.yaml
spec:
resources:
clusters:
- name: main
# Base cluster configuration
# platform-layer.yaml
spec:
extends:
- name: org/infrastructure-layer
resources:
helm:
- name: argocd
- name: cert-manager
# application-layer.yaml
spec:
extends:
- name: org/platform-layer
resources:
helm:
- name: my-app Mixin Pattern
Combine feature blueprints:
spec:
extends:
# Base infrastructure
- name: teabar/base-kubernetes
# Add monitoring (mixin)
- name: teabar/monitoring-mixin
# Add logging (mixin)
- name: teabar/logging-mixin
# Add security scanning (mixin)
- name: teabar/security-mixin Profile Pattern
Create profiles for different scales:
# small-profile.yaml
spec:
variables:
- name: worker_count
default: 2
- name: worker_size
default: cx21
# large-profile.yaml
spec:
variables:
- name: worker_count
default: 10
- name: worker_size
default: cx41
# workshop.yaml
spec:
extends:
- name: org/base-workshop
- name: org/large-profile # Use large profile Viewing Resolved Blueprints
See the final merged result:
# Render with all extensions resolved
teactl blueprint render my-blueprint --resolve
# Show inheritance tree
teactl blueprint info my-blueprint --show-extends
# Output:
# my-blueprint v1.0.0
# └── extends: teabar/base-kubernetes v1.5.0
# └── extends: teabar/base-network v1.2.0
# └── extends: acme/company-standards v1.0.0
# Diff against base
teactl blueprint diff my-blueprint --base teabar/base-kubernetes Publishing Reusable Blueprints
Organization Blueprints
Share within your organization:
# Push to organization registry
teactl blueprint push -f base-standards.yaml --org acme
# Others can now extend it
# extends:
# - name: acme/base-standards Public Catalog
Share with the Teabar community (Pro feature):
# Publish to public catalog
teactl blueprint publish -f my-blueprint.yaml
--public
--description "Reusable GitLab CI/CD setup" Note
acme/gitlab-cicd. Official Teabar blueprints use the teabar/ namespace.Best Practices
1. Keep Base Blueprints Stable
Base blueprints should change infrequently:
# Use semantic versioning
metadata:
version: 1.0.0 # Major.Minor.Patch
# Document breaking changes
# v2.0.0 - Changed cluster naming convention 2. Use Version Constraints Wisely
extends:
# Development: allow updates
- name: teabar/base-kubernetes
version: "1.x"
# Production: pin exact versions
- name: teabar/base-kubernetes
version: "1.5.2" 3. Document Override Points
# Base blueprint with clear extension points
variables:
# Override this to customize cluster size
- name: worker_count
type: integer
default: 3
ui:
description: "Number of worker nodes. Override in extending blueprint."
resources:
helm:
# Override 'values' in extending blueprint to customize
- name: nginx-ingress
chart: ingress-nginx/ingress-nginx
values:
# Default values - extend to customize
controller:
replicaCount: 2 4. Test Inheritance Chains
# Validate the resolved blueprint
teactl blueprint validate -f child.yaml --resolve
# Test with actual deployment
teactl env create --blueprint child --name test-inheritance --dry-run 5. Avoid Deep Inheritance
Keep inheritance chains shallow (2-3 levels max):
✅ Good: base → specialized → final
❌ Avoid: base → layer1 → layer2 → layer3 → layer4 → final Troubleshooting
“Blueprint not found” in extends
# Check if base blueprint exists
teactl blueprint get teabar/base-kubernetes
# Check version availability
teactl blueprint versions teabar/base-kubernetes Unexpected merge results
# See exactly what's being merged
teactl blueprint render my-blueprint --resolve --verbose
# Show merge operations
teactl blueprint render my-blueprint --show-merge-log Circular dependency
Error: circular dependency detected: a → b → c → a Restructure to eliminate cycles. Use composition for shared components instead of circular extends.
Next Steps
- Blueprint Variables - Define typed inputs
- Blueprint Templating - Dynamic configuration
- Blueprint Catalog - Browse and publish blueprints