How to set environmental variables using Ansible
Asked Answered
W

3

38

I need to set the variables like JAVA_HOME and update PATH. There are a number of ways of doing this. One way is to update the /etc/environment variable and include a line for JAVA_HOME using the lineinfile module and then run the command source /etc/environment directly on the guest OS (CentOS in my case).

Another way is to execute the export command e.g.

export JAVA_HOME=/usr/java/jre1.8.0_51
export PATH=$PATH:$JAVA_HOME

Is there a cleaner way to do this as all these require manipulating files and running commands directly on the OS to update the environment variables?

Waltner answered 2/8, 2015 at 18:19 Comment(1)
Did you figure out anyway for the same? I was having a problem where I launch a server from ansible and want to export the IP of the created instance to the shell for another script to use. Can you help me out on that? Thanks in advance.Orthochromatic
B
36

Yes, there is a cleaner way. You can set environment variables per task:

  tasks:
  - shell: echo JAVA_HOME is $JAVA_HOME
    environment:
      JAVA_HOME: /usr/java/jre1.8.0_51
    register: shellout
  - debug: var=shellout

Output:

TASK: [shell echo JAVA_HOME is $JAVA_HOME] ********************************** 
changed: [localhost]

TASK: [debug var=shellout] **************************************************** 
ok: [localhost] => {
    "var": {
        "shellout": {
            "changed": true, 
            "cmd": "echo JAVA_HOME is \"$JAVA_HOME\"", 
            "delta": "0:00:00.005797", 
            "end": "2015-08-07 06:32:47.295061", 
            "invocation": {
                "module_args": "echo JAVA_HOME is \"$JAVA_HOME\"", 
                "module_name": "shell"
            }, 
            "rc": 0, 
            "start": "2015-08-07 06:32:47.289264", 
            "stderr": "", 
            "stdout": "JAVA_HOME is /usr/java/jre1.8.0_51", 
            "stdout_lines": [
                "JAVA_HOME is /usr/java/jre1.8.0_51"
            ], 
            "warnings": []
        }
    }
}

If you set the environment variable like above in a task, it is only available for this specific task. In subsequent tasks it does not exist unless you define it again.

Though you can define env vars per play as well:

- hosts:
  - localhost
  gather_facts: no
  environment:
    JAVA_HOME: /usr/java/jre1.8.0_51
  tasks:
     ...

Now it's gonna be available for all tasks of this play.

See Setting the Environment and FAQ: How can I set the PATH or any other environment variable for a task or entire playbook? in the docs.


Another example with a script task:

  tasks:
  - script: /tmp/script.sh
    environment:
      JAVA_HOME: /usr/java/jre1.8.0_51
    register: shellout
  - debug: var=shellout

Where the script simply has this content:

#!/bin/sh

echo JAVA_HOME is $JAVA_HOME
Beeswing answered 2/8, 2015 at 19:10 Comment(8)
The following gives me an error "ERROR: JAVA_HOME is not a legal parameter in an Ansible task or handler" and from the documenation, there doesn't seem to be an indication of the standard variables. - name: Set path shell: ls environment: JAVA_HOME: /usr/java/jre1.8.0_51 Any suggestions on other methods or alternatives?Waltner
I just tested it again and it works for me. Make sure you have the correct yml indention. The error sounds like it might be at the same width as environment but it needs to be a subelement of environment. Here is another Ansible doc which shows this should work:Beeswing
Thank you again. I'm still not getting this to work. Can you provide another example without the "-shell" command? The Ansible documentation doesn't give an example to create and set a new environment variable clearly. Ideally, I'd like to get more examples to see how this works?Waltner
Somehow is seem to forget to paste the link in my previous comment... -> docs.ansible.com/ansible/…Beeswing
The environment parameter is global and should be working with any task. I'll try to find another easy example, shell was just simply to test. BTW, it should also work on play level, not only on task level.Beeswing
I added an example with a script task. Im sorry, I can't think of any easy to reproduce example other than shell and script. But environment is a global feature and should work with any task. If you still get an error like you described above, there rather is a indention error in your yml. Another idea i had was, you might be trying to use the env var on a separate tasks. If defined per task it's only available on that task where it was defined, not on subsequent tasks. You can define it for the whole play though. Added example for that too.Beeswing
@DeepakShenoy: I had the very same problem, double-check the indentation of the environment: row - it has to be the same level as shell: or register:Ofelia
What about if the OS requires the variable because the application you're provisioning reads for it, any other options other than export?Icarus
W
18

I found that a workaround to do this was to use the lineinfile command in Ansible:

- name: Set JAVA_HOME
  lineinfile: dest=/etc/environment state=present regexp='^JAVA_HOME' >
     line='JAVA_HOME=/opt/jre1.8.0_51/bin'

While this is not ideal, it allows you to create new environmental variables. Of course, you should use variables to construct your directory path. I have included the explicit path to simplify my example.

Waltner answered 6/8, 2015 at 19:12 Comment(0)
F
13

Update to the lineinfile approach. The JAVA_HOME value should not include the bin directory. The following worked for centos:

- name: Set JAVA_HOME
  lineinfile:
    dest: /etc/environment
    state: present
    regexp: '^JAVA_HOME'
    line: 'JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk'
Frendel answered 29/4, 2018 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.