mcpField
I
infrahub-managing-generators

infrahub-managing-generators

github.com/opsmill云与 DevOps27160 次安装1 天前更新
代码仓库

关于 infrahub-managing-generators

infrahub-managing-generators 面向创建 Infrahub Generator 的开发者,讲解如何用 GraphQL 查询设计数据并生成受跟踪的基础设施对象,并涵盖 Schema、注册和测试。

主要功能

  1. 01按设计生成对象
  2. 02GraphQL 查询指导
  3. 03Python Generator 实现
  4. 04幂等创建或更新模式
  5. 05Generator 注册与依赖跟踪
  6. 06使用 infrahubctl 验证

适用场景

  1. 01根据设计对象生成基础设施
  2. 02从模板创建对象和关系
  3. 03实现可重复运行的 Generator
  4. 04排查 Generator 的 Schema 或跟踪问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/opsmill/infrahub-skills --skill infrahub-managing-generators

安装后在 Claude Code 中输入/infrahub-managing-generators确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples.md
reference.md
rules/
_sections.md
_template.md
api-reference.md
architecture-components.md
patterns-common.md
patterns-hydration.md
patterns-natural-key-preflight.md
patterns-path-traversal.md
python-concurrent-relationship-writes.md
python-delete-ordering.md
python-generate.md
python-multi-peer-add.md
python-relationship-references.md
registration-config.md
registration-watch-dependencies.md
testing-commands.md
testing-integration.md
tracking-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-组件、组
CRITICALPython 类python-生成器、generate()
HIGH跟踪tracking-Upsert、幂等
HIGHAPI 参考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) 会重新发送内存管理器中的 IDrules/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。

生成器基础

每个生成器包含三个部分:

  1. 目标组 -- 触发生成器的对象
  2. GraphQL 查询(.gql 文件)-- 获取设计数据
  3. 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)

工作流

创建生成器时,请按以下步骤操作:

  1. 确定设计模式 — 哪个“设计”对象会触发生成?应从中创建哪些对象?阅读 rules/architecture-components.md 了解目标组和生成器组件。
  2. 编写 GraphQL 查询 — 创建一个 .gql 文件来获取设计数据。阅读 ../infrahub-common/graphql-queries.md 了解查询模式。如果仓库中有 schema.graphql,该文件是生成的 — 缺少字段时,应重新导出该文件,而不是编辑它。阅读 ../infrahub-common/rules/protocols-generated.md。
  3. 实现 Python 类 — 继承 InfrahubGenerator,实现 generate()。阅读 rules/python-generate.md 了解类模式,并阅读 rules/api-reference.md 了解可用方法。
  4. 确保操作幂等 — 使用 allow_upsert=True,使重复运行能够创建或更新内容,而不会产生重复项。参见 rules/tracking-idempotent.md。
  5. 检查是否有采用 from_graphql 的机会 — 如果 generate() 遍历响应边并调用 self.client.get() 重新获取类型化对等节点,请考虑重构为 InfrahubNode.from_graphql(),将 O(N + 1) 次往返请求减少到 O(1)。阅读 rules/patterns-hydration.md 了解决策树、检测启发式方法和重构步骤。
  6. 限制任何图遍历的范围。如果 generate() 需要两个节点之间的路径,请使用 SDK 的 traverse_paths,而不是手动逐跳遍历,并通过关系标识符和深度上限限制遍历范围。按类型筛选只会限制哪些节点可以出现,不会限制沿哪些边遍历,因此,共享的引用对象仍会连接无关子图,导致遍历返回结构上有效但实际无意义的结果。阅读 rules/patterns-path-traversal.md 了解参数语义和截断信号。
  7. 在 .infrahub.yml 中注册 — 在 generator_definitions 下添加条目,并指定目标组。参见 rules/registration-config.md。 然后使用 watch.files 声明生成器的依赖项:检查它的导入和运行时文件读取,并列出这些路径解析到的所有一方路径 — 包括同级查询模型。始终保留此键;如果生成器确实没有自身文件以外的依赖项,则使用 files: []。阅读 rules/registration-watch-dependencies.md,其中也介绍了如何检查现有 watch 块中是否缺少条目、条目是否过时或不正确。
  8. 测试 — 运行 infrahubctl generator 进行验证。参见 rules/testing-commands.md。

参考资料

评论

支持 Markdown