pulumi-automation-api

作成者: pulumi

Pulumiインフラストラクチャ操作を複数のスタックやアプリケーションにわたってプログラム的にオーケストレーションします。ローカルソース(既存のPulumiプロジェクト)とインラインソース(埋め込みプログラム)の両方のアーキテクチャをサポートし、シンプルなものから複雑なマルチスタックシナリオまで柔軟なデプロイパターンを実現します。依存関係の順序付け、並行した独立デプロイ、スタック間の出力受け渡しによる調整されたインフラプロビジョニングを備えたマルチスタックオーケストレーションを処理します。プログラム的な...

npx skills add https://github.com/pulumi/agent-skills --skill pulumi-automation-api

Pulumi Automation API

When to Use This Skill

Invoke this skill when:

  • Orchestrating deployments across multiple Pulumi stacks
  • Embedding Pulumi operations in custom applications
  • Building self-service infrastructure platforms
  • Replacing fragile Bash/Makefile orchestration scripts
  • Creating custom CLIs for infrastructure management
  • Building web applications that provision infrastructure

What is Automation API

Automation API provides programmatic access to Pulumi operations. Instead of running pulumi up from the CLI, you call functions in your code that perform the same operations.

import * as automation from "@pulumi/pulumi/automation";

// Create or select a stack
const stack = await automation.LocalWorkspace.createOrSelectStack({
    stackName: "dev",
    projectName: "my-project",
    program: async () => {
        // Your Pulumi program here
    },
});

// Run pulumi up programmatically
const upResult = await stack.up({ onOutput: console.log });
console.log(`Update summary: ${JSON.stringify(upResult.summary)}`);

When to Use Automation API

Good Use Cases

Multi-stack orchestration:

When you split infrastructure into multiple focused projects, Automation API helps offset the added complexity by orchestrating operations across stacks:

infrastructure → platform → application
     ↓              ↓            ↓
   (VPC)      (Kubernetes)   (Services)

Automation API ensures correct sequencing without manual intervention.

Self-service platforms:

Build internal tools where developers request infrastructure without learning Pulumi:

  • Web portals for environment provisioning
  • Slack bots that create/destroy resources
  • Custom CLIs tailored to your organization

Embedded infrastructure:

Applications that provision their own infrastructure:

  • SaaS platforms creating per-tenant resources
  • Testing frameworks spinning up test environments
  • CI/CD systems with dynamic infrastructure needs

Replacing fragile scripts:

If you have Bash scripts or Makefiles stitching together multiple pulumi commands, Automation API provides:

  • Proper error handling
  • Type safety
  • Programmatic access to outputs

When NOT to Use

  • Single project with standard deployment needs
  • When you don't need programmatic control over operations

Architecture Choices

Local Source vs Inline Source

Local Source - Pulumi program in separate files:

const stack = await automation.LocalWorkspace.createOrSelectStack({
    stackName: "dev",
    workDir: "./infrastructure",  // Points to existing Pulumi project
});

When to use:

  • Different teams maintain orchestrator vs Pulumi programs
  • Pulumi programs already exist
  • Want independent version control and release cycles
  • Platform team orchestrating application team's infrastructure

Inline Source - Pulumi program embedded in orchestrator:

import * as aws from "@pulumi/aws";

const stack = await automation.LocalWorkspace.createOrSelectStack({
    stackName: "dev",
    projectName: "my-project",
    program: async () => {
        const bucket = new aws.s3.Bucket("my-bucket");
        return { bucketName: bucket.id };
    },
});

When to use:

  • Single team owns everything
  • Tight coupling between orchestration and infrastructure is desired
  • Distributing as compiled binary (no source files needed)
  • Simpler deployment artifact

Language Independence

The Automation API program can use a different language than the Pulumi programs it orchestrates:

Orchestrator (Go) → manages → Pulumi Program (TypeScript)

This enables platform teams to use their preferred language while application teams use theirs.

Common Patterns

Multi-Stack Orchestration

Deploy multiple stacks in dependency order:

import * as automation from "@pulumi/pulumi/automation";

async function deploy() {
    const stacks = [
        { name: "infrastructure", dir: "./infra" },
        { name: "platform", dir: "./platform" },
        { name: "application", dir: "./app" },
    ];

    for (const stackInfo of stacks) {
        console.log(`Deploying ${stackInfo.name}...`);

        const stack = await automation.LocalWorkspace.createOrSelectStack({
            stackName: "prod",
            workDir: stackInfo.dir,
        });

        await stack.up({ onOutput: console.log });
        console.log(`${stackInfo.name} deployed successfully`);
    }
}

async function destroy() {
    // Destroy in reverse order
    const stacks = [
        { name: "application", dir: "./app" },
        { name: "platform", dir: "./platform" },
        { name: "infrastructure", dir: "./infra" },
    ];

    for (const stackInfo of stacks) {
        console.log(`Destroying ${stackInfo.name}...`);

        const stack = await automation.LocalWorkspace.selectStack({
            stackName: "prod",
            workDir: stackInfo.dir,
        });

        await stack.destroy({ onOutput: console.log });
    }
}

Passing Configuration

Set stack configuration programmatically:

const stack = await automation.LocalWorkspace.createOrSelectStack({
    stackName: "dev",
    workDir: "./infrastructure",
});

// Set configuration values
await stack.setConfig("aws:region", { value: "us-west-2" });
await stack.setConfig("dbPassword", { value: "secret", secret: true });

