mcpField
G
generate-terraform-provider

generate-terraform-provider

github.com/speakeasy-apiクラウド・DevOps1878 回インストール37 週間前に更新
リポジトリ

generate-terraform-provider について

Speakeasy CLI で OpenAPI 仕様から Terraform Provider を生成する開発者向けスキルです。エンティティの注釈、CRUD の割り当て、生成設定、テスト、Terraform Registry への公開までを扱います。

主な機能

  1. 01OpenAPI から Go Provider を生成
  2. 02エンティティと操作に注釈を付与
  3. 03API 操作を CRUD に対応付け
  4. 04生成ワークフローの設定と再実行
  5. 05テストと Registry 公開を案内

活用シーン

  1. 01既存 API 用の Terraform Provider を作成
  2. 02OpenAPI 操作を Terraform リソースに割り当て
  3. 03仕様変更後に Provider を再生成
  4. 04Provider のテストと Registry 公開を準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/speakeasy-api/sdk-generation-skills --skill generate-terraform-provider

インストール後、Claude Code で/generate-terraform-providerを入力して読み込まれたか確認します。

同梱ファイルcontent/customization.md

詳細

generate-terraform-provider

Speakeasy CLI を使用して、OpenAPI 仕様から Terraform プロバイダーを生成します。このスキルでは、エンティティメタデータを仕様に付与する、CRUD 操作をマッピングする、プロバイダーを生成する、ワークフローを設定する、Terraform Registry に公開するといったライフサイクル全体を扱います。

コンテンツガイド

トピックガイド
高度なカスタマイズcontent/customization.md

カスタマイズガイドでは、エンティティマッピングの配置、複数操作のリソース、非同期ポーリング、プロパティのカスタマイズ、プランの変更、バリデーション、状態アップグレーダーについて説明します。

使用するタイミング

  • OpenAPI 仕様から新しい Terraform プロバイダーを生成する場合
  • OpenAPI 仕様に x-speakeasy-entity と x-speakeasy-entity-operation を付与する場合
  • API 操作を Terraform の CRUD メソッドにマッピングする場合
  • OpenAPI スキーマから Terraform の型を推論する方法を理解する場合
  • Terraform プロバイダー生成用に workflow.yaml を設定する場合
  • Terraform Registry にプロバイダーを公開する場合
  • ユーザーが「terraform provider」「generate terraform」「create terraform provider」「CRUD mapping」「x-speakeasy-entity」「terraform resource」「terraform registry」と言った場合

入力

入力必須説明
OpenAPI 仕様はいOpenAPI 3.0 または 3.1 の仕様(ローカルファイル、URL、またはレジストリソース)
プロバイダー名はいプロバイダーの PascalCase 名(例:Petstore)
パッケージ名はい小文字のパッケージ識別子(例:petstore)
エンティティアノテーションはいスキーマ上の x-speakeasy-entity、操作上の x-speakeasy-entity-operation

出力

出力場所
ワークフロー設定.speakeasy/workflow.yaml
生成設定gen.yaml
生成された Go プロバイダー出力ディレクトリ(デフォルト:現在のディレクトリ)
Terraform の例examples/ ディレクトリ

前提条件

  1. Speakeasy CLI がインストールされ、認証済みであること
  2. エンティティアノテーションを含む OpenAPI 3.0 または 3.1 の仕様
  3. Go がインストールされていること(Terraform プロバイダーは Go で記述されています)
  4. 認証:SPEAKEASY_API_KEY 環境変数を設定するか、speakeasy auth login を実行してください
export SPEAKEASY_API_KEY="<your-api-key>"

対話形式で認証するには speakeasy auth login を実行するか、SPEAKEASY_API_KEY 環境変数を設定してください。

コマンド

初回生成(クイックスタート)
speakeasy quickstart --skip-interactive --output console \
  -s <spec-path> \
  -t terraform \
  -n <ProviderName> \
  -p <package-name>
変更後の再生成
speakeasy run --output console
特定のターゲットを再生成
speakeasy run -t <target-name> --output console

エンティティアノテーション

生成する前に、OpenAPI 仕様に2つの拡張を付与してください。

1. スキーマをエンティティとしてマークする

Terraform リソースにするコンポーネントスキーマに x-speakeasy-entity を追加します。

components:
  schemas:
    Pet:
      x-speakeasy-entity: Pet
      type: object
      properties:
        id:
          type: string
          readOnly: true
        name:
          type: string
        price:
          type: number
      required:
        - name
        - price
2. 操作を CRUD メソッドにマッピングする

各 API 操作に x-speakeasy-entity-operation を追加します。

paths:
  /pets:
    post:
      x-speakeasy-entity-operation: Pet#create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Pet"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
  /pets/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
    get:
      x-speakeasy-entity-operation: Pet#read
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
    put:
      x-speakeasy-entity-operation: Pet#update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Pet"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
    delete:
      x-speakeasy-entity-operation: Pet#delete
      responses:
        "204":
          description: Deleted
