1. Docs
  2. Pulumi ESC
  3. Get started
  4. Integrate with Pulumi IaC

Pulumi ESC: Integrate with Pulumi IaC

    Overview

    Pulumi ESC works independently of Pulumi Infrastructure as Code (IaC), providing developers the flexibility to centrally manage their environment configuration regardless of how or where those environments are created.

    Pulumi ESC also integrates seamlessly with Pulumi IaC, and this tutorial will demonstrate how to leverage Pulumi ESC in your own Pulumi programs. This works everywhere, including Pulumi Deployments and GitHub Actions, without any additional work or changes.

    Prerequisites

    To complete the steps in this tutorial, you will need to install the following prerequisites:

    Create and Configure a New Project

    Once the prerequisites are installed, run the pulumi new <language> command in an empty folder to create a new Pulumi project, making sure to replace <language> with the supported language of your choice:

    # example using python
    $ pulumi new python
    This command will walk you through creating a new Pulumi project.
    
    Enter a value or leave blank to accept the (default), and press <ENTER>.
    Press ^C at any time to quit.
    
    project name (pulumi-esc-iac):  
    project description (A minimal Python Pulumi program):  
    Created project 'pulumi-esc-iac'
    
    Please enter your desired stack name.
    To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
    stack name (dev): pulumi/dev
    Created stack 'dev'
    
    Installing dependencies...
    
    Creating virtual environment...
    Finished creating virtual environment
    Updating pip, setuptools, and wheel in virtual environment...
    ...
    ...
    Finished installing dependencies
    
    Your new project is ready to go!
    
    To perform an initial deployment, run `pulumi up`
    

    Access configuration locally

    In a Pulumi project, you can locally store and retrieve configuration values using the pulumi config set <key> [value] command. Run the following command to create a config value with a key of myEnvironment and a value of development:

    $ pulumi config set myEnvironment development
    

    Now run the following command to create a secret config value with a key of myPassword and a value of demo-password-123:

    $ pulumi config set myPassword demo-password-123 --secret
    

    These values will be stored in your project’s stack settings file Pulumi.<your-stack-name>.yaml as shown below:

    # Contents of Pulumi.<your-stack-name>.yaml file
    config:
      pulumi-esc-iac:myEnvironment: development
      pulumi-esc-iac:myPassword:
        secure: AAABADd5YzRaVuzxM08i5z2CJ3LGkQau5e5Lhk+1Gtj37qv6zKkFr8KxmN6X+w/XMg==
    

    You can retrieve the value of this configuration via the CLI by running the pulumi config get <key> command as shown below:

    # example output
    $ pulumi config get myEnvironment
    development
    

    You can also import and access this configuration value from directly within your Pulumi program as shown below:

    "use strict";
    const pulumi = require("@pulumi/pulumi");
    
    // Create a new Pulumi Config
    const config = new pulumi.Config();
    
    // Retrieve the values of "myEnvironment" and "myPassword"
    const environment = config.get("myEnvironment");
    const password = config.getSecret("myPassword");
    
    // Export values as stack outputs
    module.exports = {
        Environment: environment,
        Password: password,
    };
    
    import * as pulumi from "@pulumi/pulumi";
    
    // Create a new Pulumi Config
    const config = new pulumi.Config();
    
    // Retrieve the values of "myEnvironment" and "myPassword"
    const environment = config.get("myEnvironment");
    const password = config.getSecret("myPassword");
    
    // Export values as stack output
    export const Environment = environment;
    export const Password = password;
    
    import pulumi
    
    # Import the configuration values
    config = pulumi.Config()
    
    # Retrieve the values of "myEnvironment" and "myPassword"
    environment = config.get("myEnvironment")
    password = config.get_secret("myPassword")
    
    # Export the values as an output
    pulumi.export('Environment', environment)
    pulumi.export("Password", password)
    package main
    
    import (
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		// Create a Pulumi Config
    		config := config.New(ctx, "")
    
    		// Retrieve the value of "myEnvironment" and "myPassword"
    		environment := config.Get("myEnvironment")
    		password := config.GetSecret("myPassword")
    
    		// Export values as outputs
    		ctx.Export("Environment", pulumi.String(environment))
    		ctx.Export("Password", pulumi.StringOutput(password))
    		return nil
    	})
    }
    
    using Pulumi;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    
    class Program
    {
        static async Task<int> Main(string[] args)
        {
            return await Deployment.RunAsync(() =>
            {
                // Import the configuration values
                var config = new Config();
    
                // Retrieve the value of "myEnvironment" and "myPassword"
                var environment = config.Get("myEnvironment");
                var password = config.GetSecret("myPassword");
    
                // Return a dictionary of outputs
                return new Dictionary<string, object?>
                {
                    ["Environment"] = environment,
                    ["Password"] = password
                };
            });
        }
    }
    
    package myproject;
    
    import com.pulumi.Pulumi;
    import com.pulumi.core.Output;
    
    public class App {
        public static void main(String[] args) {
            Pulumi.run(ctx -> {
                // Create a Pulumi Config
                var config = ctx.config();
    
                // Retrieve the values of "myEnvironment" and "myPassword"
                var environment = config.get("myEnvironment");
                var password = config.getSecret("myPassword");
    
                // Export the values as a stack outputs
                ctx.export("Environment", Output.of(environment));
                ctx.export("Password", Output.of(password));
            });
        }
    }

    Run the pulumi preview command as shown below to validate the retrieval of the configuration:

    $ pulumi preview
    Previewing update (dev)
    
    Loading policy packs...
    
         Type                 Name                Plan
     +   pulumi:pulumi:Stack  pulumi-esc-iac-dev  create
    
    Policies:
        ✅ pulumi-internal-policies@v0.0.6
    
    Outputs: # the outputted config values
        Environment: "development"
        Password   : [secret]
    
    Resources:
        + 1 to create
    

    Defining the configuration via the project stack settings file may be fine when dealing with a singular project, but it can become very challenging to maintain securely and consistently across multiple projects. Centralizing these configuration values using Pulumi ESC provides more scalability without increasing administrative overhead along the way.

    Access configuration from ESC

    To centralize this configuration and make it accessible to your Pulumi program, you will need to add a second-level key named pulumiConfig in your environment file that will expose the values nested underneath it to Pulumi IaC. Add the following configuration to your environment file:

    values:
      pulumiConfig:
        myEnvironment: development
    

    From here, you will need to import your environment file into your Pulumi project. To do this, return to your Pulumi.<your-stack-name>.yaml file and update it to import your environment as shown below, making sure to replace the value of <your-project-name>/<your-environment-name> with the identifier of your own environment:

    environment:
      - <your-project-name>/<your-environment-name>
    

    This will import any configuration values that you have defined under the pulumiConfig key in your environment file and make them accessible to your Pulumi project.

    Save the file and then run the pulumi config get <key> command as shown below to quickly test that the import is working:

    # example output
    $ pulumi config get myEnvironment
    development
    

    Now run the pulumi preview command again to test that the imported configuration value is accessible from within your Pulumi program:

    $ pulumi preview
    Previewing update (dev)
    
    Loading policy packs...
    
         Type                 Name                Plan
     +   pulumi:pulumi:Stack  pulumi-esc-iac-dev  create
    
    Policies:
        ✅ pulumi-internal-policies@v0.0.6
    
    Outputs:
        Value: "development"
    
    Resources:
        + 1 to create
    

    See the Pulumi documentation on Accessing Configuration from Code for more details.

      PulumiUP 2024. Watch On Demand.