Pulumi Infrastructure Evolution and Provider Versioning

The maintenance of Infrastructure as Code (IaC) requires a rigorous approach to version management to ensure stability, security, and access to new cloud capabilities. Pulumi, as a modern IaC platform, necessitates a multi-tiered upgrade strategy that encompasses the Command Line Interface (CLI), the backend state storage, and the specific resource providers that translate code into cloud infrastructure. Navigating these upgrades requires an understanding of how the CLI interacts with the state and how providers—specifically those bridging Terraform or native APIs—are evolved over time. Failing to synchronize these components can lead to state drift, deployment failures, or the inability to utilize critical new cloud resource properties.

Pulumi CLI Installation and Versioning

The Pulumi CLI serves as the primary entry point for all infrastructure operations. Keeping the CLI updated is critical for accessing the latest feature sets, performance improvements, and bug fixes. As of the current ecosystem, version 3.250.0 represents a significant milestone in the tool's evolution.

For users transitioning from older versions, such as version 2.17.26, the upgrade path is designed to be streamlined across different operating systems to minimize downtime.

Windows Installation and Upgrade Pathways

Windows users have several options for installing and maintaining the Pulumi CLI, ranging from automated scripts to package managers.

The Windows Package Manager (winget), which is built into Windows 11 and later versions, provides a native way to handle the lifecycle of the application. To perform an initial installation, the following command is utilized:

winget install pulumi

When a newer version of the CLI becomes available, Windows users can trigger an update using the upgrade command:

winget upgrade pulumi

For those who prefer traditional installers, Pulumi provides a Windows x64 installer. Running this executable automatically adds the Pulumi binary to the system path, ensuring that the pulumi command is available machine-wide across all command prompt and PowerShell sessions.

In environments where a manual installation script is preferred, PowerShell can be used to fetch and execute the installation logic. The following command ensures that the security protocol is set to TLS 1.2 before downloading and executing the installation script:

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1'))" && SET "PATH=%PATH%;%USERPROFILE%\.pulumi\bin"

This specific sequence performs several critical actions: it bypasses the execution policy to allow the script to run, downloads the latest installer from the official Pulumi servers, and modifies the session's PATH environment variable to include %USERPROFILE%\.pulumi\bin, where the pulumi.exe is located.

Unix-based and Generic Installation

For users on macOS, Linux, or other Unix-like environments, Pulumi provides a shell script that automates the detection of the operating system and the downloading of the appropriate binary. The standard upgrade command to move from a version like 2.17.26 to 3.250.0 is:

curl -sSL https://get.pulumi.com | sh

This command pipes the installation script directly into the shell, which then handles the placement of the binary in the user's home directory and assists with path configuration.

Air-Gapped and Restricted Environments

In highly secure environments where internet access is restricted, the Pulumi CLI's default behavior of checking for updates on every command can be disruptive. To prevent the CLI from attempting to connect to external servers to verify if a new version exists, users can set a specific environment variable.

Setting PULUMI_SKIP_UPDATE_CHECK to either 1 or true disables the version update check. This is essential for CI/CD pipelines running in isolated VPCs or on-premises data centers where egress traffic is strictly controlled.

State Backend Migration and Management

While upgrading the CLI binary is a client-side operation, the state of the infrastructure is stored in a backend. Depending on whether a user utilizes the Pulumi Service (SaaS) or a DIY backend (such as AWS S3, Azure Blob Storage, or Google Cloud Storage), the upgrade process for the state may differ.

The pulumi state upgrade Command

The pulumi state upgrade command is specifically designed to migrate the current backend to the latest supported version. This is a critical operation for those employing DIY backends, as the format of the state file may change between major CLI versions to support new metadata or efficiency improvements.

The synopsis of the command is as follows:

pulumi state upgrade [flags]

This command ensures that the underlying state storage is compatible with the version of the CLI being used for deployments. If a state file is outdated, the CLI may refuse to perform updates to prevent potential corruption of the infrastructure record.

Command Options and Configuration

The pulumi state upgrade command includes several flags to control the execution flow and output.

  • -y, --yes: This flag is used to automatically approve the upgrade. It is particularly useful in automated pipelines where a human operator cannot manually confirm the migration.
  • -h, --help: Displays the help menu for the upgrade command.