CRUD マッピングの概要
HTTP メソッドパスアノテーション目的
POST/resourceEntity#create新しいリソースを作成します
GET/resource/{id}Entity#read単一のリソースを読み取ります
PUT/resource/{id}Entity#updateリソースを更新します
DELETE/resource/{id}Entity#deleteリソースを削除します

データソース(一覧): 一覧取得エンドポイント(GET /resources)には、#read を使って別の複数形のエンティティ名を指定します(例:Pets#read)。#list は有効な操作タイプではないため、使用しないでください。

Terraform の型推論

Speakeasy は、OpenAPI 仕様から Terraform のスキーマ型を自動的に推論します。

ルール条件Terraform 属性
必須CREATE リクエストボディでプロパティが required に指定されているRequired: true
任意CREATE リクエストボディでプロパティが required に指定されていないOptional: true
計算済みプロパティがレスポンスに含まれているが、CREATE リクエストには含まれていないComputed: true
ForceNewプロパティが CREATE リクエストにはあるが、UPDATE リクエストにはないForceNew(リソースの再作成を強制します)
列挙値の検証プロパティが enum として定義されている実行時チェック用の Validator が追加されます

READ、UPDATE、DELETE に必要な各パラメーターは、CREATE レスポンスに含まれているか、CREATE リクエストで必須になっている必要があります。

例

Petstore プロバイダーの完全なワークフロー
# 1. Ensure your spec has entity annotations (see above)

# 2. Generate the provider
speakeasy quickstart --skip-interactive --output console \
  -s ./openapi.yaml \
  -t terraform \
  -n Petstore \
  -p petstore

# 3. Build and test
cd terraform-provider-petstore
go build ./...
go test ./...

# 4. After spec changes, regenerate
speakeasy run --output console

これにより、次のように使用できる Terraform リソースが生成されます。

resource "petstore_pet" "my_pet" {
  name  = "Buddy"
  price = 1500
}

ワークフローの設定

ローカルの仕様
# .speakeasy/workflow.yaml
workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
  my-api:
    inputs:
      - location: ./openapi.yaml
targets:
  my-provider:
    target: terraform
    source: my-api
オーバーレイを使用したリモート仕様

サードパーティ API 用にプロバイダーをビルドする場合は、仕様をリモートから取得し、ローカルのオーバーレイを適用します。

# .speakeasy/workflow.yaml
workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
  vendor-api:
    inputs:
      - location: https://api.vendor.com/openapi.yaml
    overlays:
      - location: terraform_overlay.yaml
    output: openapi.yaml
targets:
  vendor-provider:
    target: terraform
    source: vendor-api

speakeasy overlay compare を使用して、上流 API の変更を追跡します。

speakeasy overlay compare \
  --before https://api.vendor.com/openapi.yaml \
  --after terraform_overlay.yaml \
  --out overlay-diff.yaml

リポジトリと命名規則

リポジトリの命名

リポジトリには terraform-provider-XXX という名前を付けます。XXX はプロバイダーの型名です。プロバイダーの型名は小文字の英数字([a-z][a-z0-9])にします。ただし、ハイフンとアンダースコアも使用できます。

エンティティの命名

エンティティ名には PascalCase を使用し、Terraform のアンダースコア形式の命名に正しく変換されるようにします。

エンティティ名Terraform リソース
Petpetstore_pet
GatewayControlPlanekonnect_gateway_control_plane
MeshControlPlanekonnect_mesh_control_plane

リストデータソースには、複数形の PascalCase 形式(例:Pets)を使用します。

リソースのインポート

生成されたプロバイダーは、既存のリソースを Terraform の状態にインポートできます。

単純なキー

ID フィールドが 1 つのリソースの場合:

terraform import petstore_pet.my_pet my_pet_id
複合キー

ID フィールドが複数あるリソースの場合は、JSON エンコードしたオブジェクトを渡します。

terraform import my_test_resource.my_example \
  '{ "primary_key_one": "9cedad30-...", "primary_key_two": "e20c40a0-..." }'

または、インポートブロックを使用します。

import {
  id = jsonencode({
    primary_key_one: "9cedad30-..."
    primary_key_two: "e20c40a0-..."
  })
  to = my_test_resource.my_example
}

次に、構成を生成します。

terraform plan -generate-config-out=generated.tf

Terraform Registry への公開

前提条件
  1. 公開リポジトリ:terraform-provider-{name} という名前(小文字)
  2. GPG 署名キー:リリースへの署名用
  3. GoReleaser の設定
  4. registry.terraform.io での登録
手順 1:GPG キーを生成する
gpg --full-generate-key  # Choose RSA, 4096 bits
gpg --armor --export-secret-keys YOUR_KEY_ID > private.key
gpg --armor --export YOUR_KEY_ID > public.key
手順 2:リポジトリのシークレットを設定する

GitHub リポジトリのシークレットに追加します。

  • terraform_gpg_secret_key - 秘密鍵の内容
  • terraform_gpg_passphrase - 鍵のパスフレーズ
