mcpField
P
pulumi-python

pulumi-python

github.com/dirienクラウド・DevOps1389 回インストール今日更新
リポジトリ

pulumi-python について

Python で Pulumi のインフラプロジェクトを開発するためのスキルです。プロジェクトの作成、Pulumi ESC の設定、再利用可能なコンポーネント、デプロイ手順を扱います。

主な機能

  1. 01Python Pulumi プロジェクトの作成
  2. 02Pulumi ESC による設定とシークレット管理
  3. 03再利用可能なコンポーネントリソースの作成
  4. 04Stack 間での出力参照
  5. 05インフラのプレビューとデプロイ

活用シーン

  1. 01Python のインフラプロジェクトを開始
  2. 02ESC 環境の値を使ってデプロイを実行
  3. 03他の Pulumi 言語で使うコンポーネントを作成
  4. 04別の Stack の出力を参照

インストール

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

$npx skills add https://github.com/dirien/claude-skills --skill pulumi-python

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
pulumi-best-practices-aws.md
pulumi-best-practices-azure.md
pulumi-best-practices-gcp.md
pulumi-esc.md
pulumi-patterns.md
pulumi-python.md

詳細

Pulumi Python スキル

開発ワークフロー

1. プロジェクトのセットアップ
# Create new Python project
pulumi new python

# Or with a cloud-specific template
pulumi new aws-python
pulumi new azure-python
pulumi new gcp-python

プロジェクト構造:

my-project/
├── Pulumi.yaml
├── __main__.py
├── requirements.txt     # or pyproject.toml
└── venv/                # Virtual environment
2. Pulumi ESC の統合

スタック設定ファイルの代わりに 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}

ESC 環境を検証する:

# View resolved values (verify no errors)
pulumi env open myorg/myproject-dev

# Check for missing required values
pulumi env open myorg/myproject-dev --format json | jq .
3. Python のパターン

基本的なリソースの作成:

import pulumi
import pulumi_aws as aws

# Get configuration from ESC
config = pulumi.Config()
instance_type = config.require("instanceType")

# Create resources with proper tagging
bucket = aws.s3.Bucket(
    "my-bucket",
    versioning=aws.s3.BucketVersioningArgs(
        enabled=True,
    ),
    server_side_encryption_configuration=aws.s3.BucketServerSideEncryptionConfigurationArgs(
        rule=aws.s3.BucketServerSideEncryptionConfigurationRuleArgs(
            apply_server_side_encryption_by_default=aws.s3.BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultArgs(
                sse_algorithm="AES256",
            ),
        ),
    ),
    tags={
        "Environment": pulumi.get_stack(),
        "ManagedBy": "Pulumi",
    },
)

# Export outputs
pulumi.export("bucket_name", bucket.id)
pulumi.export("bucket_arn", bucket.arn)

辞書リテラルの使用(簡潔な代替方法):

import pulumi
import pulumi_aws as aws

bucket = aws.s3.Bucket(
    "my-bucket",
    versioning={"enabled": True},
    server_side_encryption_configuration={
        "rule": {
            "apply_server_side_encryption_by_default": {
                "sse_algorithm": "AES256",
            },
        },
    },
    tags={
        "Environment": pulumi.get_stack(),
        "ManagedBy": "Pulumi",
    },
)

再利用性を高めるコンポーネントリソース:

import pulumi
from pulumi_aws import lb


class WebServiceArgs:
    def __init__(self, port: pulumi.Input[int], image_uri: pulumi.Input[str]):
        self.port = port
        self.image_uri = image_uri


class WebService(pulumi.ComponentResource):
    url: pulumi.Output[str]

    def __init__(self, name: str, args: WebServiceArgs, opts: pulumi.ResourceOptions = None):
        super().__init__("custom:app:WebService", name, {}, opts)

        # Create child resources with parent=self
        load_balancer = lb.LoadBalancer(
            f"{name}-lb",
            load_balancer_type="application",
            # ... configuration
            opts=pulumi.ResourceOptions(parent=self),
        )

        self.url = load_balancer.dns_name

        self.register_outputs({
            "url": self.url,
        })

スタック間の依存関係に対するスタック参照:

import pulumi

# Reference outputs from networking stack
networking_stack = pulumi.StackReference("myorg/networking/prod")
vpc_id = networking_stack.get_output("vpc_id")
subnet_ids = networking_stack.get_output("private_subnet_ids")

Outputs の扱い:

import pulumi

# Apply transformation
uppercase_name = bucket.id.apply(lambda id: id.upper())

# Combine multiple outputs
combined = pulumi.Output.all(bucket.id, bucket.arn).apply(
    lambda args: f"Bucket {args[0]} has ARN {args[1]}"
)

# Using Output.concat for string interpolation
message = pulumi.Output.concat("Bucket ARN: ", bucket.arn)

# Conditional resources
is_prod = pulumi.get_stack() == "prod"
if is_prod:
    alarm = aws.cloudwatch.MetricAlarm(
        "alarm",
        # ... configuration
    )
4. pulumi env run で ESC を使用する

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 -- pytest

# Open environment and export to shell
pulumi env open myorg/myproject-dev --format shell
5. マルチ言語コンポーネント