Additionally, the command inherits global flags from the parent Pulumi CLI:

  • --color: Controls the colorization of the output. Options include always, never, raw, and auto.
  • -C, --cwd: Allows the user to run Pulumi as if it had started in a different directory, which is useful for managing multiple projects from a single root directory.
  • --disable-integrity-checking: Disables the integrity check of checkpoint files, which is typically only used in advanced recovery scenarios.
  • -e, --emoji: Enables the use of emojis in the command output for better visual scanning.
  • -Q, --fully-qualify-stack-names: Forces the CLI to show fully-qualified stack names, reducing ambiguity in multi-organization environments.
  • --logflow: Manages how logs are flowed to child processes, such as provider plugins.
  • --logtostderr: Redirects logs to stderr instead of writing them to local files.
  • --memprofilerate: Allows for precise memory allocation profiles by setting the runtime.MemProfileRate.
  • --non-interactive: Disables all interactive prompts, making the command suitable for scripts.
  • --otel-traces: Exports OpenTelemetry traces to a specified endpoint (e.g., file:// or grpc://).
  • --profiling: Emits CPU and memory profiles and execution traces to a file.
  • --tracing: Specifies the endpoint for emitting tracing data.

Automated Provider Upgrades with upgrade-provider

Resource providers are the plugins that Pulumi uses to communicate with cloud APIs. Some providers are native, while others act as bridges to Terraform providers. The upgrade-provider tool is a specialized utility used by developers and maintainers to automate the tedious process of upgrading these providers.

Purpose and Capabilities

The upgrade-provider tool is designed to eliminate the manual effort required to keep a provider current. It automates four primary tasks:

  1. Upgrading the terraform bridge version within the provider.
  2. Upgrading the version of the Pulumi SDK used by the provider.
  3. Updating the provider to the latest version of the upstream source (or a specific target version).
  4. Handling major version upgrades that would otherwise require significant manual refactoring of the bridge code.

Prerequisites for Execution

Before the upgrade-provider tool can be utilized, the host environment must meet specific technical requirements. The tool relies on the underlying build toolchains of the SDKs it is upgrading.

The following software versions and tools are mandatory:

  • Go: Version 1.23.
  • Git: Version 2.36.0 or higher.
  • GitHub CLI: Must be installed and authenticated to manage Pull Requests.
  • Pulumi CLI: The base CLI must be present.
  • Make: Required for executing build scripts.
  • SDK Build Toolchains: Depending on the provider, the appropriate compilers for the released SDKs must be installed.

Installation of upgrade-provider

The tool is installed via the Go toolchain. There are two primary ways to install it depending on whether the user wants the latest stable release or the most recent development version from the main branch.

To install the latest tagged version:

go install github.com/pulumi/upgrade-provider@latest

To install from the main development branch:

go install github.com/pulumi/upgrade-provider@main

Once installed, the binary is placed in the Go bin directory, and the user can call it simply as upgrade-provider.

Executing a Provider Upgrade

The tool requires the organization and repository name of the provider as a positional argument. For example, to upgrade the Docker provider, the command would be:

upgrade-provider pulumi/pulumi-docker

Mandatory and Optional Flags

To ensure the tool operates correctly, especially in CI/CD environments, several flags are available:

  • --upstream-provider-name: This is a required flag unless the tool is run from the provider root and a upgrade-config.yml is present. It identifies the name of the original upstream provider.
  • --allow-major: When set to true, this allows the provider to move to a new major version if one is available.
  • --target-pulumi-version: Allows the user to specify a specific pulumi/{pkg,sdk} version. If left blank, it defaults to the latest version tracking the bridge.
  • --target-version: Allows the user to specify a precise version of the provider to upgrade to.
  • --java-version: Specifies the version of pulumi-java-gen to target for Java SDKs.
  • --kind: Defines the scope of the upgrade. Options include:
    • all: Upgrades both the upstream provider and the bridge (shorthand for bridge, provider, and code).
    • bridge: Only upgrades the bridge.
    • provider: Only upgrades the upstream provider.
    • check-upstream-version: Only checks if an upgrade is necessary.
  • --allow-missing-docs: Prevents the tool from erroring if documentation is missing during the tfgen process. This is equivalent to setting the PULUMI_MISSING_DOCS_ERROR environment variable.

Workflow and Operational Constraints

Running the upgrade-provider tool is an iterative process. The tool handles git operations—including creating branches, making commits, and opening Pull Requests—but it does so in a way that requires the local repository to remain read-only.

A typical execution flow involves:
1. Discovering the repository and validating the local path.
2. Pulling the default branch (e.g., master).
3. Creating a new branch specifically for the upgrade (e.g., upgrade-terraform-provider-snowflake-to-v0.56.3).
4. Running go get -u to update dependencies.

Because provider upgrades involve downloading large dependency trees and running generation tools, they can be long-running. The upgrade-provider command can take up to 10 minutes to complete. When running this via Bash, it is recommended to use a timeout to prevent the process from hanging indefinitely:

timeout 600000

Error Handling and Debugging

When utilizing upgrade-provider, specific exit codes must be monitored to determine the health of the environment.

  • Exit Code 127: This indicates that the upgrade-provider command was not found. This is classified as an environment configuration issue. In such cases, the operator should report the failure immediately and not attempt to manually locate the tool.
  • Logging: To avoid infinite loops and track errors across multiple iterations, it is recommended to pipe the output to a log file:

mkdir -p .pulumi
upgrade-provider $ORG/$REPO --repo-path . > .pulumi/upgrade-provider-stdout.txt 2> /dev/null

Azure Native Provider v2 Transition

The transition to version 2 of the Pulumi Azure Native provider represents a shift in how Azure infrastructure is handled. Unlike Terraform-based providers, the Azure Native provider is auto-generated directly from Azure APIs, ensuring that every new Azure feature is available in Pulumi as soon as the API is released.

Rationale for the v2 Upgrade

The migration from v1 to v2 is driven by several technical improvements aimed at increasing the efficiency and reliability of the provider:

  • Provider Size Reduction: The overall footprint of the provider has been reduced, leading to faster installation and lower memory usage during execution.
  • Module Version Refresh: Default module versions have been updated to ensure the latest best practices are applied.
  • Resource Coverage Expansion: v2 includes coverage for a wider array of Azure resources, reducing the need for custom providers or ARM templates.
  • Case Inconsistency Resolution: Major fixes have been implemented to resolve issues where resource names or properties had inconsistent casing, which previously caused deployment instabilities.
  • Simplified Identity Inputs: User Assigned Managed Identity inputs have been streamlined to be more intuitive for the developer.

Understanding Azure API Versions

A critical component of the Azure Native provider is the concept of API versions. Microsoft utilizes API versioning to allow the introduction of new features or the deprecation of old ones without breaking existing infrastructure.

When upgrading to v2, users must remain aware that the properties available on a resource are tied to the specific API version being targeted. If a project requires a property that only exists in a newer API version, the user must ensure the provider is configured to use that version.

Production Risk Assessment

It is important to note that as of the recent announcements, the v2 Azure Native provider is in a beta release phase. While the upgrade process is described as straightforward, the beta status implies a level of risk. Organizations should avoid deploying v2 to production workloads unless they have a high tolerance for beta software or have performed exhaustive testing in a staging environment. General Availability (GA) is expected later in the year.

Technical Specification Summary

The following tables synthesize the critical data points regarding Pulumi installation and tool versions.

Pulumi CLI Installation Commands

OS / Method Command / Action Target Version
Unix/macOS `curl -sSL https://get.pulumi.com sh` 3.250.0
Windows (winget) winget install pulumi Latest
Windows (Update) winget upgrade pulumi Latest
Windows (PS) iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1')) 3.250.0
Air-Gapped Set PULUMI_SKIP_UPDATE_CHECK=1 N/A

upgrade-provider Environment Requirements

Requirement Minimum Version / Tool Note
Go Language 1.23 Required for tool execution
Git 2.36.0 Required for repo management
GitHub CLI Installed/Auth Required for PR creation
Bash Timeout 600000 ms Recommended for long runs
Java Gen Specified via flag Required for Java SDKs

Analysis of the Upgrade Lifecycle

The process of upgrading a Pulumi environment is not a single event but a continuous lifecycle consisting of three distinct layers: the tool (CLI), the state (Backend), and the bridge (Provider).

The first layer, the CLI, is the most frequent update. Its purpose is to provide the interface and orchestration logic. The shift to version 3.250.0 demonstrates a commitment to maintaining a lean, efficient binary that can be deployed via modern package managers like winget or simple shell scripts.

The second layer, the state backend, is the most sensitive. The pulumi state upgrade command exists because the way Pulumi tracks resources in a DIY backend can evolve. By migrating the state, users ensure that their current infrastructure "truth" is compatible with the new orchestration logic provided by the CLI.

The third layer, the providers, is where the most complexity resides. Because Pulumi often bridges the gap between Terraform's ecosystem and its own SDKs, the upgrade-provider tool is essential. It automates the complex choreography of upgrading a terraform-bridge, updating the Go-based provider code, and generating new SDKs for users. This ensures that when a cloud provider like AWS or Azure updates an API, the Pulumi community can propagate those changes rapidly without manual coding for every minor version bump.

The Azure Native v2 example further illustrates this evolution. By moving toward an auto-generated model, Pulumi reduces the "human-in-the-loop" requirement for provider updates, moving away from hand-crafted bridges toward a direct mapping of cloud APIs. This reduces the size of the provider and increases the coverage of available resources, representing a fundamental shift in how IaC providers are maintained.

Sources

  1. Pulumi Install Documentation
  2. Pulumi State Upgrade CLI Reference
  3. Smithery AI Pulumi Upgrade Provider
  4. Pulumi Upgrade-Provider GitHub
  5. Sam Cogan Azure Provider Upgrade Guide

Related Posts