pulumi-go について
pulumi-goは、GoでPulumiのインフラプロジェクトを構築、デプロイするためのガイドスキルです。Pulumi ESCの設定、再利用可能なコンポーネント、変更検証、デプロイ手順を扱います。
主な機能
- 01Goプロジェクトの設定パターン
- 02Pulumi ESC環境の設定
- 03リソースとコンポーネントの例
- 04プレビューとデプロイの手順
- 05セキュリティとエラー処理の指針
活用シーン
- 01GoベースのPulumiプロジェクト作成
- 02ESCによるスタック設定と認証情報の管理
- 03複数言語で利用するコンポーネントの作成
- 04デプロイ前のインフラ変更の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dirien/ claude-skills --skill pulumi-goインストール後、Claude Code で/pulumi-goを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/pulumi-best-practices-aws.mdpulumi-best-practices-azure.mdpulumi-best-practices-gcp.mdpulumi-esc.mdpulumi-go.mdpulumi-patterns.md詳細
Pulumi Go スキル
開発ワークフロー
1. プロジェクトのセットアップ
# Create new Go project
pulumi new go
# Or with a cloud-specific template
pulumi new aws-go
pulumi new azure-go
pulumi new gcp-go
2. Pulumi ESC との連携
ESC 環境をスタックにリンクします:
# Create ESC environment
pulumi env init myorg/myproject-dev
# Edit environment
pulumi env edit myorg/myproject-dev
# Link to Pulumi stack
pulumi config env add myorg/myproject-dev
ESC 環境の定義(YAML):
values:
# Static configuration
pulumiConfig:
aws:region: us-west-2
myapp:instanceType: t3.medium
# Dynamic OIDC credentials for AWS
aws:
login:
fn::open::aws-login:
oidc:
roleArn: arn:aws:iam::123456789:role/pulumi-oidc
sessionName: pulumi-deploy
# Pull secrets from AWS Secrets Manager
secrets:
fn::open::aws-secrets:
region: us-west-2
login: ${aws.login}
get:
dbPassword:
secretId: prod/database/password
# Expose to environment variables
environmentVariables:
AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
AWS_SESSION_TOKEN: ${aws.login.sessionToken}
3. Go のパターン
基本的なリソースの作成:
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Get configuration from ESC
cfg := config.New(ctx, "")
instanceType := cfg.Require("instanceType")
// Create resources with proper tagging
bucket, err := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{
Versioning: &s3.BucketVersioningArgs{
Enabled: pulumi.Bool(true),
},
ServerSideEncryptionConfiguration: &s3.BucketServerSideEncryptionConfigurationArgs{
Rule: &s3.BucketServerSideEncryptionConfigurationRuleArgs{
ApplyServerSideEncryptionByDefault: &s3.BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultArgs{
SseAlgorithm: pulumi.String("AES256"),
},
},
},
Tags: pulumi.StringMap{
"Environment": pulumi.String(ctx.Stack()),
"ManagedBy": pulumi.String("Pulumi"),
},
})
if err != nil {
return err
}
// Export outputs
ctx.Export("bucketName", bucket.ID())
ctx.Export("bucketArn", bucket.Arn)
return nil
})
}
コンポーネントリソース:
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
type WebServiceArgs struct {
Port pulumi.IntInput
ImageUri pulumi.StringInput
}
type WebService struct {
pulumi.ResourceState
URL pulumi.StringOutput `pulumi:"url"`
}
func NewWebService(ctx *pulumi.Context, name string, args *WebServiceArgs, opts ...pulumi.ResourceOption) (*WebService, error) {
component := &WebService{}
err := ctx.RegisterComponentResource("custom:app:WebService", name, component, opts...)
if err != nil {
return nil, err
}
// Create child resources with pulumi.Parent(component)
loadBalancer, err := lb.NewLoadBalancer(ctx, name+"-lb", &lb.LoadBalancerArgs{
LoadBalancerType: pulumi.String("application"),
// ... configuration
}, pulumi.Parent(component))
if err != nil {
return nil, err
}
component.URL = loadBalancer.DnsName
ctx.RegisterResourceOutputs(component, pulumi.Map{
"url": component.URL,
})
return component, nil
}
スタック間の依存関係に対するスタック参照:
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Reference outputs from networking stack
networkingStack, err := pulumi.NewStackReference(ctx, "myorg/networking/prod", nil)
if err != nil {
return err
}
vpcId := networkingStack.GetStringOutput(pulumi.String("vpcId"))
subnetIds := networkingStack.GetOutput(pulumi.String("privateSubnetIds"))
ctx.Export("vpcId", vpcId)
return nil
})
}
Output の操作:
package main
import (
"fmt"
"strings"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Apply transformation
uppercaseName := bucket.ID().ApplyT(func(id string) string {
return strings.ToUpper(id)
}).(pulumi.StringOutput)
// Combine multiple outputs
combined := pulumi.All(bucket.ID(), bucket.Arn).ApplyT(
func(args []interface{}) string {
id := args[0].(string)
arn := args[1].(string)
return fmt.Sprintf("Bucket %s has ARN %s", id, arn)
},
).(pulumi.StringOutput)
// Conditional resources
if ctx.Stack() == "prod" {
_, err := cloudwatch.NewMetricAlarm(ctx, "alarm", &cloudwatch.MetricAlarmArgs{
// ... configuration
})
if err != nil {
return err
}
}
return nil
})
}
4. pulumi env run で ESC を使用する
# Run pulumi commands with ESC credentials
pulumi env run myorg/aws-dev -- pulumi up
# Run tests with secrets
pulumi env run myorg/test-env -- go test ./...
# Open environment and export to shell
pulumi env open myorg/myproject-dev --format shell
5. 検証を含むデプロイワークフロー
ビルドとプレビュー:
# Build Go binary first
go build -o $(basename $(pwd))
# Preview changes
pulumi preview
検証チェックポイント: プレビュー出力を確認します。予期しない変更がある場合:
- ESC 環境の値を確認します:
pulumi env open myorg/myproject-dev - スタック設定を確認します:
pulumi config - 続行する前に、リソースの差分を慎重に確認します
デプロイ:
# Deploy after validation
pulumi up
# Verify outputs
pulumi stack output
エラーからの復旧: デプロイに失敗した場合:
- リソース固有の問題についてエラーログを確認します
- 認証情報と権限を確認します:
pulumi env open myorg/myproject-dev --format shell - 必要に応じてロールバックを試みます:
pulumi refresh(変更を加えずに状態を更新します) - 問題を修正して再試行します:
pulumi up
破壊的な変更(削除)の場合、Pulumi は pulumi up の実行中に確認を求めます。
6. エラー処理
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
bucket, err := s3.NewBucket(ctx, "bucket", &s3.BucketArgs{})
if err != nil {
return fmt.Errorf("failed to create bucket: %w", err)
}
policy, err := s3.NewBucketPolicy(ctx, "policy", &s3.BucketPolicyArgs{
Bucket: bucket.ID(),
Policy: bucket.Arn.ApplyT(func(arn string) string {
return fmt.Sprintf(`{"Version":"2012-10-17",...}`, arn)
}).(pulumi.StringOutput),
})
if err != nil {
return fmt.Errorf("failed to create bucket policy: %w", err)
}
return nil
})
}
7. マルチ言語コンポーネント
あらゆる Pulumi 言語から利用できる、再利用可能なコンポーネントを Go で作成します。
プロジェクト構成:
my-component/
├── PulumiPlugin.yaml
├── go.mod
├── go.sum
└── main.go
PulumiPlugin.yaml:
runtime: go
コンポーネントの実装:
package main
import (
"context"
"log"
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
"github.com/pulumi/pulumi-go-provider/infer"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
// Use Input types for all properties
type SecureBucketArgs struct {
BucketName pulumi.StringInput `pulumi:"bucketName"`
EnableVersioning pulumi.BoolInput `pulumi:"enableVersioning,optional"`
Tags pulumi.StringMapInput `pulumi:"tags,optional"`
}
type SecureBucket struct {
pulumi.ResourceState
BucketId pulumi.StringOutput `pulumi:"bucketId"`
BucketArn pulumi.StringOutput `pulumi:"bucketArn"`
}
func NewSecureBucket(ctx *pulumi.Context, name string, args *SecureBucketArgs, opts ...pulumi.ResourceOption) (*SecureBucket, error) {
component := &SecureBucket{}
err := ctx.RegisterComponentResource("myorg:storage:SecureBucket", name, component, opts...)
if err != nil {
return nil, err
}
bucket, err := s3.NewBucket(ctx, name+"-bucket", &s3.BucketArgs{
Bucket: args.BucketName,
Versioning: &s3.BucketVersioningArgs{
Enabled: args.EnableVersioning,
},
ServerSideEncryptionConfiguration: &s3.BucketServerSideEncryptionConfigurationArgs{
Rule: &s3.BucketServerSideEncryptionConfigurationRuleArgs{
ApplyServerSideEncryptionByDefault: &s3.BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultArgs{
SseAlgorithm: pulumi.String("AES256"),
},
},
},
Tags: args.Tags,
}, pulumi.Parent(component))
if err != nil {
return nil, err
}
component.BucketId = bucket.ID().ToStringOutput()
component.BucketArn = bucket.Arn
ctx.RegisterResourceOutputs(component, pulumi.Map{
"bucketId": component.BucketId,
"bucketArn": component.BucketArn,
})
return component, nil
}
func main() {
prov, err := infer.NewProviderBuilder().
WithNamespace("myorg").
WithComponents(
infer.ComponentF(NewSecureBucket),
).
Build()
if err != nil {
log.Fatal(err.Error())
}
_ = prov.Run(context.Background(), "go-components", "v0.0.1")
}
公開:
# Consume from git repository
pulumi package add github.com/myorg/my-component
# With version tag
pulumi package add github.com/myorg/[email protected]
# Local development
pulumi package add /path/to/local/my-component
ベストプラクティス
セキュリティ
- すべてのシークレットに Pulumi ESC を使用し、スタック設定ファイルにシークレットを絶対にコミットしないでください
- 静的な認証情報ではなく、OIDC 認証を有効にしてください
- 可能な場合は、有効期間の短い動的シークレットを使用してください
- 最小権限の IAM ポリシーを適用してください
コードの整理
- 再利用可能なインフラストラクチャパターンには、コンポーネントリソースを使用してください
- Go の型システムを活用して設定を検証してください
- スタック固有の設定は ESC 環境に保持してください
- スタック間の依存関係にはスタック参照を使用してください
デプロイ
pulumi upの前に必ずpulumi previewを実行し、変更内容を慎重に確認してください- リリースには ESC 環境のバージョン管理とタグを使用してください
- すべてのリソースに適切なタグ付け戦略を導入してください
- Pulumi を実行する前に Go プログラムをビルドしてください:
go build -o $(basename $(pwd))
よく使うコマンド
# Environment Commands (pulumi env)
pulumi env init <org>/<project>/<env> # Create environment
pulumi env edit <org>/<env> # Edit environment
pulumi env open <org>/<env> # View resolved values
pulumi env run <org>/<env> -- <command> # Run with env vars
pulumi env version tag <org>/<env> <tag> # Tag version
# Pulumi Commands
pulumi new go # New project
pulumi config env add <org>/<env> # Link ESC environment
go build -o $(basename $(pwd)) # Build Go binary
pulumi preview # Preview changes
pulumi up # Deploy
pulumi stack output # View outputs
pulumi destroy # Tear down
参考資料
- references/pulumi-esc.md - ESC のパターンとコマンド
- references/pulumi-patterns.md - よく使われるインフラストラクチャパターン
- references/pulumi-go.md - Go 固有のガイダンス
- references/pulumi-best-practices-aws.md - AWS のベストプラクティス
- references/pulumi-best-practices-azure.md - Azure のベストプラクティス
- references/pulumi-best-practices-gcp.md - GCP のベストプラクティス
コメント
Markdown 対応