infrahub-managing-generators について
infrahub-managing-generators は、Infrahub Generator を作成する開発者向けのスキルです。GraphQL で設計データを取得して追跡可能なインフラオブジェクトを生成する方法を、スキーマ、登録、テストとともに説明します。
主な機能
- 01設計に基づくオブジェクト生成
- 02GraphQL クエリのガイダンス
- 03Python Generator の実装
- 04冪等な作成・更新パターン
- 05Generator の登録と依存関係の追跡
- 06infrahubctl による検証
活用シーン
- 01設計オブジェクトからインフラを生成
- 02テンプレートからオブジェクトと関係を作成
- 03Generator の反復実行を実装
- 04Generator のスキーマや追跡の問題を調査
インストール
コマンドをコピーしてターミナルで実行します。
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 Generator Creator
概要
Infrahub Generator を作成するための専門的なガイダンスです。Generator は GraphQL を介して Infrahub からデータをクエリし、その結果に基づいて新しいノードと リレーションシップを作成します -- これにより、「設計」オブジェクトが自動的に ダウンストリームのインフラストラクチャを作成する、設計駆動型の 自動化が可能になります。
プロジェクトコンテキスト
Infrahub 設定:
!cat .infrahub.yml 2>/dev/null || echo "No .infrahub.yml found"
既存の Generator:
!find . -name "*.py" -path "*/generators/*" 2>/dev/null | head -20
使用すべき場面
- 設計駆動型の自動化の構築 (トポロジー -> デバイス)
- テンプレートまたは設計定義からのオブジェクトの作成
- 冪等な create-or-update ワークフローの実装
- 高レベルの設計からのインフラストラクチャの自動生成
- Generator のトラッキングシステムの理解
ルールカテゴリ
| 優先度 | カテゴリ | プレフィックス | 説明 |
|---|---|---|---|
| CRITICAL | アーキテクチャ | architecture- | コンポーネント、グループ |
| CRITICAL | Python クラス | python- | Generator、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 |
| 出力を決めるために「design」ノードを読み取る | ジェネレーターの追跡キーが実行間で安定するよう、そのノードの human_friendly_id を定義していること | ../infrahub-managing-schemas/rules/display-human-friendly-id.md |
| グループへの所属によってトリガーされる | 種類を問わず、design オブジェクトがすでに所属しているグループを対象にすること。該当するグループが存在しない場合に限り、CoreStandardGroup を作成してください。CoreGeneratorGroup はジェネレーター自身の出力グループです | rules/registration-config.md |
| 再実行時に冪等である必要がある | すべての save() で allow_upsert=True を使用すること。実行時の追跡コンテキストによって、以前の実行で作成され、再作成されなかったオブジェクトが削除されます | rules/tracking-idempotent.md |
| リポジトリから何か(共有パッケージ、生成されたプロトコル、独自のクエリモデルなど)をインポートする | .infrahub.yml に、それらすべてのパスを指定した watch: ブロックを含めること。インポートは追跡されないため、ヘルパーの宣言がないと、そのヘルパーが変更された際にジェネレーターが再実行されなくなります | rules/registration-watch-dependencies.md |
| カーディナリティが many のリレーションシップに複数のピアを追加する | リストには .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 呼び出しで文字列の種類ではなく、生成されたプロトコルクラスを型として指定してください。たとえば kind="NetworkDevice" ではなく client.create(NetworkDevice, ...) とします。これにより、スキーマが変更された場合、返されたオブジェクトの属性読み取りに関する問題を型チェック時に検出できます。create() に渡すフィールド名は型チェックされません。詳しくは、protocols-adopt-typed-kinds を参照してください。
ジェネレーターの基本
すべてのジェネレーターには、次の 3 つの要素があります。
- 対象グループ -- ジェネレーターを起動するオブジェクト
- 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()が 2 つのノード間のルートを必要とする場合は、手書きのホップごとの 走査ではなく SDK のtraverse_pathsを使用し、リレーションシップ識別子と 深さの上限によって制約してください。種別フィルタリングはどのノードが 現れてよいかを制限するものであり、どのエッジをたどるかではありません。したがって、 共有された参照オブジェクトは無関係なサブグラフ同士を橋渡ししてしまい、 走査は構造的には妥当でも無意味な結果を返します。パラメーターの意味と 切り捨てのシグナルについては rules/patterns-path-traversal.md を参照してください。 - .infrahub.yml に登録する — 対象グループを指定して
generator_definitionsの下に追加します。 rules/registration-config.md を参照してください。 次に、watch.filesで Generator の依存関係を宣言します。そのインポートと 実行時のファイル読み取りを確認し、それらが解決されるすべてのファーストパーティのパスを 挙げてください。兄弟クエリモデルも含みます。常にこのキーを持たせてください。 Generator が自身のファイル以外に依存関係を本当に持たない場合はfiles: []とします。 rules/registration-watch-dependencies.md を参照してください。ここでは、既存のwatchブロックについて、欠落しているエントリ、 古くなったエントリ、誤ったエントリがないかを確認する方法も扱っています。 - テストする —
infrahubctl generatorを実行して検証します。 rules/testing-commands.md を参照してください。
関連リファレンス
- reference.md -- クラス API、
ライフサイクル、冪等性契約、
.infrahub.yml登録(check_definitions とは異なるquery:必須の 形式を含む) - examples.md -- 完全な Generator パターン(POP トポロジー、ネットワークセグメント、最小構成)
- ../infrahub-common/graphql-queries.md -- GraphQL クエリ作成リファレンス
- ../infrahub-common/infrahub-yml-reference.md -- .infrahub.yml プロジェクト設定
- ../infrahub-common/marketplace-reference.md -- 生成対象のデータモデル用にゼロから作る前に、 マーケットプレイスで公開されているスキーマを再利用する
- ../infrahub-common/rules/ -- 共通ルール (git 連携、キャッシュの注意点)
- ../infrahub-common/rules/workflow-information-priority.md
-- スキルコンテンツを最優先。真に不足がある場合
(例: ノードの削除)に
docs.infrahub.appを参照する方法 - ../infrahub-managing-schemas/SKILL.md -- Generator が扱うスキーマ定義
- rules/ -- カテゴリプレフィックスごとに整理された 個別ルール