关于 pulumi-automation-api
pulumi-automation-api 是一项通过代码调用 Pulumi Automation API 管理基础设施操作的技能,适用于构建部署编排、自助平台或基础设施应用。它涵盖多 Stack 协调、配置传递和输出读取等模式。
主要功能
- 01以编程方式执行 Pulumi 操作
- 02多 Stack 顺序编排与并行执行
- 03支持本地或内嵌程序源
- 04编程设置配置并读取输出
- 05处理部署错误
适用场景
- 01编排存在依赖关系的基础设施 Stack
- 02构建自助式资源配置工具
- 03在应用中嵌入基础设施配置
- 04替换 Bash 或 Makefile 部署脚本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pulumi/ agent-skills --skill pulumi-automation-api安装后在 Claude Code 中输入/pulumi-automation-api确认已加载。
附带文件agents/openai.yamluse_cases.yaml
详细介绍
Pulumi Automation API
何时使用此技能
在以下情况下调用此技能:
- 协调多个 Pulumi 堆栈之间的部署
- 在自定义应用程序中嵌入 Pulumi 操作
- 构建自助式基础设施平台
- 替换脆弱的 Bash/Makefile 编排脚本
- 创建用于基础设施管理的自定义 CLI
- 构建可预配基础设施的 Web 应用程序
什么是 Automation API
Automation API 提供对 Pulumi 操作的编程访问。你无需从 CLI 运行 pulumi up,而是可以在代码中调用执行相同操作的函数。
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)}`);
何时使用 Automation API
适用场景
多堆栈编排:
当你将基础设施拆分为多个专注于特定领域的项目时,Automation API 可通过协调各个堆栈之间的操作,帮助抵消由此增加的复杂性:
infrastructure → platform → application
↓ ↓ ↓
(VPC) (Kubernetes) (Services)
Automation API 可确保操作按正确顺序执行,无需人工干预。
自助式平台:
构建内部工具,让开发人员无需学习 Pulumi 即可申请基础设施:
- 用于预配环境的 Web 门户
- 可创建/销毁资源的 Slack 机器人
- 根据组织需求定制的 CLI
嵌入式基础设施:
可为自身预配基础设施的应用程序:
- 为每个租户创建资源的 SaaS 平台
- 启动测试环境的测试框架
- 需要动态基础设施的 CI/CD 系统
替换脆弱的脚本:
如果你使用 Bash 脚本或 Makefile 串联多个 pulumi 命令,Automation API 可以提供:
- 正确的错误处理
- 类型安全
- 对输出的编程访问
不适用的情况
- 单个项目且部署需求标准
- 不需要以编程方式控制操作
架构选择
本地源代码与内嵌源代码
本地源代码 - Pulumi 程序位于独立文件中:
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "dev",
workDir: "./infrastructure", // Points to existing Pulumi project
});
适用场景:
- 编排器和 Pulumi 程序由不同团队维护
- 已有 Pulumi 程序
- 希望采用独立的版本控制和发布周期
- 平台团队负责编排应用团队的基础设施
内嵌源代码 - Pulumi 程序嵌入在编排器中:
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 };
},
});
适用场景:
- 由单个团队负责所有工作
- 希望编排与基础设施紧密耦合
- 以编译后的二进制文件形式分发(无需源文件)
- 部署产物更简单
语言独立性
Automation API 程序可以使用与其所编排的 Pulumi 程序不同的语言:
Orchestrator (Go) → manages → Pulumi Program (TypeScript)
这使平台团队能够使用偏好的语言,同时应用团队也可以使用自己的语言。
常见模式
多堆栈编排
按依赖顺序部署多个堆栈:
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 });
}
}
传递配置
以编程方式设置堆栈配置:
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();
读取输出
部署后访问堆栈输出:
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)}`);
错误处理
妥善处理部署失败:
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;
}
并行堆栈操作
如果堆栈相互独立,可并行部署:
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}`) });
}));
最佳实践
将配置与代码分离
将配置外置到文件或环境变量中:
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();
}
这样即可分发编译后的二进制文件,而不会暴露源代码。
为长时间运行的操作流式输出
使用 onOutput 回调实时获取反馈:
await stack.up({
onOutput: (message) => {
process.stdout.write(message);
// Or send to logging system, websocket, etc.
},
});
快速参考
| 场景 | 方案 |
|---|---|
| 已有 Pulumi 项目 | 使用 workDir 的本地源代码 |
| 新的嵌入式基础设施 | 使用 program 函数的内嵌源代码 |
| 不同团队 | 使用本地源代码以保持独立性 |
| 编译后的二进制文件分发 | 使用内嵌源代码或打包的本地源代码 |
| 多堆栈依赖 | 按顺序依次部署 |
| 相互独立的堆栈 | 使用 Promise.all 并行部署 |
相关技能
- pulumi-best-practices:Pulumi 程序的代码级模式