关于 infrahub-managing-generators
infrahub-managing-generators 面向创建 Infrahub Generator 的开发者,讲解如何用 GraphQL 查询设计数据并生成受跟踪的基础设施对象,并涵盖 Schema、注册和测试。
主要功能
- 01按设计生成对象
- 02GraphQL 查询指导
- 03Python Generator 实现
- 04幂等创建或更新模式
- 05Generator 注册与依赖跟踪
- 06使用 infrahubctl 验证
适用场景
- 01根据设计对象生成基础设施
- 02从模板创建对象和关系
- 03实现可重复运行的 Generator
- 04排查 Generator 的 Schema 或跟踪问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ opsmill/ infrahub-skills --skill infrahub-managing-generators安装后在 Claude Code 中输入/infrahub-managing-generators确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples.mdreference.mdrules/_sections.md_template.mdapi-reference.mdarchitecture-components.mdpatterns-common.mdpatterns-hydration.mdpatterns-natural-key-preflight.mdpatterns-path-traversal.mdpython-concurrent-relationship-writes.mdpython-delete-ordering.mdpython-generate.mdpython-multi-peer-add.mdpython-relationship-references.mdregistration-config.mdregistration-watch-dependencies.mdtesting-commands.mdtesting-integration.mdtracking-idempotent.md详细介绍
Infrahub 生成器创建指南
概述
创建 Infrahub 生成器的专业指南。生成器通过 GraphQL 从 Infrahub 查询数据,并根据结果创建新的节点和关系——实现由设计驱动的自动化,让“设计”对象自动创建下游基础设施。
项目上下文
Infrahub 配置:
!cat .infrahub.yml 2>/dev/null || echo "No .infrahub.yml found"
现有生成器:
!find . -name "*.py" -path "*/generators/*" 2>/dev/null | head -20
适用场景
- 构建设计驱动的自动化(拓扑 -> 设备)
- 根据模板或设计定义创建对象
- 实现幂等的创建或更新工作流
- 根据高级设计自动生成基础设施
- 了解生成器跟踪系统
规则类别
| 优先级 | 类别 | 前缀 | 描述 |
|---|---|---|---|
| CRITICAL | 架构 | architecture- | 组件、组 |
| CRITICAL | Python 类 | python- | 生成器、generate() |
| HIGH | 跟踪 | tracking- | Upsert、幂等 |
| HIGH | API 参考 | api- | 构造函数、属性 |
| HIGH | 注册 | registration- | .infrahub.yml 配置 |
| MEDIUM | 模式 | patterns- | 清理、批处理、存储 |
| LOW | 测试 | testing- | infrahubctl 命令 |
此技能依赖的前置条件
生成器会创建真实对象,因此架构必须 允许其生成的结构。在首次运行前找出这些缺口—— 重新运行有缺陷的生成器可能会通过跟踪清理 删除数据。
| 如果生成器…… | 架构必须…… | 参见 |
|---|---|---|
| 创建 X 类型的对象 | 定义 X 节点,并包含生成器设置的属性——如果该类型没有某个字段,该字段会在发送请求前被丢弃,且不会报错;缺少必需字段则会导致创建失败 | ../infrahub-managing-schemas/rules/attribute-defaults-and-types.md |
| 将创建的对象关联到父对象 | 配置一对标识符匹配的 Component/Parent 关系,并在 Parent 侧设置 optional: false | ../infrahub-managing-schemas/rules/relationship-component-parent.md |
| 读取“设计”节点以驱动输出 | 为该节点定义 human_friendly_id,确保生成器的跟踪键在不同运行间保持稳定 | ../infrahub-managing-schemas/rules/display-human-friendly-id.md |
| 由加入某个组触发 | 以设计对象已有的组为目标,该组可以是任何类型;仅当不存在组时才创建 CoreStandardGroup。CoreGeneratorGroup 是生成器自身的输出组 | rules/registration-config.md |
| 重新运行时应具有幂等性 | 每次 save() 都使用 allow_upsert=True;运行的跟踪上下文会删除之前运行创建但本次未重新创建的对象 | rules/tracking-idempotent.md |
| 从仓库导入任何内容(共享包、生成的协议、自身的查询模型) | 在 .infrahub.yml 中添加 watch: 块,列出所有这些路径——导入不会被自动追踪,因此未声明的辅助文件发生变化时,生成器会悄无声息地停止重新运行 | rules/registration-watch-dependencies.md |
| 向基数为多的关系添加多个对等对象 | 对列表使用 .extend(),或逐个对等对象循环调用 .add()——绝不能使用 .add() 添加列表 | rules/python-multi-peer-add.md |
| 向可能由多个运行同时写入的关系添加对等对象 | node.add_relationships(relation_to_update=..., related_nodes=[ids]) | rules/python-concurrent-relationship-writes.md |
| 删除生成器之前创建的对象 | 删除对等对象前,先解除指向它们的关系,并在两步之间保存持有对象——删除后调用 save(allow_upsert=True) 会重新发送内存管理器中的 ID | rules/python-delete-ordering.md |
| 修改生成器,使其生成的对象集合与上次运行不同 | 检查从 generate() 可到达的每个 save(),包括辅助函数中的调用 | rules/tracking-idempotent.md |
编写 Python 之前
生成器应根据设计计算对象。如果你打算写的是“从硬编码列表中创建这 N 个特定对象”,那么该列表就是数据——请将其移到 objects/,并让对象加载器直接处理,或将其传给更小的生成器。在使用 InfrahubGenerator 之前,先按以下层级逐项检查:
| 信号 | 更轻量的层 | 参见规则 |
|---|---|---|
| 生成器硬编码对象列表、角色目录或状态集合 | objects/ 下的 YAML 数据文件(由对象加载器加载) | yagni-generator-hardcoding-data |
| 生成器重新实现内置的 IPAM/VLAN 基础类型(自定义 IP 地址、前缀、VLAN 节点) | 在架构中使用 inherit_from: [BuiltinIPAddress / BuiltinIPPrefix / IpamVLAN],然后让生成器计算引用,而不是重新实现基础类型 | yagni-custom-domain-primitives-instead-of-builtin |
生成器的输出结构与 opsmill/schema-library 中已有的对象重复 | 从库中的通用类型 inherit_from;生成器计算实例,而非结构 | yagni-duplicate-shape-not-extracted-to-generic |
生成器使用 ipaddress 运算、random 或手写的“查找第一个可用项”循环来分配子网/IP/VLAN/端口 | 使用内置资源池——allocate_next_ip_prefix / allocate_next_ip_address、CoreIPPrefixPool / CoreNumberPool——它会跟踪利用率,并在重新运行时保持幂等 | yagni-imperative-allocation-vs-resource-pool |
generate() 使用固定值创建一组固定的子对象,不进行计算(没有分支、派生命名或分配) | 对象模板(generate_template: true),供用户克隆——结构保存在数据中,而非 Python 中 | yagni-generator-that-should-be-template |
引导、种子和演示生成器(位于 bootstrap/、seed/、demo/ 下)不受此限制——它们的存在目的就是硬编码初始状态。只有当生成器确实需要根据设计定义计算对象时才使用 Python;适用情形请参见 rules/python-generate.md。
开始编写 Python 后,请使用生成的协议类为 SDK 调用添加类型,而不是使用字符串类型——例如 client.create(NetworkDevice, ...),而非 kind="NetworkDevice"——这样架构变更会在类型检查时暴露返回对象的属性读取问题。传给 create() 的字段名称不会进行类型检查。请参见 protocols-adopt-typed-kinds。
生成器基础
每个生成器包含三个部分:
- 目标组 -- 触发生成器的对象
- GraphQL 查询(
.gql文件)-- 获取设计数据 - Python 类 -- 继承
InfrahubGenerator,实现generate()
from infrahub_sdk.generator import InfrahubGenerator
class MyGenerator(InfrahubGenerator):
async def generate(self, data: dict) -> None:
obj = await self.client.create(
kind="DcimDevice",
data={"name": "spine-01"},
)
await obj.save(allow_upsert=True)
工作流
创建生成器时,请按以下步骤操作:
- 确定设计模式 — 哪个“设计”对象会触发生成?应从中创建哪些对象?阅读 rules/architecture-components.md 了解目标组和生成器组件。
- 编写 GraphQL 查询 — 创建一个
.gql文件来获取设计数据。阅读 ../infrahub-common/graphql-queries.md 了解查询模式。如果仓库中有schema.graphql,该文件是生成的 — 缺少字段时,应重新导出该文件,而不是编辑它。阅读 ../infrahub-common/rules/protocols-generated.md。 - 实现 Python 类 — 继承
InfrahubGenerator,实现generate()。阅读 rules/python-generate.md 了解类模式,并阅读 rules/api-reference.md 了解可用方法。 - 确保操作幂等 — 使用
allow_upsert=True,使重复运行能够创建或更新内容,而不会产生重复项。参见 rules/tracking-idempotent.md。 - 检查是否有采用
from_graphql的机会 — 如果generate()遍历响应边并调用self.client.get()重新获取类型化对等节点,请考虑重构为InfrahubNode.from_graphql(),将O(N + 1)次往返请求减少到O(1)。阅读 rules/patterns-hydration.md 了解决策树、检测启发式方法和重构步骤。 - 限制任何图遍历的范围。如果
generate()需要两个节点之间的路径,请使用 SDK 的traverse_paths,而不是手动逐跳遍历,并通过关系标识符和深度上限限制遍历范围。按类型筛选只会限制哪些节点可以出现,不会限制沿哪些边遍历,因此,共享的引用对象仍会连接无关子图,导致遍历返回结构上有效但实际无意义的结果。阅读 rules/patterns-path-traversal.md 了解参数语义和截断信号。 - 在 .infrahub.yml 中注册 — 在
generator_definitions下添加条目,并指定目标组。参见 rules/registration-config.md。 然后使用watch.files声明生成器的依赖项:检查它的导入和运行时文件读取,并列出这些路径解析到的所有一方路径 — 包括同级查询模型。始终保留此键;如果生成器确实没有自身文件以外的依赖项,则使用files: []。阅读 rules/registration-watch-dependencies.md,其中也介绍了如何检查现有watch块中是否缺少条目、条目是否过时或不正确。 - 测试 — 运行
infrahubctl generator进行验证。参见 rules/testing-commands.md。
参考资料
- reference.md -- 类 API、生命周期、幂等性约定、
.infrahub.yml注册(其结构要求提供query:,与 check_definitions 不同) - examples.md -- 完整的 Generator 模式(POP 拓扑、网络网段、最小示例)
- ../infrahub-common/graphql-queries.md -- GraphQL 查询编写参考
- ../infrahub-common/infrahub-yml-reference.md -- .infrahub.yml 项目配置
- ../infrahub-common/marketplace-reference.md -- 在手动编写目标数据模型以供生成器使用之前,先复用 Marketplace 发布的架构
- ../infrahub-common/rules/ -- 通用规则 (Git 集成、缓存注意事项)
- ../infrahub-common/rules/workflow-information-priority.md
-- 优先查阅 Skill 内容;遇到确实的内容缺口时(例如删除节点),如何查阅
docs.infrahub.app - ../infrahub-managing-schemas/SKILL.md -- Generator 使用的架构定义
- rules/ -- 按类别前缀整理的各项规则