Git / NetDevOps
Versioning Real Automation Artifacts: Rendered Templates and NetBox Snapshots
What you'll learn
- Versioning already-known output, not re-producing it
- A real, verified commit of a rendered-config-shaped artifact
- A real, verified commit of a NetBox-style snapshot, as a static fixture
- Reading a real diff that shows a source-of-truth change over time
Listen to a guided explanation of this lesson.
Spoken narration isn't supported in this browser.
Two artifacts this curriculum already knows how to produce
Output, not production
This lesson does not render a Jinja2 template (Phase 2.9) or query NetBox (Phase 3.7) -- both are treated as already-known, already-verified capabilities. What's new here is committing their OUTPUT to a real repository, so that output has a history.
rendered_config = (
"hostname SW2\n"
"interface Ethernet1\n"
" description mgmt-uplink\n"
"vlan 10\n"
" name USERS\n"
)
with open("repo2/rendered_sw2.cfg", "w") as f:
f.write(rendered_config)
repo.index.add(["rendered_sw2.cfg"])
commit1 = repo.index.commit("Commit rendered SW2 config")rendered_config here is written directly, standing in for whatever Phase 2.9's Jinja2 rendering already produced -- this lesson picks up after rendering, not during it.
A NetBox-style snapshot: a static, clearly-labeled fixture
Not Phase 3.7's mock server, reinvoked
Phase 3.7 built a real, local mock NetBox REST backend and queried it live with pynetbox. This lesson does neither -- netbox_snapshot below is a plain, static JSON fixture, explicitly labeled as a stand-in for what a real NetBox export would look like. The subject here is versioning that snapshot, not querying NetBox again.
netbox_snapshot = {
"_source": "NetBox export snapshot (static fixture, not a live query)",
"devices": [
{"name": "SW1", "site": "hq", "platform": "cisco_ios"},
{"name": "SW2", "site": "hq", "platform": "arista_eos"},
],
}
with open("repo2/netbox_snapshot.json", "w") as f:
json.dump(netbox_snapshot, f, indent=2)
repo.index.add(["netbox_snapshot.json"])
commit2 = repo.index.commit("Commit NetBox inventory snapshot")The _source field states plainly what this is -- a fixture, not a live NetBox response. Real, verified commit, executed against a real local repo.
commit1: 60aaa6b3 'Commit rendered SW2 config'
commit2: bc2170be 'Commit NetBox inventory snapshot'Real, verified output. Two commits, two different artifact types, in the same repository.
Diffing a source-of-truth change over time
snapshot["devices"].append(
{"name": "SW3", "site": "branch1", "platform": "cisco_ios"}
)
with open("repo2/netbox_snapshot.json", "w") as f:
json.dump(snapshot, f, indent=2)
print(repo.git.diff("netbox_snapshot.json"))Phase 3.7's own capstone proved live that adding a NetBox device record changes what Nornir loads. This lesson shows the other half: that same change, now captured permanently in history.
diff --git a/netbox_snapshot.json b/netbox_snapshot.json
index b08e2ae..6889e50 100644
--- a/netbox_snapshot.json
+++ b/netbox_snapshot.json
@@ -10,6 +10,11 @@
"name": "SW2",
"site": "hq",
"platform": "arista_eos"
+ },
+ {
+ "name": "SW3",
+ "site": "branch1",
+ "platform": "cisco_ios"
}
]
}
\ No newline at end of fileReal, verified output, shown exactly as produced -- including git's own trailing 'no newline at end of file' marker line, a genuine artifact of how the JSON was written, not edited out.
Key takeaways
- This lesson versions output already known how to produce (Phase 2.9's rendering, Phase 3.7's NetBox data) -- it doesn't re-teach producing either.
- The NetBox snapshot is a static, explicitly-labeled fixture -- Phase 3.7's real mock server was deliberately not reinvoked.
- Two real commits, two different artifact types, verified in the same repository.
- A real diff showed a source-of-truth change over time -- the permanent-record complement to Phase 3.7's own live dynamic-inventory demonstration.