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


11 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')