用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/agents-inc/skills --skill infra-iac-pulumi命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | infra-iac-pulumi |
| description | TypeScript-native Infrastructure as Code with Pulumi |
Quick Guide: Define cloud infrastructure in TypeScript with full type safety. Use
ComponentResourceto encapsulate reusable infrastructure patterns. Pass{ parent: this }to all child resources inside components. Usepulumi.interpolatefor string building with Outputs (not string concatenation). Never create resources inside.apply(). UseConfig.requireSecret()for sensitive values. Prefertransformsover deprecatedtransformations. Always callthis.registerOutputs()at the end of component constructors.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST pass { parent: this } to ALL child resources inside a ComponentResource -- omitting it breaks the resource tree and state tracking)
(You MUST use pulumi.interpolate for string building with Outputs -- string concatenation silently produces [object Object])
(You MUST NEVER create resources inside .apply() -- they will not appear in pulumi preview and cause ordering issues)
(You MUST use Config.requireSecret() for sensitive values -- Config.require() stores values as plaintext in state)
(You MUST call this.registerOutputs() at the end of every ComponentResource constructor -- omitting it prevents output tracking)
</critical_requirements>
Detailed Resources:
Auto-detection: Pulumi, @pulumi/pulumi, @pulumi/aws, @pulumi/gcp, @pulumi/azure, @pulumi/kubernetes, pulumi.ComponentResource, pulumi.CustomResource, pulumi.Output, pulumi.Config, pulumi.interpolate, pulumi.all, registerOutputs, StackReference, ComponentResourceOptions, CustomResourceOptions, dynamic.Resource, dynamic.ResourceProvider, LocalWorkspace, InlineProgramArgs, Automation API, CrossGuard, PolicyPack
When to use:
ComponentResourceWhen NOT to use:
Key patterns covered:
apply, all, interpolate, and liftingConfig.require, Config.requireSecret, pulumi.secret)dependsOn, protect, aliases, ignoreChanges, transforms)Pulumi treats infrastructure as real code, not configuration files. TypeScript gives you type safety, IDE autocompletion, refactoring tools, and the full Node.js ecosystem. Resources are objects, dependencies are automatic, and reuse happens through functions and classes -- not a custom module language.
Core principles:
ComponentResource encapsulates multiple resources into a single logical unit with its own inputs and outputsOutput<T> represents a value that may not be known until after deployment -- use apply, all, or interpolate to work with them, never unwrap manuallyaliasesEvery resource takes a logical name (used for state tracking), an args bag (typed inputs), and optional resource options.
const bucket = new aws.s3.Bucket(
"data-bucket",
{
versioning: { enabled: true },
lifecycleRules: [
{ enabled: true, expiration: { days: BUCKET_EXPIRY_DAYS } },
],
},
{ protect: true },
); // Prevent accidental deletion
Key points: Logical names must be unique per type within a stack. Pulumi auto-appends a random suffix to the physical name to prevent collisions. Use protect: true on critical resources. Export outputs for cross-stack consumption.
See examples/core.md for resource naming, auto-naming configuration, and provider options.
Wrap related resources in a ComponentResource to create reusable infrastructure units.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
interface StaticSiteArgs {
indexDocument?: string;
errorDocument?: string;
}
class StaticSite extends pulumi.ComponentResource {
public readonly bucketName: pulumi.Output<string>;
public readonly websiteUrl: pulumi.Output<string>;
constructor(
name: string,
args: StaticSiteArgs,
opts?: pulumi.ComponentResourceOptions,
) {
super("myinfra:web:StaticSite", name, args, opts);
const bucket = new aws.s3.BucketV2(`${name}-bucket`, {}, { parent: this });
const website = new aws.s3.BucketWebsiteConfigurationV2(
`${name}-website`,
{
: bucket.,
: { : args. ?? },
: { : args. ?? },
},
{ : },
);
. = bucket.;
. = website.;
.({
: .,
: .,
});
}
}
Why good: child resources use { parent: this }, name is prefixed from parent, registerOutputs is called, type token follows pkg:module:Type format
See examples/core.md for complete component patterns with provider inheritance and multi-resource components.
Outputs represent values resolved after deployment. Never use string concatenation -- use interpolate, apply, or all.
// interpolate -- tagged template for string building (preferred)
const url = pulumi.interpolate`https://${bucket.bucketRegionalDomainName}/index.html`;
// apply -- transform a single output
const upper = bucket.id.apply((id) => id.toUpperCase());
// all -- combine multiple outputs
const endpoint = pulumi
.all([lb.dnsName, listener.port])
.apply(([dns, port]) => `http://${dns}:${port}`);
// Lifting -- access properties directly on resource outputs
const subnetId = vpc.subnets[0].id; // No apply needed for known properties
Why good: interpolate handles Output values transparently, all waits for multiple values, lifting avoids unnecessary apply calls
Gotcha: Resources created inside .apply() will not appear in pulumi preview and may cause ordering issues. Always pass Outputs directly as inputs to other resources.
See examples/core.md for Output patterns, pulumi.output() wrapping, and the apply anti-pattern.
Use pulumi.Config for stack-specific values. Use requireSecret for sensitive data -- it encrypts the value in state.
const config = new pulumi.Config();
// Plain config values
const region = config.require("region"); // Fails if missing
const nodeCount = config.getNumber("nodeCount"); // Returns undefined if missing
// Secret values -- encrypted in state
const dbPassword = config.requireSecret("dbPassword");
const apiKey = config.getSecret("apiKey");
// Mark programmatic values as secret
const connectionString = pulumi.interpolate`postgres://admin:${dbPassword}@${db.endpoint}/mydb`;
// connectionString is automatically secret because dbPassword is secret
// Explicitly mark a value as secret
const token = pulumi.secret(generateToken());
Key point: Any Output derived from a secret is automatically marked secret. You do not need to re-mark derived values.
See examples/core.md for namespaced config, secret outputs, and config set CLI commands.
Resource options control lifecycle behavior. The most important ones:
const db = new aws.rds.Instance(
"primary-db",
{
/* ... */
},
{
protect: true, // Prevent accidental deletion
dependsOn: [vpc, securityGroup], // Explicit ordering
ignoreChanges: ["tags"], // Ignore drift on specific props
aliases: [{ name: "old-db-name" }], // Rename without recreating
retainOnDelete: true, // Keep cloud resource on pulumi destroy
deleteBeforeReplace: true, // For resources that must be unique
replaceOnChanges: ["engine"], // Force replace on specific changes
provider: usEastProvider, // Explicit provider (region, account)
},
);
Gotcha: Changing a resource's logical name or parent causes Pulumi to delete and recreate it. Use aliases to rename safely.
See reference.md for the complete resource options table.
Share outputs between stacks using StackReference.
// In the networking stack: export outputs
export const vpcId = vpc.id;
export const subnetIds = subnets.map((s) => s.id);
// In the application stack: consume outputs
const networkStack = new pulumi.StackReference("myorg/networking/prod");
const vpcId = networkStack.getOutput("vpcId");
const subnetIds = networkStack.getOutput("subnetIds");
// requireOutput fails if the output doesn't exist (safer than getOutput)
const vpcIdRequired = networkStack.requireOutput("vpcId");
See examples/advanced.md for stack reference patterns and getOutputDetails.
Apply transformations to resources and their children. Use transforms (not the deprecated transformations). Transforms receive an args object with type, props, and opts, and return a modified result or undefined to skip.
// Resource-level: apply tags to all taggable children of a component
const vpc = new MyVpcComponent(
"vpc",
{},
{
transforms: [
(args) => {
if (isTaggable(args.type)) {
return {
props: {
...args.props,
tags: { ...args.props["tags"], ManagedBy: "pulumi" },
},
opts: args.opts,
};
}
return undefined;
},
],
},
);
Key difference from deprecated transformations: transforms support modifying packaged component children (awsx, eks), support async callbacks, and do not pass a Resource object.
See examples/advanced.md for stack-level transforms, option modification, and migration from transformations.
Run Pulumi programmatically without the CLI -- for self-service platforms, integration tests, or custom deployment tooling.
const stack = await LocalWorkspace.createOrSelectStack({
stackName: "dev",
projectName: "my-platform",
program: async () => {
const bucket = new aws.s3.Bucket("auto-bucket");
return { bucketName: bucket.id };
},
});
const upResult = await stack.up({ onOutput: console.log });
Key point: The Automation API requires the Pulumi CLI to be installed and on PATH -- it uses the CLI's engine under the hood.
See examples/advanced.md for preview, destroy, local program mode, config setup, and stack output retrieval.
<red_flags>
High Priority:
.apply() -- They won't appear in pulumi preview, cause ordering issues, and break the dependency graph. Pass Outputs directly as resource inputs.{ parent: this } in ComponentResource children -- Resources appear at the root of the state tree, breaking logical grouping and component delete cascading."https://" + bucket.id produces [object Object]. Use pulumi.interpolate instead.Config.require() for passwords/keys -- Stores the value as plaintext in state. Use Config.requireSecret() to encrypt.this.registerOutputs() -- Component outputs won't be tracked properly in state or available via stack references.aliases: [{ name: "old-name" }] to rename safely.Medium Priority:
pulumi:disable-default-providers in config to enforce.dependsOn for non-obvious dependencies -- Pulumi infers dependencies from Input/Output wiring, but side effects (IAM propagation, DNS) need explicit ordering.transformations -- Use transforms instead. transforms also support modifying child resources of packaged components.pulumi.Config and providers for environment-specific values.Gotchas & Edge Cases:
pulumi refresh to detect driftpulumi.secret() wraps a value so it's encrypted in state -- any derived Output is automatically secret tooOutput.apply() runs during pulumi up, not during preview for unknown values -- conditional logic based on unknown outputs may not evaluate during previewpkg:module:Type format (e.g., myinfra:network:Vpc) to avoid conflictsprotect: true only prevents pulumi destroy deletion, not manual cloud console deletionStackReference are fully qualified: org/project/stack</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md
(You MUST pass { parent: this } to ALL child resources inside a ComponentResource -- omitting it breaks the resource tree and state tracking)
(You MUST use pulumi.interpolate for string building with Outputs -- string concatenation silently produces [object Object])
(You MUST NEVER create resources inside .apply() -- they will not appear in pulumi preview and cause ordering issues)
(You MUST use Config.requireSecret() for sensitive values -- Config.require() stores values as plaintext in state)
(You MUST call this.registerOutputs() at the end of every ComponentResource constructor -- omitting it prevents output tracking)
Failure to follow these rules will cause broken state tracking, silent data exposure, and unpredictable deployment behavior.
</critical_reminders>
Application-level caching strategies, HTTP caching, cache invalidation, and stampede prevention
Native MongoDB driver (the mongodb npm package) - MongoClient lifecycle, typed collections, CRUD result shapes, cursors, aggregation pipelines, index design, transactions
GraphQL API server with Apollo Server — schema, resolvers, context, error handling, data sources, plugins
基于 SOC 职业分类