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.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.