23

I am using vagrant with puppet to set up virtual machines for development environments. I would like to simply set a few environment variables in the .pp file. Using virtual box and a vagrant base box for Ubuntu 64 bit.

I have this currently.

$bar = 'bar'

class foobar {
   exec { 'foobar':
     command => "export Foo=${bar}",
   }
}

but when provisioning I get an error: Could not find command 'export'.

This seems like it should be simple enough am I missing some sort of require or path for the exec type? I noticed in the documentation there is an environment option to set up environment variables, should I be using that?

bgrantdev
  • 1,622
  • 4
  • 17
  • 29

9 Answers9

22

If you only need the variables available in the puppet run, whats wrong with :

Exec { environment => [ "foo=$bar" ] }

?

John
  • 573
  • 2
  • 6
  • 2
    exec statements wont export the variable for when he logs in to the server. – ptierno Aug 24 '13 at 18:46
  • 7
    I know that - thats why i said 'if you only need the variables available in the puppet run'. The question does not state that the variables are required to be set in user shells – John Aug 24 '13 at 23:29
16

Simplest way to acomplish this is to put your env vars in /etc/environment, this ensures they are available to everything (or pretty much everything).

Something like this:

class example($somevar) {
    file { "/etc/environment":
        content => inline_template("SOMEVAR=${somevar}")
    }
}

Reason for having the class parameterised is so you can target it from hiera with automatic variable lookup (http://docs.puppetlabs.com/hiera/1/puppet.html#automatic-parameter-lookup) ... if you're sticking something in /etc/environment, it's usually best if you actually make it environment specific.

note: I've only tested this on ubuntu

Andrei Serdeliuc ॐ
  • 5,828
  • 5
  • 39
  • 66
  • I like the simple & succinct fix much more than I dislike that this pollutes my `/etc/environment`. Thanks. – 7yl4r May 25 '17 at 20:41
4

The way I got around it is to also use /etc/profile.d:

$bar = 'bar'
file { "/etc/profile.d/my_test.sh":
  content => "export Foo=${bar}",
  mode    => 755
}

This ensures that everytime you login (ex ssh), the variable $MYVAR gets exported to your environment. After you apply through puppet and login (ex ssh localhost), echo $Foo would return bar

Tony Z
  • 195
  • 1
  • 8
4

You can set an environment variable by defining it on a line in /etc/environment and you can ensure a line inside a file using file_line in puppet. Combine these two into the following solution:

file_line { "foo_env_var":
    ensure  => present,
    line    => "Foo=${bar}",
    path    => "/etc/environment",
}
7yl4r
  • 4,788
  • 4
  • 34
  • 46
  • 1
    This is the cleanest solution if you need to coexist with other environment variables in your /etc/environment file. You can also use the match parameter to ensure that the line isn't duplicated after it is changed. – N. DaSilva Dec 18 '18 at 17:14
  • How would you use that variable? Just `$foo_env_var` ? – LanFeusT May 24 '21 at 22:43
  • `foo_env_var` is the name of the line used by puppet only. The environment variable being set here is `Foo` so using it will be like `$Foo` - eg: `echo $Foo` – 7yl4r May 26 '21 at 16:36
2

You could try the following, which sets the environment variable for this exec:

class foobar {
   exec { 'foobar' :
     command => "/bin/bash -c \"export Foo=${bar}\"",
   }
}
iamauser
  • 11,119
  • 5
  • 34
  • 52
  • Thanks for the response I actually found that solution. While it removes the error about the command not being found it unfortunately does not produce the expected result. The environment variable Foo is not set when I ssh into the virtual machine. – bgrantdev Aug 23 '13 at 23:01
  • 5
    This is a noop. It modifies the environment of a shell that has been forked specifically for this `exec` resource. This shell then immediately terminates. The export has no effect. – Felix Frank Apr 23 '15 at 13:29
2

Something like this would work while preserving existing contents of the /etc/environment file:

/code/environments/{environment}/manifests/environment/variable.pp:

define profile::environment::variable (
    $variable_name,
    $value,
    $ensure => present,
) {
    file_line { $variable_name:
        path   => '/etc/environment',
        ensure => $ensure,
        line   => "$variable_name=$value",
        match  => "$variable_name=",
    }
}

Usage (in the body of a node manifest):

profile::environment::variable { 'JAVA_HOME':
    variable_name  => 'JAVA_HOME',
    value => '/usr/lib/jvm/java-1.8.0',
}
N. DaSilva
  • 174
  • 3
  • 4
0

I know this is an old question, but I was able to set the PS1 prompt value and add it to my .bashrc file like this:

$PS1 = '\[\e[0;31m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \$ '

and within a class:

exec {"vagrant-prompt":
  unless =>  "grep -F 'export PS1=\"${PS1}\"' ${HOME_DIR}/.bashrc",
  command => "echo 'export PS1=\"${PS1}\"' >> ${HOME_DIR}/.bashrc",
  user => "${APP_USER}",
}

The -F makes grep it interpret it as a fixed string. Otherwise it won't find it and keeps adding to the .bashrc file.

Cameron
  • 1,000
  • 8
  • 11
0

Another variation. This has the advantage that stdlib isn't required (as is with file_line solutions), and the existing content of /etc/environment is preserved:

exec {'echo foo=bar>>/etc/environment':
  onlyif => 'test -f /etc/environment',
  unless => 'grep "foo=bar" /etc/environment',
  path   => '/usr/bin',
}
Jimadine
  • 998
  • 13
  • 26
0

Check out the documentation https://puppet.com/docs/puppet/5.5/types/exec.html

class envcheck {

  file { '/tmp/test':
    ensure => file,
  }

  exec { 'foobar':
    command     => 'echo $bar >> /tmp/test',
    environment => ['bar=foo'],
    path        => ['/bin/'],
  }
}
  1. Creating an empty file because an echo would happen in the shell Puppet is running the command in, not the one we're looking at.
  2. Setting an environment variable bar to equal foo.
  3. Setting the path for the echo binary, this isn't normally necessary for system commands but useful to know about.
16c7x
  • 500
  • 2
  • 6