1. Docs
  2. Pulumi IaC
  3. Build with Pulumi
  4. Local Packages

Local Packages

    Pulumi Packages are the core technology that enables cloud infrastructure resource provisioning to be defined once and made available to users in all Pulumi languages. While many packages are published to the Pulumi Registry, there are cases where you might need to work with locally generated packages that haven’t been published.

    Understanding local packages

    Local packages are Pulumi packages with SDKs generated on your computer, instead of being checked into a provider repository and published to the Pulumi Registry. Given a package schema pulumi can generate your package SDK for you. These packages are frequently part of the Pulumi experience in several contexts:

    • When using parameterized providers like terraform-provider.
    • When working with components as packages.
    • During package development and testing.
    • For private or organization-specific resources.

    Local packages allow you to generate SDKs in any Pulumi language for resources or components before they’re published.

    Adding local packages with pulumi package add

    The preferred way to add a local package is with the pulumi package add command, which:

    1. Locally generates an SDK in your currently selected Pulumi language.
    2. Adds the package to your project configuration file (Pulumi.yaml).
    3. Prints instructions on how to link the package into your project.

    Command syntax

    pulumi package add <provider|schema|path> [provider-parameter...] [flags]
    

    Command examples

    From a local path

    pulumi package add ./my-provider
    

    This executes the provider binary to extract its package schema, useful when developing a custom provider locally.

    From a schema file

    pulumi package add ./my/schema.json
    

    This generates an SDK directly from a schema file, which is useful for component resources or when working with pre-defined schema definitions. For details on the structure and syntax of Pulumi package schemas, refer to the Schema Reference.

    From a git repository

    pulumi package add example.com/org/repo.git/path[@version]
    

    This clones the repo and executes the source, enabling you to use packages from private or public git repositories with specific version control. You can specify a branch, tag, or commit hash to control which version is used.

    Using terraform-provider

    pulumi package add terraform-provider hashicorp/random
    

    Refer to the Terraform Provider documentation for more details.

    Using generated SDKs

    After adding a local package, reference it in your project:

    npm install ./sdks/my-package
    
    import * as myPackage from "my-package";
    
    const example = new myPackage.ExampleResource("example");
    
    pip install -e ./sdks/my-package
    
    import my_package
    
    example = my_package.ExampleResource("example")
    
    go get my-package@file:sdks/my-package
    
    import (
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    	"github.com/pulumi/my-package/sdk/go/my_package"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		example := my_package.NewExampleResource("example", nil)
    		return nil
    	})
    }
    
    dotnet add package my-package --source ./sdks/my-package
    
    using Pulumi;
    using MyPackage;
    
    await Deployment.RunAsync(ctx =>
    {
      var example = new ExampleResource("example");
    });
    

    You can then import and use the package in your code just like any other Pulumi package.

    Managing generated SDKs

    When working with locally generated SDKs, you need to decide whether to commit them to your repository or regenerate them as needed:

    • Add the generated SDK directory to your .gitignore file.
    • Document the process for other developers to regenerate the SDK with pulumi install.
    • Include the pulumi package add command in your setup instructions.

    Option 2: Check in the generated SDK

    • Pros: Ensures consistent builds and eliminates the need for regeneration.
    • Cons: Increases repository size and can lead to noisy PRs, possible merge conflicts.

    Updating local packages

    As underlying providers evolve with new features or bug fixes, you’ll need to update your local packages to take advantage of these improvements. To update a local package:

    pulumi package add <provider|schema|path> [provider-parameter...] [flags]
    
    1. Re-run the pulumi package add command with the updated source.
    2. This will regenerate the SDK with the latest schema.
    3. Update your imports and code as needed if there are breaking changes.

    For packages from Git repositories, specify a version tag or commit hash to control which version is used.

    After regenerating the SDK, ensure you reinstall or relink the SDK in your project using your language’s package manager (e.g., npm add, pip install -e, etc.).

    Versioning considerations

    • For native providers (e.g., azure-native, aws-native), versioning is managed via the language package manager (e.g., npm, pip, etc.).

    • For the terraform-provider specifically, you can specify a version with the --version flag:

      pulumi package add terraform-provider hashicorp/random --version=3.5.1
      

      This version information will be stored in your Pulumi.yaml file, ensuring that anyone using your project gets the same provider version. The --version flag is only supported for parameterized providers.

    • Document the version of the source provider you’re using:

      • In your project documentation, note the specific version used.
      • Include version information in your README to help others understand compatibility requirements.
      • Consider creating a VERSION file for packages you develop.
    • Consider using Git tags or specific commit hashes when referencing repositories:

      • Pinning (using specific versions): Ensures reproducible builds and stability, but may miss security patches or important updates.
      • Non-pinning (using latest): Automatically gets the newest features and fixes, but may introduce unexpected breaking changes.
      • Choose pinned versions for production systems where stability is critical, and unpinned/floating versions for development where you want the latest features.

    Managing breaking changes

    When working with local packages, it’s important to understand how breaking changes are handled:

    • For standard providers (like azure-native), the provider version is recorded in your Pulumi.yaml file automatically.

    • When using terraform-provider specifically, you’re working with two different components:

      • The Pulumi terraform-provider bridge (which converts Terraform providers to Pulumi)
      • The actual Terraform provider you’re accessing (e.g., hashicorp/random)

      To ensure stability, you should specify the version of both:

      pulumi package add terraform-provider hashicorp/random --version=3.5.1
      

      This pins the Terraform provider version, protecting you from unexpected breaking changes when the underlying provider is updated.

    See also

    For more information about developing and publishing your own packages, see the Publishing Packages guide.

      Guide to Secure Infrastructure Automation