Metaprogramming Roadmap
Code that writes code. A unified approach to generating CLI commands, documentation, configurations, and policies from single sources of truth.
Current Metaprogramming (Already Doing)
| Project | Pattern | What It Does |
|---|---|---|
Antora attributes |
Data → Docs |
|
Antora partials |
Fragment → Full page |
Single table partial, included in many pages |
netapi CLI |
Schema → Commands |
ISE OpenAPI introspection → CLI commands |
Jinja2 templates |
Data + Template → Config |
YAML variables → switch/firewall configs |
dsec |
Encrypted data → Environment |
|
Terraform |
HCL → Infrastructure |
Declarative specs → VMs, DNS, policies |
Vision: One Truth, Infinite Outputs
┌─────────────────┐
│ YAML Schema │
│ (Single Truth) │
└────────┬────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CLI Commands │ │ Documentation │ │ Configurations │
│ (netapi) │ │ (Antora) │ │ (switches, FW) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ ISE Policies │ │ Ansible Inv. │ │ Terraform TF │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Phase 1: Infrastructure Schema
Goal: Single YAML file defines all infrastructure, generates everything else.
1.1 Schema Design
# infrastructure.yml - THE source of truth
domain: inside.domusdigitalis.dev
hosts:
vault-01:
ip: 10.50.1.60
mac: "aa:bb:cc:dd:ee:f1"
roles: [pki, ssh-ca, secrets]
os: rocky-9
location: kvm-01
ise-01:
ip: 10.50.1.20
roles: [radius, admin, mnt, psn]
os: ise-3.4
k3s-master-01:
ip: 10.50.1.120
roles: [k3s-control-plane]
os: rocky-9
vlans:
mgmt:
id: 100
subnet: 10.50.1.0/24
gateway: 10.50.1.1
data:
id: 10
subnet: 10.50.10.0/24
1.2 Generators
| Generator | Input | Output |
|---|---|---|
|
|
|
|
|
|
|
|
BIND DNS zone record commands |
|
|
|
|
|
AsciiDoc partials (IP tables, host lists) |
1.3 Implementation
# domus-metagen/generators/antora.py
import yaml
from jinja2 import Template
def generate_antora_attributes(infra_file: str) -> str:
"""Generate Antora attributes from infrastructure schema."""
with open(infra_file) as f:
infra = yaml.safe_load(f)
attrs = []
for hostname, host in infra['hosts'].items():
attrs.append(f" {hostname}-ip: {host['ip']}")
attrs.append(f" {hostname}-hostname: {hostname}.{infra['domain']}")
return "\n".join(attrs)
Phase 2: OpenAPI → CLI Generation
Goal: Auto-generate 100% of netapi commands from OpenAPI/Swagger specs.
2.2 Target State
# Read OpenAPI spec, generate Click commands
from openapi_parser import parse
spec = parse("ise-ers-openapi.json")
for path, methods in spec.paths.items():
for method, operation in methods.items():
generate_click_command(
name=operation.operation_id,
method=method,
path=path,
params=operation.parameters,
body=operation.request_body
)
Phase 3: Policy as Code
Goal: Define ISE policies in YAML, generate API calls.
3.1 Policy Schema
# policies/linux-eaptls.yml
policy_set: Wired_802.1X_Closed
authorization_rules:
- name: Linux-AD-Auth-Full-Access
rank: 1
conditions:
- type: certificate
attribute: Subject-CN
matches: "*.inside.domusdigitalis.dev"
- type: ad_group
name: GRP-Linux-Computers
result:
profile: Linux-Full-Access
dacl: DACL-Linux-AD-Auth
- name: Linux-Onboarding
rank: 2
conditions:
- type: authentication_method
equals: MAB
result:
profile: Linux-Onboarding
dacl: DACL-Linux-Onboard
dacls:
DACL-Linux-AD-Auth:
rules:
- permit tcp any host {ad-dc-ip} eq 88
- permit tcp any host {ad-dc-ip} eq 389
- permit udp any host {ad-dc-ip} eq 53
- deny ip any any
3.2 Generator
# Generate ISE API calls from policy YAML
domus-metagen policy apply policies/linux-eaptls.yml
# Output:
# Creating dACL: DACL-Linux-AD-Auth
# netapi ise ers dacl-create --name DACL-Linux-AD-Auth --content "permit tcp..."
# Creating authorization rule: Linux-AD-Auth-Full-Access
# netapi ise policy authz-rule-create --policy-set Wired_802.1X_Closed ...
Phase 4: Executable Documentation
Goal: Runbooks contain code that can be extracted and run.
4.1 Tagged Code Blocks
// In runbook.adoc
[source,bash,tag=verify-ise-sessions]
netapi ise mnt sessions | jq '.[] | {mac, status, policy}'
4.2 Extractor
# Extract tagged code blocks from AsciiDoc
def extract_runnable_blocks(adoc_file: str) -> dict:
blocks = {}
for block in parse_code_blocks(adoc_file):
if block.tag:
blocks[block.tag] = block.content
return blocks
# Usage
blocks = extract_runnable_blocks("k3s-deployment.adoc")
run(blocks["verify-ise-sessions"])
Phase 5: The Meta-Platform
Goal: domus-metagen - unified generator toolkit.
5.1 Project Structure
domus-metagen/
├── schemas/
│ ├── infrastructure.yml # Host/network definitions
│ ├── policies/ # ISE policy definitions
│ └── services/ # Service configurations
├── generators/
│ ├── antora.py # Generate Antora attributes
│ ├── ansible.py # Generate Ansible inventory
│ ├── terraform.py # Generate Terraform vars
│ ├── dns.py # Generate DNS records
│ ├── cli.py # Generate netapi commands
│ └── policy.py # Generate ISE policies
├── templates/
│ ├── antora.yml.j2
│ ├── inventory.yml.j2
│ └── partial-table.adoc.j2
└── cli.py # Main CLI entry point
5.2 Usage
# Generate everything from schema
domus-metagen generate all
# Generate specific outputs
domus-metagen generate antora-attrs
domus-metagen generate ansible-inventory
domus-metagen generate dns-records
# Apply policies
domus-metagen policy apply policies/linux-eaptls.yml
# Validate schema
domus-metagen validate schemas/infrastructure.yml
Diagnostic Commands Reference
Commands used for metaprogramming-style debugging:
# Print specific line range with numbers
awk 'NR>=950 && NR<=970 {print NR": "$0}' file.adoc
# Find patterns in backticks
grep -n '`[^`]*|[^`]*`' file.adoc
# Extract all code blocks from AsciiDoc
awk '/^\[source,bash\]/,/^----$/' runbook.adoc
# Generate attribute list from grep
grep -h "^ [a-z-]*-ip:" */antora.yml | sort -u
# Count patterns across repos
for repo in domus-*/; do
echo "=== $repo ==="
grep -c "xref:" "$repo/docs"/**/*.adoc 2>/dev/null | awk -F: '{sum+=$2} END {print sum}'
done
Reading List
-
The Pragmatic Programmer - "Don’t Repeat Yourself" principle
-
Structure and Interpretation of Computer Programs - Lisp metaprogramming
-
Metaprogramming Ruby - Even if not Ruby, concepts transfer
-
Domain-Specific Languages by Martin Fowler
Related
-
Docs as Code - Documentation generation
-
Network Automation - Config generation
-
CI/CD Automation - Pipeline generation