generate-terraform-provider について
Speakeasy CLI で OpenAPI 仕様から Terraform Provider を生成する開発者向けスキルです。エンティティの注釈、CRUD の割り当て、生成設定、テスト、Terraform Registry への公開までを扱います。
主な機能
- 01OpenAPI から Go Provider を生成
- 02エンティティと操作に注釈を付与
- 03API 操作を CRUD に対応付け
- 04生成ワークフローの設定と再実行
- 05テストと Registry 公開を案内
活用シーン
- 01既存 API 用の Terraform Provider を作成
- 02OpenAPI 操作を Terraform リソースに割り当て
- 03仕様変更後に Provider を再生成
- 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/ ディレクトリ |
前提条件
- Speakeasy CLI がインストールされ、認証済みであること
- エンティティアノテーションを含む OpenAPI 3.0 または 3.1 の仕様
- Go がインストールされていること(Terraform プロバイダーは Go で記述されています)
- 認証:
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 | /resource | Entity#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 リソース |
|---|---|
Pet | petstore_pet |
GatewayControlPlane | konnect_gateway_control_plane |
MeshControlPlane | konnect_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 への公開
前提条件
- 公開リポジトリ:
terraform-provider-{name}という名前(小文字) - GPG 署名キー:リリースへの署名用
- GoReleaser の設定
- 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 に登録する
- registry.terraform.io にアクセスします
- GitHub でサインインします(組織の管理者権限が必要です)
- 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- 生成エラーのトラブルシューティング