Automation API Overview
Relevant source files
The following files were used as context for generating this wiki page:
The Pulumi Automation API provides a programmatic interface for driving Pulumi programs without using the command-line interface (CLI). It encapsulates the functionality of the CLI, such as pulumi up, pulumi preview, and pulumi stack init, allowing for greater flexibility and integration into custom applications. The Automation API is ideal for a variety of use cases, including building CI/CD workflows, integration testing, multi-stage deployments (like blue-green patterns), and creating custom tooling or REST/gRPC APIs on top of Pulumi. While it offers a programmatic way to manage infrastructure, it still requires a Pulumi CLI binary to be installed and available on the system's $PATH.
Sources: sdk/go/auto/README.md:15-19, sdk/python/lib/pulumi/automation/__init__.py:10-14, README.md:12-13.
Core Concepts
The Automation API is built around two primary concepts: the Workspace and the Stack. These components provide the structure and execution context for running Pulumi programs.
This diagram shows the fundamental relationship between a Workspace and its Stacks.
Workspace
A Workspace is the main execution context for a Pulumi program. It contains a single Pulumi project and its associated stacks. The workspace is responsible for managing the execution environment, which includes tasks like:
- Plugin installation and management.
- Environment configuration (e.g., setting
PULUMI_HOME). - Creating, selecting, deleting, and listing stacks.
The default implementation, LocalWorkspace, uses Pulumi.yaml for project settings and Pulumi.<stack-name>.yaml for stack settings, mirroring the behavior of the Pulumi CLI. Custom Workspace implementations can be created to store project and stack settings in other backends, such as a database or cloud object storage.
Sources: sdk/go/auto/README.md:52-75, sdk/python/lib/pulumi/automation/__init__.py:47-75.
Stack
A Stack is an isolated, independently configurable instance of a Pulumi program. Each stack is associated with a Workspace and has access to the full range of Pulumi lifecycle operations. These operations are exposed as methods on the Stack object.
The typical workflow for using the Automation API is illustrated below.
The primary methods available on a Stack object are summarized in the table below.
| Method | Description | Corresponding CLI Command |
|---|---|---|
Up() | Creates or updates resources in a stack. | pulumi up |
Preview() | Previews changes to a stack's resources. | pulumi preview |
Destroy() | Destroys all resources in a stack. | pulumi destroy |
Refresh() | Refreshes the state of a stack's resources. | pulumi refresh |
SetConfig() | Sets a configuration value for the stack. | pulumi config set |
GetConfig() | Retrieves a configuration value for the stack. | pulumi config get |
GetAllConfig() | Retrieves all configuration values for the stack. | pulumi config |
Outputs() | Gets the outputs of a stack. | pulumi stack output |
Sources: sdk/go/auto/README.md:16-18, sdk/python/lib/pulumi/automation/__init__.py:11-13.
Program Sources
The Automation API supports several ways to define the Pulumi program to be executed. This flexibility allows developers to choose the most convenient method for their use case, from running local projects to defining infrastructure inline with their automation code.
Local Programs
Programs can be sourced from the local filesystem. This is the most common approach and is analogous to running pulumi up in a local project directory. The workspace is initialized with a path to the directory containing the Pulumi.yaml file.
Go Example:
stack, err := NewStackLocalSource(ctx, "myOrg/myProj/myStack", filepath.Join("..", "path", "to", "project"))
Sources: sdk/go/auto/README.md:22-24.
Python Example:
stack = create_stack("myOrg/myProj/myStack", work_dir=os.path.join("..", "path", "to", "project"))
Sources: sdk/python/lib/pulumi/automation/__init__.py:20-21.
Remote Git Programs
Programs can be fetched from a Git repository. The Automation API will clone the repository and run the Pulumi program from a specified subdirectory. This is useful for CI/CD scenarios where the infrastructure code lives in version control.
Go Example:
stack, err := NewStackRemoteSource(ctx, "myOrg/myProj/myStack", GitRepo{
URL: "https:github.com/pulumi/test-repo.git",
ProjectPath: filepath.Join("project", "path", "repo", "root", "relative"),
})
Sources: sdk/go/auto/README.md:26-31.
Inline Programs
For simple cases or for embedding infrastructure directly within an application, programs can be defined as an inline function. This function is passed directly to the stack creation method and is executed by the Pulumi engine. This approach is particularly useful for debugging or for creating higher-level tools.
Go Example:
stack, err := NewStackInlineSource(ctx, "myOrg/myProj/myStack", "myProj", func(pCtx *pulumi.Context) error {
bucket, err := s3.NewBucket(pCtx, "bucket", nil)
if err != nil {
return err
}
pCtx.Export("bucketName", bucket.Bucket)
return nil
})
Sources: sdk/go/auto/README.md:33-41.
Python Example:
def pulumi_program():
bucket = s3.Bucket("bucket")
pulumi.export("bucket_name", bucket.Bucket)
stack = create_stack("myOrg/myProj/myStack", program=pulumi_program)
Sources: sdk/python/lib/pulumi/automation/__init__.py:26-31.
CLI Dependency and Versioning
The Automation API is a wrapper around the Pulumi CLI and requires a compatible CLI binary to be installed and accessible in the system's $PATH. The API includes mechanisms to install a specific version of the Pulumi CLI and to validate that the installed version meets the minimum requirements.
The PulumiCommand class in the Node.js SDK, for example, provides methods to install a specific version of the CLI and to get a command instance, which can perform version checks.
// Example of installing a specific CLI version
const cmd = await PulumiCommand.install({ root: tmpDir.name, version: new semver.SemVer("3.97.0") });
// Example of version validation logic
const validate = () => parseAndValidatePulumiVersion(minVersion, test.currentVersion, test.optOut);
The parseAndValidatePulumiVersion function checks for major version mismatches and ensures the installed version meets a minimum requirement. This helps prevent runtime errors due to incompatibilities between the Automation API SDK and the underlying Pulumi engine.
Sources: sdk/nodejs/tests/automation/cmd.spec.ts:31-41, 91-146, sdk/go/auto/README.md:18-19.
Use Cases
The Automation API is designed to support a wide range of scenarios beyond typical CLI usage. Some of the primary use cases include:
- CI/CD Integration: Driving Pulumi deployments programmatically within CI/CD pipelines.
- Integration Testing: Creating and destroying ephemeral infrastructure for tests.
- Multi-Stage Deployments: Orchestrating complex deployment patterns like blue-green or canary releases by managing multiple stacks and passing outputs from one to another.
- Custom Tooling: Building higher-level tools, custom CLIs, or internal developer platforms on top of Pulumi's core engine.
- Infrastructure as a Service: Exposing Pulumi's capabilities through a REST or gRPC API.
- Debugging: Using inline programs to create a single entry point for debugging Pulumi applications.
Sources: sdk/go/auto/README.md:52-64, sdk/python/lib/pulumi/automation/__init__.py:47-62.