// Then deploy
await stack.up();

Reading Outputs

Access stack outputs after deployment:

const upResult = await stack.up();

// Get all outputs
const outputs = await stack.outputs();
console.log(`VPC ID: ${outputs["vpcId"].value}`);

// Or from the up result
console.log(`Outputs: ${JSON.stringify(upResult.outputs)}`);

Error Handling

Handle deployment failures gracefully:

try {
    const result = await stack.up({ onOutput: console.log });

    if (result.summary.result === "failed") {
        console.error("Deployment failed");
        process.exit(1);
    }
} catch (error) {
    console.error(`Deployment error: ${error}`);
    throw error;
}

Parallel Stack Operations

When stacks are independent, deploy in parallel:

const independentStacks = [
    { name: "service-a", dir: "./service-a" },
    { name: "service-b", dir: "./service-b" },
    { name: "service-c", dir: "./service-c" },
];

await Promise.all(independentStacks.map(async (stackInfo) => {
    const stack = await automation.LocalWorkspace.createOrSelectStack({
        stackName: "prod",
        workDir: stackInfo.dir,
    });
    return stack.up({ onOutput: (msg) => console.log(`[${stackInfo.name}] ${msg}`) });
}));

Best Practices

Separate Configuration from Code

Externalize configuration into files or environment variables:

import * as fs from "fs";

interface DeployConfig {
    stacks: Array<{ name: string; dir: string; }>;
    environment: string;
}

const config: DeployConfig = JSON.parse(
    fs.readFileSync("./deploy-config.json", "utf-8")
);

for (const stackInfo of config.stacks) {
    const stack = await automation.LocalWorkspace.createOrSelectStack({
        stackName: config.environment,
        workDir: stackInfo.dir,
    });
    await stack.up();
}

This enables distributing compiled binaries without exposing source code.

Stream Output for Long Operations

Use onOutput callback for real-time feedback:

await stack.up({
    onOutput: (message) => {
        process.stdout.write(message);
        // Or send to logging system, websocket, etc.
    },
});

Quick Reference

ScenarioApproach
Existing Pulumi projectsLocal source with workDir
New embedded infrastructureInline source with program function
Different teamsLocal source for independence
Compiled binary distributionInline source or bundled local
Multi-stack dependenciesSequential deployment in order
Independent stacksParallel deployment with Promise.all

Related Skills

  • pulumi-best-practices: Code-level patterns for Pulumi programs

References

pulumiのその他のスキル

package-usage
pulumi
Pulumi組織全体のスタックにおいて、特定のパッケージがどのバージョンで使用されているかを追跡します。クロススタック監査や、古くなった、またはメンテナンスされていないものを特定するために使用します…
official
pulumi-best-practices
pulumi
信頼性が高く保守しやすいPulumiインフラストラクチャコードを記述するための包括的なベストプラクティス。apply()コールバック内でリソースを作成せず、依存関係の追跡とプレビューの可視性を維持するためにOutputオブジェクトを直接入力として渡します。ComponentResourceクラスを使用して関連リソースを再利用可能な論理ユニットにグループ化し、parent: thisを介して適切な親子階層を設定します。--secretフラグまたはconfig.requireSecret()を使用して最初からシークレットを暗号化し、状態ファイルへの認証情報漏洩を防ぎます...
official
pulumi-component
pulumi
再利用可能なインフラストラクチャコンポーネントで、多言語サポート、適切なデフォルト設定、および構成パターンを備えています。4つのコア要素が必要です:ComponentResourceを拡張し、標準パラメータを受け入れ、すべての子にparent: thisを設定し、コンストラクタの最後にregisterOutputs()を呼び出します。ArgsインターフェースはInput<T>ラッパーを使用し、ユニオン型や関数を避け、構造をフラットに保つことで多言語SDK生成をサポートします。必須の出力のみをパブリックプロパティとして公開し、非表示にします...
official
pulumi-debug-failed-operation
pulumi
失敗したPulumiの更新またはプレビューをデバッグします:Pulumiが既に記録した失敗を読み取り、原因を特定して修正します。ユーザーが依頼したときにこのスキルを読み込んでください。
official
pulumi-esc
pulumi
Pulumiインフラストラクチャとアプリケーション向けの、集中管理されたシークレット、設定、動的認証情報管理。インポートとレイヤリングによる環境構成をサポートし、environmentVariables、pulumiConfig、files用の予約キーを備えています。OIDCを介してAWS、Azure、GCP向けの短期認証情報を生成し、AWS Secrets Manager、Azure Key Vault、HashiCorp Vault、1Passwordと統合します。コアCLIコマンドには、pulumi env init、pulumi env edit、pulumi env open(表示...)が含まれます。
official
pulumi-neo-handoff
pulumi
現在のスレッドを新しいPulumi Neoタスクに一方向で引き継ぎます。ユーザーが明示的に引き継ぎ、送信、転送、または現在の続行を依頼した場合に使用します…
official
pulumi-overview
pulumi
このスキルは、クラウドインフラストラクチャやSaaS構成を作成、変更、検査、または破棄するあらゆるタスクに使用します。単発のCLI操作から完全な…
official
pulumi-terraform-to-pulumi
pulumi
Terraform/OpenTofuプロジェクトをPulumiに移行します。HCLソースコードの変換や、Terraformの状態をPulumiスタックにインポートする機能を含みます。ユーザーが…場合に使用します。
official