49 KiB
Based on your Jinja2 mastery goals and the comprehensive use cases in your document, here's the tactical toolchain that will make you unstoppable:
Core Stack (Your Foundation)
1. Python Ecosystem
# Essential Python libraries for Jinja2 mastery
pip install jinja2 pyyaml requests click rich tabulate
Why Each Matters:
- PyYAML: Parse YAML data files (your primary input format)
- Requests: Pull data from APIs (NetBox, cloud providers, monitoring systems)
- Click: Build CLI tools for your templates
- Rich: Beautiful terminal output for your tools
- Tabulate: Generate nice tables in outputs
2. Data Sources & APIs
| Tool | Purpose | Jinja2 Integration |
|---|---|---|
| NetBox | Network documentation SSOT | pynetbox → YAML → templates |
| Nautobot | NetBox alternative | Same pattern as NetBox |
| Ansible | Automation platform | Built-in Jinja2 support |
| Git | Version control | Store templates + data |
Specialized Tools by Use Case
Network Engineering Stack
# Network-specific tools
pip install netmiko nornir napalm textfsm
pip install ipaddress netaddr
Power Combo Example:
from netmiko import ConnectHandler
from jinja2 import Template
import yaml
# Pull live config from device
device = ConnectHandler(**cisco_device)
running_config = device.send_command("show running-config")
# Generate new config from template
template = Template(open('templates/bgp.j2').read())
new_config = template.render(yaml.safe_load(open('data/bgp.yml')))
# Deploy with error checking
device.send_config_set(new_config.split('\n'))
Documentation & Visualization
# Documentation tools
pip install mkdocs mkdocs-material
pip install graphviz plotly mermaid-cli
npm install -g @mermaid-js/mermaid-cli # For diagram generation
Workflow:
# Generate network diagrams from templates
template = env.get_template('network_diagram.mmd.j2')
mermaid_output = template.render(topology=network_data)
# Convert to PNG via CLI
subprocess.run(['mmdc', '-i', 'diagram.mmd', '-o', 'diagram.png'])
Sales/Proposal Generation
# Document generation
pip install python-docx reportlab pandoc
Pro Tip:
# Jinja2 → LaTeX → PDF pipeline
template = env.get_template('proposal.tex.j2')
latex_content = template.render(customer_data)
with open('proposal.tex', 'w') as f:
f.write(latex_content)
subprocess.run(['pdflatex', 'proposal.tex'])
DevOps/Automation Stack
Container & Cloud Tools
# Cloud automation
pip install boto3 azure-identity google-cloud-storage
pip install kubernetes docker-py
Multi-Cloud Template Example:
{# Works for AWS, Azure, GCP #}
{% if cloud_provider == 'aws' %}
resource "aws_instance" "{{ instance_name }}" {
ami = "{{ ami_id }}"
instance_type = "{{ instance_type }}"
}
{% elif cloud_provider == 'azure' %}
resource "azurerm_virtual_machine" "{{ instance_name }}" {
name = "{{ instance_name }}"
vm_size = "{{ vm_size }}"
}
{% endif %}
CI/CD Integration Tools
# Pipeline tools
pip install github3.py python-gitlab
pip install pre-commit black flake8
GitHub Actions Integration:
# .github/workflows/jinja2-render.yml
- name: Render Templates
run: |
python scripts/render_all.py
git add rendered/
git commit -m "Auto-rendered configs [skip ci]"
Advanced Toolchain
Database Integration
# Pull data from multiple sources
import sqlite3
import psycopg2
from sqlalchemy import create_engine
import pandas as pd
# SQL → Jinja2 pipeline
df = pd.read_sql("SELECT * FROM network_devices", engine)
devices = df.to_dict('records')
template.render(devices=devices)
Testing & Validation
pip install pytest jsonschema yamale
Template Testing:
# tests/test_templates.py
def test_cisco_config_template():
template = env.get_template('cisco.j2')
result = template.render(test_data)
assert 'hostname TEST-SW-01' in result
assert 'interface GigabitEthernet0/1' in result
assert 'no shutdown' in result
Performance & Scalability
# For high-volume templating
from concurrent.futures import ThreadPoolExecutor
from functools import lru_cache
@lru_cache(maxsize=128)
def get_template(template_name):
return env.get_template(template_name)
# Parallel rendering
with ThreadPoolExecutor(max_workers=4) as executor:
configs = list(executor.map(render_device_config, devices))
Monitoring & Observability
pip install prometheus_client grafana-api
pip install loguru structlog
Template Metrics:
from prometheus_client import Counter, Histogram
import time
TEMPLATE_RENDERS = Counter('jinja2_renders_total', 'Total template renders')
RENDER_TIME = Histogram('jinja2_render_seconds', 'Template render time')
@RENDER_TIME.time()
def render_with_metrics(template, data):
TEMPLATE_RENDERS.inc()
return template.render(**data)
IDE & Development Tools
VS Code Extensions
- Jinja2: Syntax highlighting for
.j2files - YAML: Better YAML editing
- Python: Obviously
- GitLens: Track template changes
- REST Client: Test APIs that feed your templates
CLI Tools
# Essential CLI tools
pip install jinja2-cli j2cli cookiecutter
npm install -g js-yaml # YAML validation
Quick CLI Usage:
# One-liner template rendering
j2 template.j2 data.yml --format=yaml > output.cfg
# Template from stdin
echo "Hello {{ name }}" | j2 --undefined -D name=World
Your 90-Day Mastery Stack
Month 1: Foundation
# Core tools only
pip install jinja2 pyyaml click rich
git clone https://github.com/your-templates/network-templates
Month 2: Specialization
# Add your domain-specific tools
pip install netmiko ansible # Network
# OR
pip install boto3 kubernetes # Cloud
# OR
pip install python-docx reportlab # Documentation
Month 3: Automation
# Full pipeline
pip install pytest pre-commit
# Set up CI/CD
# Add monitoring
Tool Selection Decision Tree
For Network Engineering:
- Primary: Jinja2 + PyYAML + Netmiko + Ansible
- Documentation: MkDocs + Mermaid
- Advanced: NetBox + Nornir
For Cloud/DevOps:
- Primary: Jinja2 + PyYAML + Terraform + Helm
- Multi-Cloud: Boto3 + Azure SDK + Google Cloud
- Advanced: Kubernetes Python client + ArgoCD
For Sales/Proposals:
- Primary: Jinja2 + PyYAML + ReportLab/python-docx
- Advanced: LaTeX + Pandoc
- Integration: CRM APIs (Salesforce, HubSpot)
Pro Tips for Tool Selection
- Start minimal: Jinja2 + PyYAML + Click gets you 80% of the value
- Add incrementally: Don't boil the ocean—add tools as you hit specific limitations
- Standardize data formats: YAML for configs, JSON for APIs, CSV for bulk data
- Version everything: Templates, data, and generated outputs
- Test templates like code: Unit tests prevent production surprises
Want to dive deep on any specific toolchain? Pick your primary use case (network, cloud, sales) and I'll show you the exact setup with working examples.
Now you have an interactive Jinja2 playground that brings your document to life! This lets you experiment with all the concepts from your data dump in real-time.
What Makes You Dangerous with Jinja2
Based on your comprehensive document, you've identified the key insight: Jinja2 is the invisible force multiplier. Here's your tactical mastery roadmap:
Level 1: Master the Fundamentals (You're Already Here)
- ✅ Variables:
{{ variable }} - ✅ Loops:
{% for item in items %} - ✅ Conditionals:
{% if condition %} - ✅ Filters:
{{ value | default('fallback') }}
Level 2: Advanced Patterns (Your Next Target)
A. Custom Filters for Network Engineering
def subnet_mask(cidr):
"""Convert CIDR to subnet mask"""
return str(ipaddress.IPv4Network(f'0.0.0.0/{cidr}', strict=False).netmask)
env.filters['subnet_mask'] = subnet_mask
Usage: {{ '24' | subnet_mask }} → 255.255.255.0
B. Macros for Reusable Components
{# Define once, use everywhere #}
{% macro cisco_interface(name, ip, vlan=None) %}
interface {{ name }}
ip address {{ ip }}
{% if vlan %} switchport access vlan {{ vlan }}{% endif %}
no shutdown
{% endmacro %}
{# Use it #}
{{ cisco_interface('Gi0/1', '192.168.1.1', vlan=100) }}
Level 3: Systems Integration (Your Competitive Edge)
A. NetBox + Jinja2 Pipeline
# Pull live data from NetBox
import pynetbox
nb = pynetbox.api('https://netbox.company.com', token='your-token')
devices = []
for device in nb.dcim.devices.all():
devices.append({
'name': device.name,
'type': str(device.device_type),
'primary_ip': str(device.primary_ip4).split('/')[0]
})
# Template with live data
template.render(devices=devices)
B. Git-Ops Automation
# .github/workflows/network-configs.yml
name: Generate Network Configs
on:
push:
paths: ['network-data/**']
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Render configs
run: |
pip install jinja2-cli
jinja2 templates/cisco.j2 network-data/prod.yml > configs/prod.cfg
- name: Commit generated configs
run: |
git add configs/
git commit -m "Auto-generated configs"
Level 4: Business Impact (Where You Become Irreplaceable)
A. Proposal Automation (From Your Doc)
- Before: 8 hours per RFP response
- After: 30 minutes with templated proposals
- ROI: 16x time multiplier
B. Compliance as Code
{# NIST 800-53 Control Validation #}
{% for control in nist_controls %}
## {{ control.id }}: {{ control.name }}
Status: {% if control.implemented %}✅ COMPLIANT{% else %}❌ NON-COMPLIANT{% endif %}
{% if not control.implemented %}
**Required Actions:**
{% for action in control.remediation %}
- [ ] {{ action }}
{% endfor %}
{% endif %}
{% endfor %}
Your Next 30 Days
Week 1: Practice the Playground
- Work through all 6 example scenarios in the artifact
- Modify each template to match your real-world data structures
Week 2: Build Your First Production Template
- Choose one repetitive task (device configs, proposals, documentation)
- Create a template + data file
- Measure time savings
Week 3: Add Automation
- Set up a Git repository with templates
- Add basic CI/CD to auto-generate outputs
- Share with one colleague
Week 4: Scale & Share
- Create a template library for your team
- Document best practices
- Start building your reputation as "the automation expert"
Pro Tips from Your Document
-
Start with the pain point: Don't template for templating's sake. Find the manual task that's eating your time.
-
Embrace the invisible nature: As you noted, Jinja2 works backstage. The cleaner your final output, the more professional you look.
-
Multi-format mastery: Use the same data to generate Cisco configs AND Mermaid diagrams AND Word proposals. That's your superpower.
-
Version everything: Templates are code. Treat them like infrastructure.
Want to go deeper on any specific aspect? Pick a scenario from the playground and I'll help you build a production-ready version with real-world data integration.
<html lang="en"> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
min-height: 100vh;
}
.panel {
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
padding: 25px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.2);
}
.panel h2 {
margin-bottom: 20px;
color: #4a5568;
font-size: 1.5rem;
border-bottom: 3px solid #667eea;
padding-bottom: 10px;
}
textarea {
width: 100%;
height: 200px;
padding: 15px;
border: 2px solid #e2e8f0;
border-radius: 8px;
font-family: 'Courier New', monospace;
font-size: 14px;
resize: vertical;
background: #f7fafc;
transition: border-color 0.3s;
}
textarea:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.output {
background: #1a202c;
color: #e2e8f0;
padding: 20px;
border-radius: 8px;
font-family: 'Courier New', monospace;
font-size: 14px;
min-height: 200px;
white-space: pre-wrap;
word-wrap: break-word;
margin-top: 15px;
border: 2px solid #2d3748;
}
.examples {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.example-card {
background: rgba(255, 255, 255, 0.9);
border-radius: 12px;
padding: 20px;
border: 2px solid transparent;
transition: all 0.3s ease;
cursor: pointer;
}
.example-card:hover {
border-color: #667eea;
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
}
.example-card h3 {
color: #667eea;
margin-bottom: 10px;
font-size: 1.2rem;
}
.example-card p {
color: #666;
margin-bottom: 15px;
line-height: 1.6;
}
.example-code {
background: #f1f5f9;
padding: 10px;
border-radius: 6px;
font-family: 'Courier New', monospace;
font-size: 12px;
border-left: 4px solid #667eea;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 25px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.3s;
margin-top: 15px;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.error {
color: #e53e3e;
background: #fed7d7;
padding: 10px;
border-radius: 6px;
border-left: 4px solid #e53e3e;
}
.success {
color: #38a169;
background: #c6f6d5;
padding: 10px;
border-radius: 6px;
border-left: 4px solid #38a169;
}
</style>
</head>
🎯 Template Editor
# {{ network.name }} Configuration <h2 id="user-content-devices" dir="auto">Devices</h2> <p dir="auto">{% for device in network.devices -%}</p> <ul dir="auto"> <li><strong>{{ device.name }}</strong> ({{ device.type }}) <ul dir="auto"> <li>Management IP: {{ device.mgmt_ip }}</li> <li>Role: {{ device.role | default('Unknown') }} {% if device.interfaces -%}</li> <li>Interfaces: {% for intf in device.interfaces -%} <ul dir="auto"> <li>{{ intf.name }}: {{ intf.description | default('No description') }} {% endfor %} {% endif %} {% endfor %}</li> </ul> </li> </ul> </li> </ul> <h2 id="user-content-vlan-summary" dir="auto">VLAN Summary</h2> <p dir="auto">{% set vlans = network.devices | selectattr('vlans', 'defined') | map(attribute='vlans') | list | flatten | unique | sort %} {% if vlans %} Active VLANs: {{ vlans | join(', ') }} {% else %} No VLANs configured {% endif %} 🚀 Render Template <div class="panel">
<h2>📊 Data (YAML/JSON)</h2>
<textarea id="data" placeholder="Enter your YAML or JSON data here...">
network: name: "DataVox Core Network" environment: "production" devices: - name: "Core-SW-01" type: "Cisco Nexus 9000" mgmt_ip: "10.0.1.10" role: "Core Switch" vlans: [10, 20, 30, 100] interfaces: - name: "Eth1/1" description: "Uplink to Firewall" - name: "Eth1/2" description: "Backup uplink" - name: "FW-01" type: "Palo Alto PA-3400" mgmt_ip: "10.0.1.1" role: "Perimeter Firewall" vlans: [100] - name: "Access-SW-01" type: "Cisco Catalyst 9300" mgmt_ip: "10.0.1.20" role: "Access Switch" vlans: [10, 20]
<div class="examples">
<div class="example-card" onclick="loadExample('network')">
<h3>🌐 Network Configuration</h3>
<p>Generate Cisco/Juniper configs from structured data with loops and conditionals.</p>
<div class="example-code">interface {{ intf.name }}
description {{ intf.desc }} {% if intf.vlan %} switchport access vlan {{ intf.vlan }}{% endif %}
<div class="example-card" onclick="loadExample('k8s')">
<h3>☸️ Kubernetes Manifests</h3>
<p>One template → multiple environment-specific YAML manifests.</p>
<div class="example-code">apiVersion: apps/v1
kind: Deployment metadata: name: {{ app_name }}-{{ env }} spec: replicas: {{ replicas[env] }}
<div class="example-card" onclick="loadExample('proposal')">
<h3>📋 Sales Proposals</h3>
<p>Auto-generate professional RFP responses with dynamic pricing.</p>
<div class="example-code"># {{ customer.name }} Proposal
Total: ${{ bom | sum(attribute='cost') }} {% for item in bom %}
-
{{ item.name }}: ${{ item.cost }}{% endfor %}
<div class="example-card" onclick="loadExample('diagram')"> <h3>🔀 Network Diagrams</h3> <p>Generate Mermaid/Graphviz diagrams from network topology data.</p> <div class="example-code">graph TD
{% for device in devices %} {{ device.name }}["{{ device.type }}"]{% endfor %} {% for link in links %} {{ link.src }} --> {{ link.dst }}{% endfor %}
<div class="example-card" onclick="loadExample('security')">
<h3>🔒 Security Policies</h3>
<p>Template firewall rules and compliance checks across environments.</p>
<div class="example-code">{% for rule in acl_rules %}
{{ rule.action }} {{ rule.protocol }} {{ rule.src }} {{ rule.dst }} {% endfor %}
<div class="example-card" onclick="loadExample('advanced')">
<h3>⚡ Advanced Patterns</h3>
<p>Macros, inheritance, custom filters, and complex data transformations.</p>
<div class="example-code">{% macro render_vlan(vlan) %}
vlan {{ vlan.id }} name {{ vlan.name }} {% endmacro %}
<script>
// Simple YAML parser for demo purposes
function parseYAML(yamlStr) {
try {
// This is a very basic YAML parser - in production use js-yaml
const lines = yamlStr.split('\n').filter(line => line.trim() && !line.trim().startsWith('#'));
const result = {};
let currentObj = result;
let objStack = [result];
let keyStack = [];
for (let line of lines) {
const indent = line.length - line.trimLeft().length;
const trimmed = line.trim();
if (trimmed.includes(':')) {
const [key, ...valueParts] = trimmed.split(':');
const value = valueParts.join(':').trim();
// Adjust stack based on indentation
while (keyStack.length > 0 && indent <= keyStack[keyStack.length - 1].indent) {
keyStack.pop();
objStack.pop();
}
currentObj = objStack[objStack.length - 1];
if (value === '' || value === null) {
// This is an object
currentObj[key.trim()] = {};
objStack.push(currentObj[key.trim()]);
keyStack.push({key: key.trim(), indent: indent});
} else if (value.startsWith('[') && value.endsWith(']')) {
// This is an array
try {
currentObj[key.trim()] = JSON.parse(value);
} catch {
currentObj[key.trim()] = value.slice(1, -1).split(',').map(v => v.trim());
}
} else {
// This is a simple value
let parsedValue = value;
if (value === 'true') parsedValue = true;
else if (value === 'false') parsedValue = false;
else if (!isNaN(value) && value !== '') parsedValue = Number(value);
else if (value.startsWith('"') && value.endsWith('"')) parsedValue = value.slice(1, -1);
currentObj[key.trim()] = parsedValue;
}
} else if (trimmed.startsWith('- ')) {
// Handle array items
const parentKey = keyStack[keyStack.length - 1]?.key;
if (parentKey && currentObj[parentKey]) {
if (!Array.isArray(currentObj[parentKey])) {
currentObj[parentKey] = [];
}
const item = trimmed.slice(2).trim();
if (item.includes(':')) {
const itemObj = {};
const [itemKey, itemValue] = item.split(':');
itemObj[itemKey.trim()] = itemValue.trim() || '';
currentObj[parentKey].push(itemObj);
} else {
currentObj[parentKey].push(item);
}
}
}
}
return result;
} catch (e) {
console.error('YAML parsing error:', e);
return {};
}
}
// Simple Jinja2-like template renderer
function renderJinja2Template(template, data) {
let result = template;
// Handle variable substitutions {{ var }}
result = result.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, expr) => {
try {
const parts = expr.split('.');
let value = data;
for (let part of parts) {
part = part.trim();
if (part.includes('|')) {
const [key, ...filters] = part.split('|');
value = value[key.trim()];
for (let filter of filters) {
filter = filter.trim();
if (filter === 'default("Unknown")' || filter === "default('Unknown')") {
value = value || 'Unknown';
} else if (filter.startsWith('default(')) {
const defaultValue = filter.match(/default\(['"](.+)['"]\)/)?.[1] || '';
value = value || defaultValue;
} else if (filter === 'join(", ")' || filter === "join(', ')") {
value = Array.isArray(value) ? value.join(', ') : value;
} else if (filter.startsWith('join(')) {
const separator = filter.match(/join\(['"](.+)['"]\)/)?.[1] || '';
value = Array.isArray(value) ? value.join(separator) : value;
}
}
} else {
value = value?.[part];
}
}
return value !== undefined ? value : '';
} catch (e) {
return match;
}
});
// Handle for loops {% for item in items %}
result = result.replace(/\{%\s*for\s+(\w+)\s+in\s+([\w.]+)\s*-%?\s*%\}([\s\S]*?)\{%\s*endfor\s*%\}/g, (match, itemVar, arrayExpr, loopContent) => {
try {
const parts = arrayExpr.split('.');
let array = data;
for (let part of parts) {
array = array[part];
}
if (!Array.isArray(array)) return '';
return array.map((item, index) => {
let content = loopContent;
content = content.replace(new RegExp(`\\{\\{\\s*${itemVar}\\.(\\w+)\\s*\\}\\}`, 'g'), (m, prop) => {
return item[prop] || '';
});
content = content.replace(new RegExp(`\\{\\{\\s*${itemVar}\\s*\\}\\}`, 'g'), item);
return content;
}).join('');
} catch (e) {
return match;
}
});
// Handle if conditions {% if condition %}
result = result.replace(/\{%\s*if\s+([^%]+)\s*-%?\s*%\}([\s\S]*?)(?:\{%\s*else\s*-%?\s*%\}([\s\S]*?))?\{%\s*endif\s*%\}/g, (match, condition, ifContent, elseContent = '') => {
try {
let conditionResult = false;
if (condition.includes('.')) {
const parts = condition.trim().split('.');
let value = data;
for (let part of parts) {
value = value?.[part];
}
conditionResult = !!value;
}
return conditionResult ? ifContent : elseContent;
} catch (e) {
return ifContent;
}
});
// Handle set statements {% set var = expression %}
result = result.replace(/\{%\s*set\s+(\w+)\s*=\s*([^%]+)\s*%\}/g, (match, varName, expr) => {
// For demo purposes, just remove set statements
return '';
});
// Clean up extra whitespace
result = result.replace(/\n\s*\n\s*\n/g, '\n\n');
return result;
}
function renderTemplate() {
const template = document.getElementById('template').value;
const dataStr = document.getElementById('data').value;
const output = document.getElementById('output');
try {
let data;
if (dataStr.trim().startsWith('{')) {
data = JSON.parse(dataStr);
} else {
data = parseYAML(dataStr);
}
const rendered = renderJinja2Template(template, data);
output.innerHTML = `<div class="success">✅ Template rendered successfully!</div>\n${rendered}`;
} catch (error) {
output.innerHTML = `<div class="error">❌ Error: ${error.message}</div>`;
}
}
function loadExample(type) {
const examples = {
network: {
template: `! {{ device.name }} Configuration
hostname {{ device.name }}
{% for interface in device.interfaces -%} interface {{ interface.name }} description {{ interface.description | default("No description") }} {% if interface.ip -%} ip address {{ interface.ip }} {{ interface.mask }} no shutdown {% endif %} {% if interface.vlan -%} switchport access vlan {{ interface.vlan }} {% endif %} {% endfor %}
! VLAN Configuration
{% for vlan in device.vlans -%}
vlan {{ vlan }}
{% endfor %}, data: device:
name: "SW-CORE-01"
type: "Cisco Catalyst 9000"
interfaces:
- name: "GigabitEthernet1/0/1"
description: "Uplink to Core"
ip: "192.168.1.1"
mask: "255.255.255.0"
- name: "GigabitEthernet1/0/2"
description: "Server Connection"
vlan: 100
vlans: [10, 20, 30, 100]}, k8s: { template:apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ app_name }}-{{ environment }}
labels:
app: {{ app_name }}
env: {{ environment }}
spec:
replicas: {{ replicas[environment] }}
selector:
matchLabels:
app: {{ app_name }}
template:
metadata:
labels:
app: {{ app_name }}
env: {{ environment }}
spec:
containers:
- name: {{ app_name }}
image: {{ registry }}/{{ app_name }}:{{ tag }}
ports:
- containerPort: {{ port }}
env:
{% for key, value in env_vars.items() -%}
- name: {{ key }}
value: "{{ value }}"
{% endfor %}
resources:
requests:
memory: "{{ resources[environment].memory }}"
cpu: "{{ resources[environment].cpu }}", data: app_name: "web-api"
environment: "production"
registry: "docker.io/datavox"
tag: "v1.2.3"
port: 8080
replicas:
development: 1
staging: 2
production: 5
env_vars:
DATABASE_URL: "postgresql://prod-db:5432/app"
REDIS_URL: "redis://prod-cache:6379"
resources:
development:
memory: "256Mi"
cpu: "100m"
staging:
memory: "512Mi"
cpu: "250m"
production:
memory: "1Gi"
cpu: "500m"}, proposal: { template:# {{ customer.name }} Network Modernization Proposal
Executive Summary
Thank you for the opportunity to present DataVox's comprehensive network solution for {{ customer.name }}. Based on your requirements for {{ customer.locations }} locations, we propose the following architecture.
Recommended Solution
{% for solution in solutions -%}
{{ solution.name }}
- Technology: {{ solution.technology }}
- Benefit: {{ solution.benefit }}
- Investment: ${{ solution.cost }} {% endfor %}
Bill of Materials
| Item | Quantity | Unit Price | Extended |
|---|---|---|---|
| {% for item in bom -%} | |||
| {{ item.description }} | {{ item.qty }} | ${{ item.unit_price }} | ${{ item.qty * item.unit_price }} |
| {% endfor %} | |||
| TOTAL | **${{ bom |
Implementation Timeline
{% for phase in timeline -%}
- {{ phase.name }}: {{ phase.duration }} ({{ phase.description }}) {% endfor %}
Why DataVox?
With over 15 years of network architecture expertise, DataVox delivers enterprise-grade solutions that scale with your business., data: customer:
name: "Acme Corporation"
locations: 12
industry: "Manufacturing"
solutions:
- name: "SD-WAN Implementation" technology: "Cisco Viptela" benefit: "40% reduction in WAN costs" cost: 125000
- name: "Network Security" technology: "Palo Alto NGFW" benefit: "Enterprise-grade threat protection" cost: 85000
bom:
- description: "Cisco vEdge 1000 (x12)" qty: 12 unit_price: 2500 total: 30000
- description: "PA-440 Firewall (x3)" qty: 3 unit_price: 3200 total: 9600
- description: "Professional Services" qty: 1 unit_price: 45000 total: 45000
timeline:
- name: "Phase 1 - Design" duration: "2 weeks" description: "Network assessment and detailed design"
- name: "Phase 2 - Deployment" duration: "6 weeks" description: "Equipment installation and configuration"
- name: "Phase 3 - Cutover"
duration: "2 weeks"
description: "Migration and testing"
}, diagram: { template:# {{ network.name }} Topology
```mermaid
graph TD
{% for device in network.devices -%}
{{ device.name }}["{{ device.type }}
{{ device.ip }}"]
{% endfor %}
{% for connection in network.connections -%}
{{ connection.from }} -->|{{ connection.type }}| {{ connection.to }}
{% endfor %}
```
Device Details
{% for device in network.devices -%}
{{ device.name }}
- Type: {{ device.type }}
- Management IP: {{ device.ip }}
- Role: {{ device.role }} {% if device.vlans -%}
- VLANs: {{ device.vlans | join(', ') }} {% endif %}
{% endfor %}, data: network:
name: "DataVox Core Infrastructure"
devices:
- name: "CORE-SW-01"
type: "Cisco Nexus 9300"
ip: "10.0.1.10"
role: "Core Switch"
vlans: [10, 20, 30, 100]
- name: "FW-01"
type: "Palo Alto PA-5220"
ip: "10.0.1.1"
role: "Perimeter Firewall"
- name: "RTR-01"
type: "Cisco ISR 4000"
ip: "10.0.1.5"
role: "WAN Router"
- name: "ACCESS-SW-01"
type: "Cisco Catalyst 9200"
ip: "10.0.2.10"
role: "Access Switch"
vlans: [10, 20]
connections:
- from: "RTR-01"
to: "FW-01"
type: "1Gbps"
- from: "FW-01"
to: "CORE-SW-01"
type: "10Gbps"
- from: "CORE-SW-01"
to: "ACCESS-SW-01"
type: "1Gbps"}, security: { template:! Security Policy Configuration for {{ environment }}
! Generated on {{ timestamp }}
{% for policy in security_policies -%} ! {{ policy.name }} {% for rule in policy.rules -%} access-list {{ policy.acl_number }} {{ rule.action }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }}{% if rule.port %} eq {{ rule.port }}{% endif %} {% endfor %}
{% endfor %}
! Interface Application {% for interface in interfaces -%} interface {{ interface.name }} ip access-group {{ interface.acl }} {{ interface.direction }} {% endfor %}
! Logging Configuration
logging {{ logging.server }}
logging facility {{ logging.facility }}
logging trap {{ logging.level }}, data: environment: "production"
timestamp: "2024-01-15 10:30:00"
security_policies:
- name: "Inbound Web Traffic"
acl_number: 101
rules:
- action: "permit" protocol: "tcp" source: "any" destination: "192.168.1.0 0.0.0.255" port: "80"
- action: "permit" protocol: "tcp" source: "any" destination: "192.168.1.0 0.0.0.255" port: "443"
- action: "deny" protocol: "ip" source: "any" destination: "any"
- name: "Database Access"
acl_number: 102
rules:
- action: "permit" protocol: "tcp" source: "192.168.1.0 0.0.0.255" destination: "192.168.100.0 0.0.0.255" port: "3306"
interfaces:
- name: "GigabitEthernet0/1" acl: 101 direction: "in"
- name: "GigabitEthernet0/2" acl: 102 direction: "out"
logging:
server: "10.0.1.100"
facility: "local0"
level: "informational"}, advanced: { template:{# Macro Definitions #}
{% macro render_interface(interface, base_config={}) -%}
interface {{ interface.name }}
{% for key, value in base_config.items() -%}
{{ key }} {{ value }}
{% endfor -%}
{% if interface.description -%}
description {{ interface.description }}
{% endif -%}
{% if interface.ip -%}
ip address {{ interface.ip }} {{ interface.netmask }}
{% endif -%}
{% if interface.vlan -%}
switchport access vlan {{ interface.vlan }}
{% endif -%}
{% if interface.enabled -%}
no shutdown
{% else -%}
shutdown
{% endif -%}
!
{%- endmacro %}
! {{ hostname }} Advanced Configuration hostname {{ hostname }}
! Standard interface configuration {% set base_interface_config = {"duplex": "full", "speed": "auto"} -%} {% for interface in interfaces -%} {{ render_interface(interface, base_interface_config) }} {% endfor %}
! VLAN Configuration with advanced logic {% set all_vlans = interfaces | selectattr('vlan', 'defined') | map(attribute='vlan') | list | unique | sort -%} {% if all_vlans -%} {% for vlan in all_vlans -%} vlan {{ vlan }} name VLAN_{{ vlan }} {% endfor -%} {% endif %}
! Conditional features {% if features.ospf -%} router ospf {{ features.ospf.process_id }} {% for network in features.ospf.networks -%} network {{ network.address }} {{ network.wildcard }} area {{ network.area }} {% endfor -%} {% endif %}
{% if features.snmp -%}
snmp-server community {{ features.snmp.community }} {{ features.snmp.access }}
snmp-server location {{ features.snmp.location }}
snmp-server contact {{ features.snmp.contact }}
{% endif %}, data: hostname: "ADVANCED-SW-01"
interfaces:
- name: "FastEthernet0/1" description: "Server Connection" ip: "192.168.10.1" netmask: "255.255.255.0" vlan: 10 enabled: true
- name: "FastEthernet0/2" description: "Uplink to Core" ip: "192.168.20.1" netmask: "255.255.255.0" vlan: 20 enabled: true
- name: "FastEthernet0/3" description: "Management Interface" ip: "10.0.0.10" netmask: "255.255.255.0" enabled: false
features: ospf: process_id: 100 networks: - address: "192.168.10.0" wildcard: "0.0.0.255" area: 0 - address: "192.168.20.0" wildcard: "0.0.0.255" area: 0 snmp: community: "public" access: "ro" location: "DataCenter-A" contact: "netadmin@datavox.com"` } };
const example = examples[type];
if (example) {
document.getElementById('template').value = example.template;
document.getElementById('data').value = example.data;
renderTemplate();
}
}
network: {
template: `! {{ device.name }} Configuration
hostname {{ device.name }}
{% for interface in device.interfaces -%} interface {{ interface.name }} description {{ interface.description | default("No description") }} {% if interface.ip -%} ip address {{ interface.ip }} {{ interface.mask }} no shutdown {% endif %} {% if interface.vlan -%} switchport access vlan {{ interface.vlan }} {% endif %} {% endfor %}
! VLAN Configuration
{% for vlan in device.vlans -%}
vlan {{ vlan }}
{% endfor %}, data: device:
name: "SW-CORE-01"
type: "Cisco Catalyst 9000"
interfaces:
- name: "GigabitEthernet1/0/1"
description: "Uplink to Core"
ip: "192.168.1.1"
mask: "255.255.255.0"
- name: "GigabitEthernet1/0/2"
description: "Server Connection"
vlan: 100
vlans: [10, 20, 30, 100]}, k8s: { template:apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ app_name }}-{{ environment }}
labels:
app: {{ app_name }}
env: {{ environment }}
spec:
replicas: {{ replicas[environment] }}
selector:
matchLabels:
app: {{ app_name }}
template:
metadata:
labels:
app: {{ app_name }}
env: {{ environment }}
spec:
containers:
- name: {{ app_name }}
image: {{ registry }}/{{ app_name }}:{{ tag }}
ports:
- containerPort: {{ port }}
env:
{% for key, value in env_vars.items() -%}
- name: {{ key }}
value: "{{ value }}"
{% endfor %}
resources:
requests:
memory: "{{ resources[environment].memory }}"
cpu: "{{ resources[environment].cpu }}", data: app_name: "web-api"
environment: "production"
registry: "docker.io/datavox"
tag: "v1.2.3"
port: 8080
replicas:
development: 1
staging: 2
production: 5
env_vars:
DATABASE_URL: "postgresql://prod-db:5432/app"
REDIS_URL: "redis://prod-cache:6379"
resources:
development:
memory: "256Mi"
cpu: "100m"
staging:
memory: "512Mi"
cpu: "250m"
production:
memory: "1Gi"
cpu: "500m"}, proposal: { template:# {{ customer.name }} Network Modernization Proposal
Executive Summary
Thank you for the opportunity to present DataVox's comprehensive network solution for {{ customer.name }}. Based on your requirements for {{ customer.locations }} locations, we propose the following architecture.
Recommended Solution
{% for solution in solutions -%}
{{ solution.name }}
- Technology: {{ solution.technology }}
- Benefit: {{ solution.benefit }}
- Investment: ${{ solution.cost }} {% endfor %}
Bill of Materials
| Item | Quantity | Unit Price | Extended |
|---|---|---|---|
| {% for item in bom -%} | |||
| {{ item.description }} | {{ item.qty }} | ${{ item.unit_price }} | ${{ item.qty * item.unit_price }} |
| {% endfor %} | |||
| TOTAL | **${{ bom |
Implementation Timeline
{% for phase in timeline -%}
- {{ phase.name }}: {{ phase.duration }} ({{ phase.description }}) {% endfor %}
Why DataVox?
With over 15 years of network architecture expertise, DataVox delivers enterprise-grade solutions that scale with your business., data: customer:
name: "Acme Corporation"
locations: 12
industry: "Manufacturing"
solutions:
- name: "SD-WAN Implementation" technology: "Cisco Viptela" benefit: "40% reduction in WAN costs" cost: 125000
- name: "Network Security" technology: "Palo Alto NGFW" benefit: "Enterprise-grade threat protection" cost: 85000
bom:
- description: "Cisco vEdge 1000 (x12)" qty: 12 unit_price: 2500 total: 30000
- description: "PA-440 Firewall (x3)" qty: 3 unit_price: 3200 total: 9600
- description: "Professional Services" qty: 1 unit_price: 45000 total: 45000
timeline:
- name: "Phase 1 - Design" duration: "2 weeks" description: "Network assessment and detailed design"
- name: "Phase 2 - Deployment" duration: "6 weeks" description: "Equipment installation and configuration"
- name: "Phase 3 - Cutover"
duration: "2 weeks"
description: "Migration and testing"
}, diagram: { template:# {{ network.name }} Topology
```mermaid
graph TD
{% for device in network.devices -%}
{{ device.name }}["{{ device.type }}
{{ device.ip }}"]
{% endfor %}
{% for connection in network.connections -%}
{{ connection.from }} -->|{{ connection.type }}| {{ connection.to }}
{% endfor %}
```
Device Details
{% for device in network.devices -%}
{{ device.name }}
- Type: {{ device.type }}
- Management IP: {{ device.ip }}
- Role: {{ device.role }} {% if device.vlans -%}
- VLANs: {{ device.vlans | join(', ') }} {% endif %}
{% endfor %}, data: network:
name: "DataVox Core Infrastructure"
devices:
- name: "CORE-SW-01"
type: "Cisco Nexus 9300"
ip: "10.0.1.10"
role: "Core Switch"
vlans: [10, 20, 30, 100]
- name: "FW-01"
type: "Palo Alto PA-5220"
ip: "10.0.1.1"
role: "Perimeter Firewall"
- name: "RTR-01"
type: "Cisco ISR 4000"
ip: "10.0.1.5"
role: "WAN Router"
- name: "ACCESS-SW-01"
type: "Cisco Catalyst 9200"
ip: "10.0.2.10"
role: "Access Switch"
vlans: [10, 20]
connections:
- from: "RTR-01"
to: "FW-01"
type: "1Gbps"
- from: "FW-01"
to: "CORE-SW-01"
type: "10Gbps"
- from: "CORE-SW-01"
to: "ACCESS-SW-01"
type: "1Gbps"}, security: { template:! Security Policy Configuration for {{ environment }}
! Generated on {{ timestamp }}
{% for policy in security_policies -%} ! {{ policy.name }} {% for rule in policy.rules -%} access-list {{ policy.acl_number }} {{ rule.action }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }}{% if rule.port %} eq {{ rule.port }}{% endif %} {% endfor %}
{% endfor %}
! Interface Application {% for interface in interfaces -%} interface {{ interface.name }} ip access-group {{ interface.acl }} {{ interface.direction }} {% endfor %}
! Logging Configuration
logging {{ logging.server }}
logging facility {{ logging.facility }}
logging trap {{ logging.level }}, data: environment: "production"
timestamp: "2024-01-15 10:30:00"
security_policies:
- name: "Inbound Web Traffic"
acl_number: 101
rules:
- action: "permit" protocol: "tcp" source: "any" destination: "192.168.1.0 0.0.0.255" port: "80"
- action: "permit" protocol: "tcp" source: "any" destination: "192.168.1.0 0.0.0.255" port: "443"
- action: "deny" protocol: "ip" source: "any" destination: "any"
- name: "Database Access"
acl_number: 102
rules:
- action: "permit" protocol: "tcp" source: "192.168.1.0 0.0.0.255" destination: "192.168.100.0 0.0.0.255" port: "3306"
interfaces:
- name: "GigabitEthernet0/1" acl: 101 direction: "in"
- name: "GigabitEthernet0/2" acl: 102 direction: "out"
logging:
server: "10.0.1.100"
facility: "local0"
level: "informational"}, advanced: { template:{# Macro Definitions #}
{% macro render_interface(interface, base_config={}) -%}
interface {{ interface.name }}
{% for key, value in base_config.items() -%}
{{ key }} {{ value }}
{% endfor -%}
{% if interface.description -%}
description {{ interface.description }}
{% endif -%}
{% if interface.ip -%}
ip address {{ interface.ip }} {{ interface.netmask }}
{% endif -%}
{% if interface.vlan -%}
switchport access vlan {{ interface.vlan }}
{% endif -%}
{% if interface.enabled -%}
no shutdown
{% else -%}
shutdown
{% endif -%}
!
{%- endmacro %}
! {{ hostname }} Advanced Configuration hostname {{ hostname }}
! Standard interface configuration {% set base_interface_config = {"duplex": "full", "speed": "auto"} -%} {% for interface in interfaces -%} {{ render_interface(interface, base_interface_config) }} {% endfor %}
! VLAN Configuration with advanced logic {% set all_vlans = interfaces | selectattr('vlan', 'defined') | map(attribute='vlan') | list | unique | sort -%} {% if all_vlans -%} {% for vlan in all_vlans -%} vlan {{ vlan }} name VLAN_{{ vlan }} {% endfor -%} {% endif %}
! Conditional features {% if features.ospf -%} router ospf {{ features.ospf.process_id }} {% for network in features.ospf.networks -%} network {{ network.address }} {{ network.wildcard }} area {{ network.area }} {% endfor -%} {% endif %}
{% if features.snmp -%}
snmp-server community {{ features.snmp.community }} {{ features.snmp.access }}
snmp-server location {{ features.snmp.location }}
snmp-server contact {{ features.snmp.contact }}
{% endif %}, data: hostname: "ADVANCED-SW-01"
interfaces:
- name: "FastEthernet0/2" description: "Uplink to Core" ip: "192.168.20.1" netmask: "255.255.255.0" vlan: 20 enabled: true
- name: "FastEthernet0/3" description: "Management Interface" ip: "10.0.0.10" netmask: "255.255.255.0" enabled: false
features: ospf: process_id: 100 networks: - address: "192.168.10.0" wildcard: "0.0.0.255" area: 0 - address: "192.168.20.0" wildcard: "0.0.0.255" area: 0 snmp: community: "public" access: "ro" location: "DataCenter-A" contact: "netadmin@datavox.com"`/1" description: "Server Connection" ip: "192.168.10.1" netmask: "255.255.255.0" vlan: 10 enabled: true
- name: "FastEthernet0