Accessing Environment Variables in Puppet Manifests: Best Practices and Code Examples


2 views

When working with Puppet, you might need to access environment variables that are set in the Puppet master's environment. This becomes particularly useful when you want to:

  • Dynamically adjust configurations based on deployment environments
  • Pass sensitive information without hardcoding in manifests
  • Create environment-specific behaviors in your infrastructure code

Puppet provides several ways to access environment variables from within your manifests:

1. Using the $::environment Variable

Puppet automatically provides the current environment name through the $::environment variable:


# Example: Conditionally include classes based on environment
if $::environment == 'production' {
  include nginx::production_config
} else {
  include nginx::development_config
}

2. Accessing System Environment Variables

For accessing other environment variables available to the Puppet master process:


# Using the $::facts hash (requires Facter)
$db_host = $facts['env']['DB_HOST'] ? {
  undef   => 'localhost',
  default => $facts['env']['DB_HOST']
}

# Alternative method using the $::environment special variable
$app_env = getvar('::environment')

3. Using External Data Lookups

A more robust approach for production environments:


# In hiera.yaml
---
version: 5
defaults:
  datadir: data
  data_hash: yaml_data
hierarchy:
  - name: "Environment variables"
    lookup_key: env_lookup
    options:
      variables: %{facts.env}
      
# In your manifest
$api_key = lookup('API_KEY', String, 'first')

When working with environment variables in Puppet:

  • Always provide default values for critical variables
  • Use the getvar() function for safer variable access
  • Consider using Hiera for complex environment-specific configurations
  • For sensitive data, prefer using Puppet's encrypted secrets management

Here's a complete example of using environment variables for database configuration:


class profile::database {
  $db_host = pick($facts['env']['DB_HOST'], 'localhost')
  $db_user = pick($facts['env']['DB_USER'], 'app_user')
  $db_pass = pick($facts['env']['DB_PASS'], 'default_pass')

  file { '/etc/app/database.conf':
    ensure  => file,
    content => template('profile/database.conf.erb'),
    owner   => 'root',
    group   => 'root',
    mode    => '0600',
  }
}

With corresponding template (database.conf.erb):


# Database Configuration
host: <%= @db_host %>
username: <%= @db_user %>
password: <%= @db_pass %>

When working with Puppet manifests, you might need to access environment variables from the Puppet daemon's environment. Unlike shell scripts where you can simply use $VAR, Puppet requires specific approaches to access these values.

There are several ways to access environment variables in Puppet manifests:

1. Using the $::environment Variable

Puppet automatically provides access to its environment through the $::environment variable:

# Example: Using built-in environment variable
if $::environment == 'production' {
  notify { 'This is production environment': }
}

2. Accessing Custom Environment Variables

For custom environment variables, you'll need to use the generate() function or external facts:

# Example: Using generate() to access env vars
$db_password = generate('/bin/sh', '-c', 'echo $DB_PASSWORD')

# Then use it in your resource
file { '/etc/db.conf':
  content => "password=${db_password}",
  mode    => '0600'
}

3. Using External Facts

A more maintainable approach is to use external facts:

# Create a fact in /etc/puppetlabs/facter/facts.d/env_vars.sh
#!/bin/bash
echo "custom_env_var=$CUSTOM_ENV_VAR"

# Then access it in your manifest
$value = $facts['custom_env_var']

When dealing with environment variables in Puppet:

  • Always sanitize input from environment variables
  • Consider using Hiera for sensitive data instead of environment variables
  • Use appropriate file permissions when writing files containing environment variables
  • Log and monitor access to sensitive environment variables

For complex scenarios, you can create a custom Puppet function:

# lib/puppet/parser/functions/get_env.rb
module Puppet::Parser::Functions
  newfunction(:get_env, :type => :rvalue) do |args|
    ENV[args[0]]
  end
end

# In your manifest:
$api_key = get_env('API_KEY')