手順 3:リリースワークフローを追加する
# .github/workflows/release.yaml
name: Release
on:
  push:
    tags: ['v*']
permissions:
  contents: write

jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-go@v4
        with:
          go-version-file: 'go.mod'
      - uses: crazy-max/ghaction-import-gpg@v5
        id: import_gpg
        with:
          gpg_private_key: ${{ secrets.terraform_gpg_secret_key }}
          passphrase: ${{ secrets.terraform_gpg_passphrase }}
      - uses: goreleaser/goreleaser-action@v6
        with:
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
手順 4:Terraform Registry に登録する
  1. registry.terraform.io にアクセスします
  2. GitHub でサインインします(組織の管理者権限が必要です)
  3. Publish → Provider → リポジトリを選択します

登録後は、タグをプッシュするとリリースが自動的に公開されます。

ベータプロバイダーのパターン

大規模な API では、安定版とベータ版のプロバイダーを分けて管理します。

  • 安定版:semver(x.y.z)を使用する terraform-provider-{name}
  • ベータ版:0.x バージョニングを使用する terraform-provider-{name}-beta

ユーザーは両方を同時にインストールできます。ベータ機能が成熟したら、安定版プロバイダーに移行します。ベータプロバイダーを設定するには、0.x バージョニングを使用する独自の gen.yaml を含む terraform-provider-{name}-beta リポジトリを別途作成し、安定版プロバイダーと並行して公開します。

プロバイダーのテスト

テスト依存関係を追加する

.speakeasy/gen.yaml で設定します。

terraform:
  additionalDependencies:
    github.com/hashicorp/terraform-plugin-testing: v1.13.3
受け入れテストの構成
// internal/provider/resource_test.go
func TestAccPet_Lifecycle(t *testing.T) {
    t.Parallel()

    resource.Test(t, resource.TestCase{
        PreCheck:                 func() { testAccPreCheck(t) },
        ProtoV6ProviderFactories: testAccProviders(),
        Steps: []resource.TestStep{
            {
                Config: testAccPetConfig("Buddy", 1500),
                Check: resource.ComposeTestCheckFunc(
                    resource.TestCheckResourceAttr("petstore_pet.test", "name", "Buddy"),
                ),
            },
            {
                ResourceName:      "petstore_pet.test",
                ImportState:       true,
                ImportStateVerify: true,
            },
        },
    })
}
テストの実行
# Unit tests
go test -v ./...

# Acceptance tests (REQUIRES TF_ACC=1)
TF_ACC=1 go test -v ./internal/provider/... -timeout 30m

注: TF_ACC=1 を指定しない場合、テストは PASS ステータスで何も表示せずにスキップされます。

してはいけないこと

  • #listを操作タイプとして使用しないでください。有効なのはcreate、read、update、deleteのみです
  • 生成されたGoコードを直接変更しないでください。再生成時に変更が上書きされます。代わりにオーバーレイまたはフックを使用してください
  • CREATEのレスポンスボディを省略しないでください。Terraformが計算フィールド(例:id)を設定するには、レスポンスが必要です
  • スキーマにx-speakeasy-entityを設定してください。設定しないと、SpeakeasyはTerraformリソースを識別できません
  • エンティティ名にcamelCaseやsnake_caseを使用しないでください。Terraformでアンダースコアを使った命名が機能するよう、PascalCaseを使用してください
  • モノレポモードでTerraformプロバイダーを生成しないでください。HashiCorpは専用リポジトリを必要とします

トラブルシューティング

問題原因解決策
invalid entity operation type: list#readではなく#listを使用していますEntity#readに変更してください。リストエンドポイントでは複数形のエンティティ名を使用します
インポート後にリソースのフィールドが不足しているREAD操作がすべての属性を返していませんGETエンドポイントがリソーススキーマ全体を返すことを確認してください
想定外のフィールドがForceNewになるCREATEには存在するフィールドが、UPDATEリクエストにはありませんそのフィールドを変更可能にする場合は、UPDATEリクエストボディに追加してください
プロバイダーのコンパイルに失敗するGoの依存関係が不足していますプロバイダーディレクトリでgo mod tidyを実行してください
計算フィールドが設定されないCREATEのレスポンスにフィールドがありませんCREATEのレスポンスが、計算フィールドを含むリソース全体を返すことを確認してください
エンティティがリソースとして表示されないx-speakeasy-entityアノテーションがありませんコンポーネントスキーマにx-speakeasy-entity: EntityNameを追加してください
認証が機能しないAPIキーが設定されていませんSPEAKEASY_API_KEY環境変数を設定するか、speakeasy auth loginを実行してください

関連するスキル

  • start-new-sdk-project - プロジェクトの初期設定
  • manage-openapi-overlays - オーバーレイを使ったエンティティアノテーションの追加
  • diagnose-generation-failure - 生成エラーのトラブルシューティング

コメント