Python でコンポーネントを作成すると、Pulumi のあらゆる言語(TypeScript、Go、C#、Java、YAML)から利用できます。

マルチ言語コンポーネントのプロジェクト構造:

my-component/
├── PulumiPlugin.yaml      # Required for multi-language
├── pyproject.toml         # or requirements.txt
└── __main__.py            # Component + entry point

PulumiPlugin.yaml:

runtime: python

適切な Args クラスを備えたコンポーネント(main.py):

from typing import Optional
import pulumi
from pulumi import Input, Output, ResourceOptions
from pulumi.provider.experimental import component_provider_host
import pulumi_aws as aws


class SecureBucketArgs:
    """Args class - use Input types for all properties."""

    def __init__(
        self,
        bucket_name: Input[str],
        enable_versioning: Optional[Input[bool]] = None,
        tags: Optional[Input[dict]] = None,
    ):
        self.bucket_name = bucket_name
        self.enable_versioning = enable_versioning or True
        self.tags = tags


class SecureBucket(pulumi.ComponentResource):
    """A secure S3 bucket with encryption and versioning."""

    bucket_id: Output[str]
    bucket_arn: Output[str]

    # Constructor must have 'args' parameter with type annotation
    def __init__(
        self,
        name: str,
        args: SecureBucketArgs,
        opts: Optional[ResourceOptions] = None,
    ):
        super().__init__("myorg:storage:SecureBucket", name, {}, opts)

        bucket = aws.s3.Bucket(
            f"{name}-bucket",
            bucket=args.bucket_name,
            versioning={"enabled": args.enable_versioning},
            server_side_encryption_configuration={
                "rule": {
                    "apply_server_side_encryption_by_default": {
                        "sse_algorithm": "AES256",
                    },
                },
            },
            tags=args.tags,
            opts=ResourceOptions(parent=self),
        )

        self.bucket_id = bucket.id
        self.bucket_arn = bucket.arn

        self.register_outputs({
            "bucket_id": self.bucket_id,
            "bucket_arn": self.bucket_arn,
        })


# Entry point for multi-language support
if __name__ == "__main__":
    component_provider_host(
        name="python-components",
        components=[SecureBucket],
    )

マルチ言語で利用できるように公開する:

# 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

マルチ言語 Args の要件:

  • すべてのプロパティに pulumi.Input[T] 型ヒントを使用します
  • Args クラスには、型付きパラメーターを持つ __init__ が必要です
  • コンストラクターには、型アノテーション付きの args パラメーターが必要です
  • オプションのプロパティには Optional[Input[T]] を使用します

重要: マルチ言語コンポーネントのエントリーポイントには、pulumi.provider.experimental の component_provider_host() を使用します。これは最新の API です。カスタム Provider サブクラスを使う以前の pulumi.provider.main() は、コンポーネント作成では非推奨です。

6. デプロイのワークフロー

エラーリカバリーを含む検証とデプロイ:

# Step 1: Preview changes
pulumi preview

# Step 2: Review output for errors or unexpected changes
# If errors appear, fix code and re-run preview

# Step 3: Deploy only after preview succeeds
pulumi up

# Step 4: Verify outputs
pulumi stack output

ESC ベースのデプロイの場合:

# Step 1: Validate ESC environment resolves correctly
pulumi env open myorg/myproject-dev

# Step 2: Preview with ESC environment
pulumi env run myorg/myproject-dev -- pulumi preview

# Step 3: Deploy with ESC environment
pulumi env run myorg/myproject-dev -- pulumi up

# Step 4: Check stack outputs
pulumi stack output

設定とセキュリティ

  • すべてのシークレットに Pulumi ESC を使用します。スタック設定ファイルや Pulumi.yaml にシークレットをコミットしないでください
  • 静的な認証情報の代わりに OIDC 認証を有効にします
  • 可能な場合は、TTL の短い動的シークレットを使用します
  • OIDC ロールには最小権限の IAM ポリシーを適用します
  • 再利用可能なインフラストラクチャパターンには ComponentResources を使用します
  • Python の型ヒントを活用して、IDE のサポートとエラー検出を向上させます

よく使うコマンド

# 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 python                      # New project
pulumi config env add <org>/<env>     # Link ESC environment
pulumi preview                         # Preview changes
pulumi up                              # Deploy
pulumi stack output                    # View outputs
pulumi destroy                         # Tear down

# Dependency Management
pip install -r requirements.txt        # Install deps (pip)
poetry add pulumi-aws                  # Add dep (poetry)
uv add pulumi-aws                      # Add dep (uv)

Python 固有の設定

pip を使用する場合(デフォルト):

# Pulumi.yaml
runtime:
  name: python
  options:
    toolchain: pip
    virtualenv: venv

poetry を使用する場合:

# Pulumi.yaml
runtime:
  name: python
  options:
    toolchain: poetry

uv を使用する場合:

# Pulumi.yaml
runtime:
  name: python
  options:
    toolchain: uv
    virtualenv: .venv

型チェックを有効にする:

# Pulumi.yaml
runtime:
  name: python
  options:
    typechecker: mypy  # or pyright

参考資料

コメント