0
# Automation
1
2
Pulumi's Automation API enables programmatic management of Pulumi stacks and workspaces, allowing you to build custom deployment tools, CI/CD integrations, and infrastructure management applications.
3
4
## Core Workspace Classes
5
6
```typescript { .api }
7
abstract class Workspace {
8
abstract workDir: string;
9
abstract pulumiHome?: string;
10
abstract program?: PulumiFn;
11
abstract envVars: { [key: string]: string };
12
abstract secretsProvider?: string;
13
abstract projectSettings(): Promise<ProjectSettings>;
14
abstract saveProjectSettings(settings: ProjectSettings): Promise<void>;
15
abstract stackSettings(stackName: string): Promise<StackSettings>;
16
abstract saveStackSettings(stackName: string, settings: StackSettings): Promise<void>;
17
abstract serializeArgsForOp(stackName: string): Promise<string[]>;
18
abstract postCommandCallback(stackName: string): Promise<void>;
19
}
20
21
class LocalWorkspace extends Workspace {
22
static create(args?: LocalWorkspaceOptions): Promise<LocalWorkspace>;
23
static createStack(args: LocalProgramArgs): Promise<Stack>;
24
static selectStack(args: LocalProgramArgs): Promise<Stack>;
25
static createOrSelectStack(args: LocalProgramArgs): Promise<Stack>;
26
27
workDir: string;
28
pulumiHome?: string;
29
program?: PulumiFn;
30
envVars: { [key: string]: string };
31
secretsProvider?: string;
32
33
constructor(opts?: LocalWorkspaceOptions);
34
35
projectSettings(): Promise<ProjectSettings>;
36
saveProjectSettings(settings: ProjectSettings): Promise<void>;
37
stackSettings(stackName: string): Promise<StackSettings>;
38
saveStackSettings(stackName: string, settings: StackSettings): Promise<void>;
39
installPlugin(name: string, version: string, kind?: string): Promise<void>;
40
removePlugin(name: string, versionRange?: string, kind?: string): Promise<void>;
41
listPlugins(): Promise<PluginInfo[]>;
42
exportStack(stackName: string): Promise<Deployment>;
43
importStack(stackName: string, state: Deployment): Promise<void>;
44
whoAmI(): Promise<string>;
45
pulumiVersion(): Promise<string>;
46
}
47
```
48
49
## Stack Management
50
51
```typescript { .api }
52
class Stack {
53
readonly name: string;
54
readonly workspace: Workspace;
55
56
constructor(name: string, workspace: Workspace);
57
58
// Core operations
59
up(opts?: UpOptions): Promise<UpResult>;
60
preview(opts?: PreviewOptions): Promise<PreviewResult>;
61
refresh(opts?: RefreshOptions): Promise<RefreshResult>;
62
destroy(opts?: DestroyOptions): Promise<DestroyResult>;
63
64
// Import/Export operations
65
import(opts: ImportOptions): Promise<ImportResult>;
66
export(): Promise<Deployment>;
67
68
// Configuration management
69
getConfig(key: string): Promise<ConfigValue>;
70
getAllConfig(): Promise<{ [key: string]: ConfigValue }>;
71
setConfig(key: string, value: ConfigValue): Promise<void>;
72
setAllConfig(config: { [key: string]: ConfigValue }): Promise<void>;
73
removeConfig(key: string): Promise<void>;
74
removeAllConfig(keys: string[]): Promise<void>;
75
76
// Stack information
77
outputs(): Promise<OutputMap>;
78
history(pageSize?: number, page?: number): Promise<UpdateSummary[]>;
79
info(): Promise<StackSummary>;
80
81
// Stack lifecycle
82
rename(newName: string): Promise<void>;
83
cancel(): Promise<void>;
84
}
85
```
86
87
## Operation Options and Results
88
89
```typescript { .api }
90
interface UpOptions {
91
parallel?: number;
92
message?: string;
93
expectNoChanges?: boolean;
94
diff?: boolean;
95
replace?: string[];
96
target?: string[];
97
targetDependents?: boolean;
98
policyPacks?: string[];
99
policyPackConfigs?: { [key: string]: PolicyPackConfig };
100
refresh?: boolean;
101
userAgent?: string;
102
colorMode?: "always" | "never" | "raw" | "auto";
103
continueOnError?: boolean;
104
}
105
106
interface UpResult {
107
stdout: string;
108
stderr: string;
109
summary: UpdateSummary;
110
outputs: OutputMap;
111
}
112
113
interface PreviewOptions {
114
parallel?: number;
115
message?: string;
116
expectNoChanges?: boolean;
117
diff?: boolean;
118
replace?: string[];
119
target?: string[];
120
targetDependents?: boolean;
121
policyPacks?: string[];
122
policyPackConfigs?: { [key: string]: PolicyPackConfig };
123
refresh?: boolean;
124
userAgent?: string;
125
colorMode?: "always" | "never" | "raw" | "auto";
126
}
127
128
interface PreviewResult {
129
stdout: string;
130
stderr: string;
131
summary: UpdateSummary;
132
changeSummary: { [key: string]: number };
133
}
134
135
interface DestroyOptions {
136
parallel?: number;
137
message?: string;
138
target?: string[];
139
targetDependents?: boolean;
140
refresh?: boolean;
141
userAgent?: string;
142
colorMode?: "always" | "never" | "raw" | "auto";
143
continueOnError?: boolean;
144
}
145
146
interface DestroyResult {
147
stdout: string;
148
stderr: string;
149
summary: UpdateSummary;
150
}
151
```
152
153
## Configuration Types
154
155
```typescript { .api }
156
interface LocalWorkspaceOptions {
157
workDir?: string;
158
pulumiHome?: string;
159
program?: PulumiFn;
160
envVars?: { [key: string]: string };
161
secretsProvider?: string;
162
kubeconfig?: string;
163
projectSettings?: ProjectSettings;
164
stackSettings?: { [key: string]: StackSettings };
165
repo?: GitRepo;
166
}
167
168
interface LocalProgramArgs {
169
stackName: string;
170
workDir?: string;
171
program?: PulumiFn;
172
opts?: LocalWorkspaceOptions;
173
}
174
175
interface InlineProgramArgs {
176
stackName: string;
177
projectName: string;
178
program: PulumiFn;
179
opts?: LocalWorkspaceOptions;
180
}
181
182
type PulumiFn = () => Promise<void> | void;
183
184
interface ProjectSettings {
185
name: string;
186
runtime: ProjectRuntimeInfo;
187
main?: string;
188
description?: string;
189
author?: string;
190
website?: string;
191
license?: string;
192
config?: { [key: string]: ProjectConfigType };
193
template?: ProjectTemplate;
194
backend?: ProjectBackend;
195
options?: ProjectOptions;
196
plugins?: PluginOptions;
197
}
198
199
interface StackSettings {
200
secretsProvider?: string;
201
encryptedKey?: string;
202
encryptionSalt?: string;
203
config?: { [key: string]: ConfigValue };
204
}
205
206
interface ConfigValue {
207
value: string;
208
secret?: boolean;
209
}
210
211
type OutputMap = { [key: string]: OutputValue };
212
213
interface OutputValue {
214
value: any;
215
secret: boolean;
216
}
217
```
218
219
## Event System
220
221
```typescript { .api }
222
interface EngineEvent {
223
sequence: number;
224
timestamp: number;
225
}
226
227
interface CancelEvent extends EngineEvent {
228
type: "cancelEvent";
229
}
230
231
interface DiagnosticEvent extends EngineEvent {
232
type: "diagnosticEvent";
233
urn?: string;
234
prefix: string;
235
message: string;
236
color: string;
237
severity: "debug" | "info" | "warning" | "error";
238
streamId?: number;
239
ephemeral?: boolean;
240
}
241
242
interface PreludeEvent extends EngineEvent {
243
type: "preludeEvent";
244
config: { [key: string]: string };
245
}
246
247
interface SummaryEvent extends EngineEvent {
248
type: "summaryEvent";
249
maybeCorrupt: boolean;
250
durationSeconds: number;
251
resourceChanges?: { [key: string]: number };
252
policyPacks?: PolicyPackRunInfo[];
253
}
254
255
interface ResourcePreEvent extends EngineEvent {
256
type: "resourcePreEvent";
257
metadata: StepEventMetadata;
258
}
259
260
interface ResOutputsEvent extends EngineEvent {
261
type: "resOutputsEvent";
262
metadata: StepEventMetadata;
263
}
264
265
interface ResOpFailedEvent extends EngineEvent {
266
type: "resOpFailedEvent";
267
metadata: StepEventMetadata;
268
}
269
```
270
271
## Usage Examples
272
273
### Basic Stack Operations
274
275
```typescript
276
import * as pulumi from "@pulumi/pulumi";
277
import { LocalWorkspace } from "@pulumi/pulumi/automation";
278
279
// Create inline program
280
const program = async () => {
281
const bucket = new pulumi.aws.s3.Bucket("my-bucket");
282
return { bucketName: bucket.id };
283
};
284
285
// Create and deploy stack
286
const stack = await LocalWorkspace.createStack({
287
stackName: "dev",
288
projectName: "my-project",
289
program,
290
});
291
292
// Configure stack
293
await stack.setConfig("aws:region", { value: "us-east-1" });
294
295
// Deploy
296
const upResult = await stack.up();
297
console.log(`Update succeeded. Outputs: ${JSON.stringify(upResult.outputs)}`);
298
```
299
300
### Workspace from Existing Project
301
302
```typescript
303
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
304
305
// Create workspace from existing Pulumi project
306
const workspace = await LocalWorkspace.create({
307
workDir: "./my-pulumi-project",
308
});
309
310
// Select existing stack
311
const stack = await Stack.select("production", workspace);
312
313
// Preview changes
314
const previewResult = await stack.preview();
315
console.log(`Preview completed: ${previewResult.changeSummary}`);
316
317
// Apply if changes look good
318
if (previewResult.changeSummary.create > 0) {
319
const upResult = await stack.up();
320
console.log("Deployment completed");
321
}
322
```
323
324
### Configuration Management
325
326
```typescript
327
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
328
329
const workspace = await LocalWorkspace.create({
330
workDir: "./project",
331
});
332
333
const stack = await Stack.select("staging", workspace);
334
335
// Set multiple configuration values
336
await stack.setAllConfig({
337
"app:environment": { value: "staging" },
338
"app:replica-count": { value: "3" },
339
"app:database-password": { value: "secret123", secret: true },
340
"aws:region": { value: "us-west-2" },
341
});
342
343
// Get configuration
344
const config = await stack.getAllConfig();
345
console.log("Current configuration:", config);
346
347
// Remove configuration
348
await stack.removeConfig("app:old-setting");
349
```
350
351
### Event Monitoring
352
353
```typescript
354
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
355
356
const stack = await Stack.select("production", workspace);
357
358
// Monitor deployment events
359
const upResult = await stack.up({
360
onOutput: (out: string) => {
361
console.log(`Output: ${out}`);
362
},
363
onEvent: (event) => {
364
if (event.type === "diagnosticEvent") {
365
console.log(`${event.severity}: ${event.message}`);
366
} else if (event.type === "resourcePreEvent") {
367
console.log(`Starting ${event.metadata.op} on ${event.metadata.type}`);
368
}
369
},
370
});
371
```
372
373
### Stack History and Rollback
374
375
```typescript
376
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
377
378
const stack = await Stack.select("production", workspace);
379
380
// Get deployment history
381
const history = await stack.history();
382
console.log(`Found ${history.length} deployments`);
383
384
// Find last successful deployment
385
const lastSuccessful = history.find(h => h.result === "succeeded");
386
387
if (lastSuccessful) {
388
console.log(`Last successful deployment: ${lastSuccessful.version}`);
389
390
// Rollback to previous version (manual process)
391
// This would typically involve:
392
// 1. Export the target state
393
// 2. Import it as the current state
394
// 3. Run refresh to sync
395
}
396
```
397
398
### Multi-Stack Management
399
400
```typescript
401
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
402
403
const workspace = await LocalWorkspace.create({
404
workDir: "./infrastructure",
405
});
406
407
const environments = ["dev", "staging", "production"];
408
409
for (const env of environments) {
410
const stack = await Stack.select(env, workspace);
411
412
// Environment-specific configuration
413
const envConfig = {
414
"app:environment": { value: env },
415
"app:replica-count": { value: env === "production" ? "5" : "2" },
416
"aws:region": { value: env === "production" ? "us-east-1" : "us-west-2" },
417
};
418
419
await stack.setAllConfig(envConfig);
420
421
// Deploy with environment-specific options
422
const upResult = await stack.up({
423
parallel: env === "production" ? 1 : 10, // More careful in prod
424
message: `Automated deployment to ${env}`,
425
});
426
427
console.log(`${env} deployment completed`);
428
}
429
```
430
431
### Custom Deployment Tool
432
433
```typescript
434
import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";
435
436
class DeploymentManager {
437
private workspace: LocalWorkspace;
438
439
constructor(private projectPath: string) {}
440
441
async initialize() {
442
this.workspace = await LocalWorkspace.create({
443
workDir: this.projectPath,
444
});
445
}
446
447
async deployToEnvironment(environment: string, config: Record<string, any>) {
448
const stack = await Stack.createOrSelect(environment, this.workspace);
449
450
// Apply configuration
451
const configValues = Object.entries(config).reduce((acc, [key, value]) => {
452
acc[key] = typeof value === "object" && value.secret
453
? { value: value.value, secret: true }
454
: { value: String(value) };
455
return acc;
456
}, {} as Record<string, any>);
457
458
await stack.setAllConfig(configValues);
459
460
// Preview first
461
console.log(`Previewing changes for ${environment}...`);
462
const previewResult = await stack.preview();
463
464
if (previewResult.changeSummary.create === 0 &&
465
previewResult.changeSummary.update === 0 &&
466
previewResult.changeSummary.delete === 0) {
467
console.log("No changes required");
468
return;
469
}
470
471
// Confirm deployment
472
console.log("Changes detected:", previewResult.changeSummary);
473
474
// Deploy
475
console.log(`Deploying to ${environment}...`);
476
const upResult = await stack.up();
477
478
console.log("Deployment completed successfully");
479
console.log("Outputs:", upResult.outputs);
480
481
return upResult;
482
}
483
484
async listStacks() {
485
const stacks = await this.workspace.listStacks();
486
return stacks.map(s => ({
487
name: s.name,
488
current: s.current,
489
lastUpdate: s.lastUpdate,
490
resourceCount: s.resourceCount,
491
}));
492
}
493
}
494
495
// Usage
496
const manager = new DeploymentManager("./my-infrastructure");
497
await manager.initialize();
498
499
await manager.deployToEnvironment("staging", {
500
"app:environment": "staging",
501
"app:database-password": { value: "secret123", secret: true },
502
"aws:region": "us-west-2",
503
});
504
```
505
506
## Best Practices
507
508
- Use inline programs for simple, dynamic infrastructure
509
- Leverage existing projects for complex, version-controlled infrastructure
510
- Always preview changes before applying in production environments
511
- Use configuration management for environment-specific settings
512
- Monitor deployment events for better observability
513
- Implement proper error handling and rollback strategies
514
- Use parallel deployment settings appropriate for your environment
515
- Store sensitive configuration as secrets
516
- Implement proper access controls for production deployments