Generator Manager
Skill: infrahub-managing-generators
The Generator Manager produces, modifies, and debugs Python generators that query Infrahub for design objects and automatically create or update the infrastructure objects derived from them. Generators are idempotent: re-running them updates existing objects rather than creating duplicates. The skill generates the Python class, GraphQL query, and .infrahub.yml registration.
When to use
- Auto-creating devices, interfaces, and IP addresses from a fabric design object
- Generating BGP sessions from a topology design
- Creating any set of objects that should be derived from a design definition and kept in sync with it
- Any scenario where "given this design, create these objects" needs to run repeatedly as the design evolves
- Changing what an existing generator produces, or working out why a run created, skipped, or deleted the wrong objects
What it produces
Three components:
- Target group: a
CoreGeneratorGroupthat defines which design objects trigger the generator - GraphQL query (
.gql): fetches the design object(s) the generator will act on - Python class (
InfrahubGeneratorsubclass): implements theasync generate()method, usesself.client.create()withallow_upsert=True
The .infrahub.yml entry tying them together includes a watch dependency declaration.
Example prompts
- "Create a generator that takes a fabric design object and creates all spine and leaf devices with their loopback interfaces"
- "Write a generator that creates BGP sessions between all spine-leaf pairs defined in a topology design"
- "Generate IP address assignments for all interfaces based on a design's IP allocation scheme"
- "Re-running this generator deleted an interface it did not create. Work out why and fix it"
Key rules enforced
allow_upsert=True: always set onself.client.create()calls; without it, re-running the generator creates duplicates instead of updating existing objectsdelete_unused_nodes=True: enables automatic cleanup of objects that were created by the generator but are no longer in the design; prevents orphaned objects from accumulating over time- Target group: generator must reference a
CoreGeneratorGroup; this is what connects design objects to the generator execution - Async
generate()method: the method signature must beasync def generate(self, data): - GraphQL query naming: query name must match the
queryclass attribute watchdependencies: thegenerator_definitionsentry always includes awatchblock naming every first-party module the generator imports, sibling query models included (files: []when there are none); imports are never analyzed, so without the key the generator re-runs on every commit, and with an incomplete list a change to a shared helper silently stops re-running it
Common mistakes it catches
| Mistake | What the skill does instead |
|---|---|
Missing allow_upsert=True | Always includes it; prevents duplicate creation on re-run |
Missing delete_unused_nodes=True | Always includes it; prevents orphaned objects |
Sync generate() method | Uses async def generate(self, data): |
| Missing target group configuration | Generates the CoreGeneratorGroup definition |
| Generator that only stamps a fixed structure with constant values | Recommends an Object Template (generate_template) to clone instead; the structure is in data, not Python |
Hand-editing schema.graphql to add a field a query needs | Re-exports it with infrahubctl graphql export-schema: the file is generated, so a hand-edit is discarded on the next export |
Running it
Generators run automatically when a design object in their target group changes. To run a generator manually:
infrahubctl generator <generator-name>