pulumi-python
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePulumi Python Skill
Pulumi Python 技能指南
Development Workflow
开发工作流
1. Project Setup
1. 项目设置
bash
undefinedbash
undefinedCreate new Python project
创建新的Python项目
pulumi new python
pulumi new python
Or with a cloud-specific template
或者使用云服务商特定模板
pulumi new aws-python
pulumi new azure-python
pulumi new gcp-python
**Project structure:**my-project/
├── Pulumi.yaml
├── Pulumi.dev.yaml # Stack config (use ESC instead)
├── main.py
├── requirements.txt # or pyproject.toml
└── venv/ # Virtual environment
undefinedpulumi new aws-python
pulumi new azure-python
pulumi new gcp-python
**项目结构:**my-project/
├── Pulumi.yaml
├── Pulumi.dev.yaml # 栈配置(建议使用ESC替代)
├── main.py
├── requirements.txt # 或pyproject.toml
└── venv/ # 虚拟环境
undefined2. Pulumi ESC Integration
2. Pulumi ESC 集成
Instead of using or stack config files, use Pulumi ESC for centralized secrets and configuration.
pulumi config setLink ESC environment to stack:
bash
undefined建议使用Pulumi ESC集中管理密钥和配置,替代命令或栈配置文件。
pulumi config set将ESC环境关联到栈:
bash
undefinedCreate ESC environment
创建ESC环境
pulumi env init myorg/myproject-dev
pulumi env init myorg/myproject-dev
Edit environment
编辑环境
pulumi env edit myorg/myproject-dev
pulumi env edit myorg/myproject-dev
Link to Pulumi stack
关联到Pulumi栈
pulumi config env add myorg/myproject-dev
**ESC environment definition (YAML):**
```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}pulumi config env add myorg/myproject-dev
**ESC环境定义(YAML):**
```yaml
values:
# 静态配置
pulumiConfig:
aws:region: us-west-2
myapp:instanceType: t3.medium
# 用于AWS的动态OIDC凭证
aws:
login:
fn::open::aws-login:
oidc:
roleArn: arn:aws:iam::123456789:role/pulumi-oidc
sessionName: pulumi-deploy
# 从AWS Secrets Manager拉取密钥
secrets:
fn::open::aws-secrets:
region: us-west-2
login: ${aws.login}
get:
dbPassword:
secretId: prod/database/password
# 暴露为环境变量
environmentVariables:
AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
AWS_SESSION_TOKEN: ${aws.login.sessionToken}3. Python Patterns
3. Python 编程模式
Basic resource creation:
python
import pulumi
import pulumi_aws as aws基础资源创建:
python
import pulumi
import pulumi_aws as awsGet configuration from ESC
从ESC获取配置
config = pulumi.Config()
instance_type = config.require("instanceType")
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",
},
)
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)
**Using dictionary literals (concise alternative):**
```python
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",
},
)Component resources for reusability:
python
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,
})Stack references for cross-stack dependencies:
python
import pulumipulumi.export("bucket_name", bucket.id)
pulumi.export("bucket_arn", bucket.arn)
**使用字典字面量(简洁写法):**
```python
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",
},
)可复用的组件资源:
python
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)
# 创建子资源并指定parent=self
load_balancer = lb.LoadBalancer(
f"{name}-lb",
load_balancer_type="application",
# ... 配置内容
opts=pulumi.ResourceOptions(parent=self),
)
self.url = load_balancer.dns_name
self.register_outputs({
"url": self.url,
})跨栈依赖的栈引用:
python
import pulumiReference 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")
**Working with Outputs:**
```python
import puluminetworking_stack = pulumi.StackReference("myorg/networking/prod")
vpc_id = networking_stack.get_output("vpc_id")
subnet_ids = networking_stack.get_output("private_subnet_ids")
**处理Output对象:**
```python
import pulumiApply transformation
应用转换
uppercase_name = bucket.id.apply(lambda id: id.upper())
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]}"
)
combined = pulumi.Output.all(bucket.id, bucket.arn).apply(
lambda args: f"Bucket {args[0]} 的ARN为 {args[1]}"
)
Using Output.concat for string interpolation
使用Output.concat进行字符串插值
message = pulumi.Output.concat("Bucket ARN: ", bucket.arn)
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
)
undefinedis_prod = pulumi.get_stack() == "prod"
if is_prod:
alarm = aws.cloudwatch.MetricAlarm(
"alarm",
# ... 配置内容
)
undefined4. Using ESC with pulumi env run
4. 结合ESC使用 pulumi env run
Run any command with ESC environment variables injected:
bash
undefined运行任意命令时注入ESC环境变量:
bash
undefinedRun pulumi commands with ESC credentials
使用ESC凭证运行pulumi命令
pulumi env run myorg/aws-dev -- pulumi up
pulumi env run myorg/aws-dev -- pulumi up
Run tests with secrets
使用密钥运行测试
pulumi env run myorg/test-env -- pytest
pulumi env run myorg/test-env -- pytest
Open environment and export to shell
打开环境并导出到shell
pulumi env open myorg/myproject-dev --format shell
undefinedpulumi env open myorg/myproject-dev --format shell
undefined5. Async Patterns
5. 异步编程模式
python
import pulumi
import asynciopython
import pulumi
import asyncioPulumi programs are single-threaded
Pulumi程序是单线程的
Use Output.from_input for async-like patterns
使用Output.from_input实现类异步模式
async def fetch_data():
# Async operation
return {"key": "value"}
async def fetch_data():
# 异步操作
return {"key": "value"}
Convert async result to Output
将异步结果转换为Output
data = pulumi.Output.from_input(asyncio.get_event_loop().run_until_complete(fetch_data()))
undefineddata = pulumi.Output.from_input(asyncio.get_event_loop().run_until_complete(fetch_data()))
undefined6. Multi-Language Components
6. 多语言组件
Create components in Python that can be consumed from any Pulumi language (TypeScript, Go, C#, Java, YAML).
Project structure for multi-language component:
my-component/
├── PulumiPlugin.yaml # Required for multi-language
├── pyproject.toml # or requirements.txt
└── __main__.py # Component + entry pointPulumiPlugin.yaml:
yaml
runtime: pythonComponent with proper Args class (main.py):
python
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,
})创建Python编写的组件,可被任意Pulumi支持的语言(TypeScript、Go、C#、Java、YAML)调用。
多语言组件的项目结构:
my-component/
├── PulumiPlugin.yaml # 多语言支持必填
├── pyproject.toml # 或requirements.txt
└── __main__.py # 组件代码+入口PulumiPlugin.yaml:
yaml
runtime: python带Args类的组件实现(main.py):
python
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类 - 所有属性使用Input类型"""
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):
"""带加密和版本控制的安全S3存储桶"""
bucket_id: Output[str]
bucket_arn: Output[str]
# 构造函数必须包含带类型注解的'args'参数
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],
)
**Publishing for multi-language consumption:**
```bashif name == "main":
component_provider_host(
name="python-components",
components=[SecureBucket],
)
**发布供多语言调用的组件:**
```bashConsume from git repository
从Git仓库引入组件
pulumi package add github.com/myorg/my-component
pulumi package add github.com/myorg/my-component
With version tag
指定版本标签
pulumi package add github.com/myorg/my-component@v1.0.0
pulumi package add github.com/myorg/my-component@v1.0.0
Local development
本地开发时引入
pulumi package add /path/to/local/my-component
**Multi-language Args requirements:**
- Use `pulumi.Input[T]` type hints for all properties
- Args class must have `__init__` with typed parameters
- Constructor must have `args` parameter with type annotation
- Use `Optional[Input[T]]` for optional propertiespulumi package add /path/to/local/my-component
**多语言Args类要求:**
- 所有属性使用`pulumi.Input[T]`类型提示
- Args类必须包含带类型参数的`__init__`方法
- 组件构造函数必须包含带类型注解的`args`参数
- 可选属性使用`Optional[Input[T]]`Best Practices
最佳实践
Security
安全
- Use Pulumi ESC for all secrets - never commit secrets to stack config files
- Enable OIDC authentication instead of static credentials
- Use dynamic secrets with short TTLs when possible
- Apply least-privilege IAM policies
- 使用Pulumi ESC管理所有密钥 - 切勿将密钥提交到栈配置文件
- 启用OIDC认证替代静态凭证
- 尽可能使用带短TTL的动态密钥
- 应用最小权限原则的IAM策略
Code Organization
代码组织
- Use ComponentResources for reusable infrastructure patterns
- Leverage Python's type hints for better IDE support
- Keep stack-specific config in ESC environments
- Use stack references for cross-stack dependencies
- Prefer Args classes for type safety, or dict literals for brevity
- 使用ComponentResource实现可复用的基础设施模式
- 利用Python类型提示获得更好的IDE支持
- 将栈特定配置存储在ESC环境中
- 使用栈引用处理跨栈依赖
- 优先使用Args类保证类型安全,或使用字典字面量简化代码
Deployment
部署
- Always run before
pulumi previewpulumi up - Use ESC environment versioning and tags for releases
- Implement proper tagging strategy for all resources
- 执行前务必先运行
pulumi uppulumi preview - 对ESC环境使用版本控制和标签管理发布
- 为所有资源实现规范的标签策略
Virtual Environments
虚拟环境
- Always use virtual environments (,
venv, orpoetry)uv - Specify toolchain in Pulumi.yaml for consistency
- 始终使用虚拟环境(、
venv或poetry)uv - 在Pulumi.yaml中指定工具链以保证一致性
Common Commands
常用命令
bash
undefinedbash
undefinedEnvironment Commands (pulumi env)
环境命令(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 env init <org>/<project>/<env> # 创建环境
pulumi env edit <org>/<env> # 编辑环境
pulumi env open <org>/<env> # 查看解析后的值
pulumi env run <org>/<env> -- <command> # 注入环境变量运行命令
pulumi env version tag <org>/<env> <tag> # 为版本打标签
Pulumi Commands
Pulumi核心命令
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
pulumi new python # 创建新项目
pulumi config env add <org>/<env> # 关联ESC环境
pulumi preview # 预览变更
pulumi up # 部署
pulumi stack output # 查看输出
pulumi destroy # 销毁资源
Dependency Management
依赖管理
pip install -r requirements.txt # Install deps (pip)
poetry add pulumi-aws # Add dep (poetry)
uv add pulumi-aws # Add dep (uv)
undefinedpip install -r requirements.txt # 安装依赖(pip)
poetry add pulumi-aws # 添加依赖(poetry)
uv add pulumi-aws # 添加依赖(uv)
undefinedPython-Specific Considerations
Python特定注意事项
Virtual Environment Setup
虚拟环境设置
Using pip (default):
yaml
undefined使用pip(默认):
yaml
undefinedPulumi.yaml
Pulumi.yaml
runtime:
name: python
options:
toolchain: pip
virtualenv: venv
**Using poetry:**
```yamlruntime:
name: python
options:
toolchain: pip
virtualenv: venv
**使用poetry:**
```yamlPulumi.yaml
Pulumi.yaml
runtime:
name: python
options:
toolchain: poetry
**Using uv:**
```yamlruntime:
name: python
options:
toolchain: poetry
**使用uv:**
```yamlPulumi.yaml
Pulumi.yaml
runtime:
name: python
options:
toolchain: uv
virtualenv: .venv
undefinedruntime:
name: python
options:
toolchain: uv
virtualenv: .venv
undefinedType Checking
类型检查
yaml
undefinedyaml
undefinedPulumi.yaml - Enable type checking
Pulumi.yaml - 启用类型检查
runtime:
name: python
options:
typechecker: mypy # or pyright
undefinedruntime:
name: python
options:
typechecker: mypy # 或pyright
undefinedInput Type Options
输入类型选项
python
undefinedpython
undefinedUsing Args classes (type-safe)
使用Args类(类型安全)
bucket = aws.s3.Bucket(
"bucket",
versioning=aws.s3.BucketVersioningArgs(enabled=True),
)
bucket = aws.s3.Bucket(
"bucket",
versioning=aws.s3.BucketVersioningArgs(enabled=True),
)
Using dict literals (concise)
使用字典字面量(简洁)
bucket = aws.s3.Bucket(
"bucket",
versioning={"enabled": True},
)
undefinedbucket = aws.s3.Bucket(
"bucket",
versioning={"enabled": True},
)
undefinedReferences
参考链接
- references/pulumi-esc.md - ESC patterns and commands
- references/pulumi-patterns.md - Common infrastructure patterns
- references/pulumi-python.md - Python-specific guidance
- references/pulumi-best-practices-aws.md - AWS best practices
- references/pulumi-best-practices-azure.md - Azure best practices
- references/pulumi-best-practices-gcp.md - GCP best practices
- references/pulumi-esc.md - ESC模式与命令
- references/pulumi-patterns.md - 常见基础设施模式
- references/pulumi-python.md - Python特定指南
- references/pulumi-best-practices-aws.md - AWS最佳实践
- references/pulumi-best-practices-azure.md - Azure最佳实践
- references/pulumi-best-practices-gcp.md - GCP最佳实践