Working with Bundles
Learn how to use bundles to package and apply multiple templates together as a cohesive unit.
Templates are great for generating individual artifacts, but real-world infrastructure and applications often require multiple related configurations. Bundles allow you to package multiple templates together and apply them as a unit.
A bundle is a collection of templates that work together to create a complete solution. Instead of running multiple template commands, you can run a single bundle command that generates everything you need.
- Application Deployment: Kubernetes manifests, ConfigMaps, Secrets, Services
- Infrastructure Setup: Terraform configs, networking rules, IAM policies
- CI/CD Pipelines: GitHub Actions, GitLab CI, Jenkins pipelines
- Development Environment: Docker Compose, env files, local configs
Let's create a bundle that generates a complete web application setup.
cd ~/conjure-workspace/bundles
mkdir -p web-app/1.0.0
cd web-app/1.0.0
Create a conjure.json file that defines the bundle and its variables:
touch conjure.json
Open conjure.json and add the bundle metadata:
{
"schema_version": "v1",
"version": "1.0.0",
"bundle_type": "kubernetes",
"bundle_name": "web-app",
"bundle_description": "Complete web application deployment bundle",
"shared_variables": [
{
"name": "app_name",
"description": "Name of your application",
"type": "string",
"default": ""
},
{
"name": "namespace",
"description": "Kubernetes namespace",
"type": "string",
"default": "default"
},
{
"name": "port",
"description": "Application port",
"type": "int",
"default": "8080"
}
],
"template_variables": {
"deployment.yaml.tmpl": [
{
"name": "replicas",
"description": "Number of pod replicas",
"type": "int",
"default": "3"
},
{
"name": "image",
"description": "Container image",
"type": "string",
"default": ""
}
],
"service.yaml.tmpl": [
{
"name": "service_type",
"description": "Service type (ClusterIP, LoadBalancer)",
"type": "string",
"default": "ClusterIP"
}
]
}
}
Note
Shared variables are available to all templates in the bundle. Template-specific variables are scoped to individual template files.
Now create the template files in your bundle directory:
touch deployment.yaml.tmpl
touch service.yaml.tmpl
Open deployment.yaml.tmpl and add:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.app_name}}-deployment
namespace: {{.namespace}}
spec:
replicas: {{.replicas}}
selector:
matchLabels:
app: {{.app_name}}
template:
metadata:
labels:
app: {{.app_name}}
spec:
containers:
- name: {{.app_name}}
image: {{.image}}
ports:
- containerPort: {{.port}}
Open service.yaml.tmpl and add:
apiVersion: v1
kind: Service
metadata:
name: {{.app_name}}-service
namespace: {{.namespace}}
spec:
type: {{.service_type}}
selector:
app: {{.app_name}}
ports:
- port: 80
targetPort: {{.port}}
Now you can generate all templates in the bundle with a single command:
# Navigate back to workspace
cd ~/conjure-workspace
# Apply the bundle
conjure bundle web-app -o ./output
Since no variables are provided via --var or -f, Conjure automatically enters interactive mode. You will see a prompt that displays one variable at a time with its description, type, and default value. Required variables (those with no default) are marked with an asterisk.
After entering all variables, the prompt displays:
✓ All variables collected!
Conjure then asks if you want to add template-specific overrides. This allows you to override a shared variable for a specific template. For example, you could set a different namespace value for just service.yaml.tmpl while keeping the original value for deployment.yaml.tmpl.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Template-Specific Overrides
Override shared variables for specific templates
Add a template-specific override? (y/n):
If you select n or after finishing overrides, Conjure renders and writes the output files:
✓ Rendered: deployment.yaml
✓ Rendered: service.yaml
✓ Bundle rendered successfully
✓ 2 files written to: ./output
Just like templates, bundles support values files. This bypasses interactive mode and provides all variable values at once:
Create web-app-prod.yaml:
touch web-app-prod.yaml
Add your values:
# Shared variables (used by all templates)
app_name: my-api
namespace: production
port: 8080
# Template-specific variables
replicas: 5
image: my-api:1.0.0
service_type: LoadBalancer
Apply the bundle with the values file:
conjure bundle web-app -o ./output -f web-app-prod.yaml
Expected output:
Using bundle: web-app v1.0.0 (source: local)
Description: Complete web application deployment bundle
Type: kubernetes
✓ Rendered: deployment.yaml
✓ Rendered: service.yaml
✓ Bundle rendered successfully
✓ 2 files written to: ./output
You can override shared variables for specific templates using the template_overrides section in your values file. This is useful when a shared variable like namespace needs a different value for one template:
# Shared variables (used by all templates)
app_name: my-api
namespace: production
port: 8080
# Template-specific variables
replicas: 5
image: my-api:1.0.0
service_type: LoadBalancer
# Override shared variables for specific templates
template_overrides:
service.yaml.tmpl:
namespace: service-namespace
In this example, deployment.yaml.tmpl uses namespace: production while service.yaml.tmpl uses namespace: service-namespace.
You can also apply template-specific overrides from the command line using the template.tmpl:key=value format:
conjure bundle web-app -o ./output -f web-app-prod.yaml --var service.yaml.tmpl:namespace=service-namespace
See all available bundles in your repository:
conjure list bundles
Expected output:
Available Bundles:
web-app
Description: Complete web application deployment bundle
Type: kubernetes
Latest: 1.0.0
Total: 1 bundle
To see all available versions of each bundle:
conjure list bundles --versions
Important
Version your bundles
Always specify a version in your
conjure.json:{ "schema_version": "v1", "version": "1.2.0", "bundle_name": "web-app", "bundle_type": "kubernetes", "bundle_description": "...", "shared_variables": [], "template_variables": {} }Use semantic versioning (x.x.x format) to track changes and maintain compatibility.
Tip
Document bundle requirements
Include a README with your bundle explaining:
- What the bundle generates
- Required infrastructure or dependencies
- Example values files
- How to customize the bundle
Note
Test bundles thoroughly
Before sharing bundles with your team:
- Test with minimal values
- Test with production-like values
- Verify all outputs are correct
- Document any manual steps needed after bundle application
You now understand the complete Conjure workflow from simple templates to complex bundles:
Using the Starter Repository
Try production-ready templates and bundles from the conjure-get-started repository.
Creating Templates
Build your own templates with variables, conditionals, and loops.
Configuration Reference
Complete reference for all Conjure configuration options.
Using Remote Repositories
Learn how to use remote template repositories instead of local ones.
What are Bundles?
Common Bundle Use Cases
Creating Your First Bundle
Step 1: Create Bundle Directory Structure
Step 2: Create Bundle Metadata
Step 3: Create Template Files
Step 4: Apply the Bundle
Using Values Files with Bundles
Template-Specific Overrides in Values Files
Listing Available Bundles
Best Practices
Next Steps