Author : MD TAREQ HASSAN | Updated : 2021/10/10

About Stack Configuration

Managing Stack Specific Configuration

Stack Settings File

Setting and Getting Configurations

Set configuration

#pulumi config set <namespace>:<key> <value> [flags]
pulumi config set xyz XyzValue

#
# flag: --plaintext
#
pulumi config set ns:xyz XyzValue --plaintext

# for secrets ("--secrets"), see secret section

Pulumi.dev.yaml

config:
  ns:xyz: XyzValue

# ... ... ...

With json

pulumi config set ns:xyz '{"key1": "val1", "key2": "val2" }'

pulumi config set ns:xyz '["val1", "val2"]'

Get configuration

pulumi config get xyz

Nested or Structured Configuration

Use --path flag

pulumi config set --path 'ns:data.active' true

pulumi config set --path 'ns:data.nums[0]' 1
pulumi config set --path 'ns:data.nums[1]' 2
pulumi config set --path 'ns:data.nums[2]' 3

Pulumi.dev.yaml

config:
  proj:data:
    active: true
    nums:
    - 1
    - 2
    - 3

Accessing Configuration from Code

Pulumi.dev.yaml

config:
  ns:ResourceGroupNameKey: yyy-rg
  
  ns:TagsKey:
    CreatedBy: Pulumi
    Scope: Demo
    
  ns:ItemsListKey:
  - item1
  - item2
  - item3
  
  ns:data:
    active: true
    IntVal: 2020
    nums:
    - 1
    - 2
    - 3

C# Code

var configNamespace = "ns"
var config = new Config(configNamespace);

var resourceGroupName = config.Require("ResourceGroupNameKey")!;

var Tags = config.RequireObject<Dictionary<string, string>>("TagsKey")!;

var items = config.RequireObject<List<string>>("ItemsListKey")!;

var jsonObject = config.RequireObject<JsonElement>("data")!; // jsonObject -> instance of JsonElement class


//Get typed value
var isActive = jsonObject.GetProperty("active").GetBoolean()!; // true
var intVal = jsonObject.GetProperty("IntVal").GetInt32() ?? 2021;

Secrets

Set secrets using Pulumi cli

pulumi config set --secret dbPassword xxx

#
# Nested secret
#
pulumi config set --secret --path 'ns:MainManagedInstanceArgs.AdministratorLoginPassword' <strong-password-here>

Pulumi.dev.yaml

config:
  # ... ... ...
  
  ns:dbPassword: xxx
  
  ns:MainManagedInstanceArgs:
    # ... ... ...
    AdministratorLoginPassword:
      secure: v1:xxxxxxx

Get secrets using Pulumi cli

#
# Pulumi will automatically decrypt and provide value as plain text
#
pulumi config get ns:dbPassword

pulumi config get --path 'ns:MainManagedInstanceArgs.AdministratorLoginPassword'

Get secrets in code

var config = new Config("ns");

//
// Simple
//
var dbPassword = config.RequireSecret("dbPassword"); //key -> ns:dbPassword

//
// Complex: secret from complex object
//
var mainManagedInstanceArgs = config.RequireObject<JsonElement>("MainManagedInstanceArgs");
var miAdminPassword = mainManagedInstanceArgs.GetString("AdministratorLoginPassword");

var mainManagedInstance = new ManagedInstance("MainManagedInstance", new ManagedInstanceArgs {

    // ... ... ...
    
    AdministratorLoginPassword = miAdminPassword, // miAdminPassword will be decrypted by Pulumi during runtime
    
    // ... .... ...
});

Default Location

Pulumi.XxxDev.yaml

config:
  azure-native:location: japaneast
  
  # ... ... ...

MyStack

var mainRg = new ResourceGroup("DemoRg", new ResourceGroupArgs
{
    ResourceGroupName = "DemoRG"
    //Location = # will be set automatically from azure-native:location in stack settings file
});

// ... ... ...

Best Practices for Using Configuration in Code

Pulumi.XxxDev.yml

config:
  azure-native:location: japaneast # default location
  
  xxx:ResourceGroupArgs:
    ResourceGroupName: DemoRG
    Tags:
      CreatedBy: Pulumi
      Scope: Demo

StackConfig.cs

namespace PulumiDemo.Constants
{
    internal static class StackConfig
    {
        internal const string CONFIG_NAMESPACE = "xxx";

        internal const string KEY_RESOURCE_GROUP_ARGS = "ResourceGroupArgs";
        
       // ... ... ...

    }
}

StringLiterals.cs

namespace PulumiDemo.Constants
{
    internal static class StringLiterals
    {
        internal const string NAME = "Name";
        internal const string TAGS = "Tags";
        internal const string RESOURCE_GROUP_NAME = "ResourceGroupName";



        //
        // Unique names for Pulumi resources
        //
        internal const string RESOURCE_GROUP_MAIN = "ResourceGroupMain";
        
        // ... ... ...
    }
}

MyStack.cs

using System.Threading.Tasks;
using Pulumi;
using Pulumi.AzureNative.Resources;
using Pulumi.AzureNative.Storage;
using static PulumiDemo.Constants.StackConfig;
using static PulumiDemo.Constants.StringLiterals;
using System.Collections.Generic;
using System.Text.Json;

namespace PulumiDemo
{
    class MyStack : Stack
    {
        public MyStack()
        {
            var config = new Config(CONFIG_NAMESPACE);
            
            //
            // Use Pulumi config to get ResourceGroupArgs from yaml (as json element)
            // Then exract configuration values from json element
            //
            var mainRgArgs = config.RequireObject<JsonElement>(KEY_RESOURCE_GROUP_ARGS);
            var mainRgName = mainRgArgs.GetProperty(RESOURCE_GROUP_NAME).GetString()!;
            var mainRgTags = mainRgArgs.GetProperty(TAGS).Deserialize<Dictionary<string, string>>()!; // .Deserialize -> available only in .Net 6.0+

            var mainRg = new ResourceGroup(RESOURCE_GROUP_MAIN, new ResourceGroupArgs
            {
                ResourceGroupName = mainRgName,
                Tags = mainRgTags
            });
            
            // ... ... ...
        }
    }
}