adbdkb
adbdkb

Reputation: 2181

Ansible - Set Playbook level Environment variable, but after defining some tasks

I want to set a playbook level environment, but after I execute a couple of tasks. I have found that I could define a playbook level environment variable before definition of any tasks or task level environment variables. But, I haven't found how can I set-up an environment variable that can be used by all tasks following a task.

- name: server properties
  hosts: kafka_broker
  vars:
    ansible_ssh_extra_args: "-o StrictHostKeyChecking=no"
    ansible_host_key_checking: false
    date: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}"
    copy_to_dest: "/export/home/kafusr/kafka/secrets"
    server_props_loc: "/etc/kafka"
    secrets_props_loc: "{{ server_props_loc }}/secrets"

  environment:
    CONFLUENT_SECURITY_MASTER_KEY: "{{ extract_key2 }}"

  tasks:

    - name: Create a directory if it does not exist
      file:
        path: "{{ copy_to_dest }}"
        state: directory
        mode: '0755'

    - name: Find files from "{{ server_props_loc }}"
      find:
        paths: /etc/kafka/
        patterns: "server.properties*"
        # ... the rest of the task
      register: etc_kafka_server_props

    - name: Find files from "{{ secrets_props_loc }}"
      find:
        paths: /etc/kafka/secrets
        patterns: "*"
        # ... the rest of the task
      register: etc_kafka_secrets_props

    - name: Copy the files
      copy:
        src: "{{ item.path }}"
        dest: "{{ copy_to_dest }}"
        remote_src: yes
      loop: "{{ etc_kafka_server_props.files + etc_kafka_secrets_props.files }}"

    - name: set masterkey content value
      set_fact:
        contents: "{{ lookup('file', '/export/home/kafusr/kafka/secrets/masterkey.txt') }}"
        extract_key2: "{{ contents.split('\n').2.split('|').2|trim }}"

I want to set CONFLUENT_SECURITY_MASTER_KEY after the set_facts task

Is it possible to set playbook level environment variable, but after defining some tasks

Thank you

UPDATE

Initially, when I was executing the playbook as originally defined, I was getting the error

fatal: [kafkaserver1]: FAILED! => {"msg": "The field 'environment' has an invalid value, 
which includes an undefined variable. The error was: 'extract_key2' is undefined"}

which was expected as the variable extract_key2 was not set - before copying the files to desired directory.

After @Zeitounator's suggestion, when I added default to the environment variable's definition,

CONFLUENT_SECURITY_MASTER_KEY: "{{ extract_key2 | default('') }}"

I now get a different error

The new error is

TASK [set masterkey content value] ******************** fatal: [kafkaserver1]: FAILED! => 
{"msg": "The task includes an option with an undefined variable. The error was: 'contents' is undefined\n\n
The error appears to be in '/export/home/kafuser/tmp/so-71538207-question.yml': line 43, column 7, but may\n
be elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n
- name: set masterkey content value\n      ^ here\n"} 

Getting this on all 3 brokers in the console and I checked the file it exists

I did do a cat on that file, copying the path from error to make sure there is no typo, and the contents of that file are displayed on console.

Update 2

I am trying to figure out how to use slurp to get the info, with the same approach as @Zeitounator's example about using lookup.

This is what I am trying. The current definition, is of course, erroneous. Just wanted to show what I am trying to do. But, can it be done for slurp and am I on the right path?

    environment:

    CONFLUENT_SECURITY_MASTER_KEY: >-
      {{
        (
          ((slurp: src: /export/home/z8tpush/kafka/secrets/masterkey.txt)['content'] | b64decode ).split('\n').2.split('|').2|trim 
        )
      }}

@Zeitounator - Will you be able to direct me to an example where a slurp or fetch module is defined to set-up an environment variable and where the value will get updated after the tasks that create the file are executed, similar to what you have shown with lookup filter? I would really appreciate it.

Note:

Ultimately, I want to use ansible to create a new kafka user using confluents CLI commands ( using shell or command module ), verify it in my directory and once satisfied, I will encrypt the security.properties file using the masterkey and copy it to the appropriate location where confluent is installed.

Upvotes: 1

Views: 3638

Answers (2)

Zeitounator
Zeitounator

Reputation: 44760

You cannot set_fact a var depending on an other var in the same block. Moreover, there is absolutely no need to set_fact here as long as your relevant tasks can live with an empty environment var until it is fully defined. The following environment declaration (untested) should work and return the key for every task running after your file exists.

  environment:
    CONFLUENT_SECURITY_MASTER_KEY: >-
      {{
        (
          (
            lookup('file', '/export/home/kafusr/kafka/secrets/masterkey.txt', errors='ignore')
            | default('')
          ).split('\n').2
          | default('')
        ).2
        | default('')
        | trim
      }}

Upvotes: 0

U880D
U880D

Reputation: 12121

As already mentioned, you can

Regarding your question

I haven't found how can I set-up an environment variable that can be used by all tasks following a task.

You can set the environment on Block level, a logical groups of tasks too

  • Setting the remote environment: "When you set a value with environment: at the play or block level, it is available only to tasks within the play or block that are executed by the same user."

This means you would need to define a block for the next tasks

   - name: Block of next task(s)
     block:
     
     - name: Next task
       ...

     environment:
       CONFLUENT_SECURITY_MASTER_KEY: "{{ extract_key2 }}"

Regarding your question

Is it possible to set playbook level environment variable, but after defining some tasks?

No, not on that level in that run as the playbook is already running.

Another option might be to distribute the tasks in question into an other role, playbook or task file and include_* it.

Upvotes: 0

Related Questions