0

I have this task in my playbook:

- name: Update instance tags
    command: oci compute instance update -c {{ compartment }} --freeform-tags {{ tag_var_json }}

According to the oracle documentation for this command, the parameter --freeform-tags accepts a json that represents the key-value pair for the tag. I need to have this json be created dynamically in the playbook itself, so prior to running that task, I have this one for testing purposes:

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

But I must be doing something wrong because I keep getting this error:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'tag_var' is undefined

Is there an easier way of creating a json directly in the playbook and passing it as an argument to that parameter?

Thank you.

Ress
  • 45
  • 1
  • 2
  • 8
  • YAML keys ought to be unique. So your sample is incorrect syntax. Maybe you meant to set the variable in a different task? – anx Oct 04 '21 at 11:41
  • Did you maybe misinterpret the error as something returned from your command? This is *ansible* itself talking, not a quote of a message returned from some program called! – anx Oct 04 '21 at 11:43
  • I'm new to ansible so apologies. I'm just trying to pass a json in as as anrgument to a parameter as seen above, but I need to build said json in the same playbook – Ress Oct 04 '21 at 13:21

1 Answers1

1

There are two things going on here. The first is that you have created YAML that is accepted by the parser, but behaves in a slightly unexpected way (and will produce a warning in the current version of Ansible.)

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

Keys in YAML are unique; when the parser encounters a second instance of the same key it throws away the first one. Since you've repeated set_fact, this is equivalent to:

  - name: Create a json object to use as tag
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

Correcting the syntax error will still result in a failure, however.

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
      tag_var_json: "{{ tag_var | to_json }}"

The arguments to set_fact have to be templated before the task runs, at which point tag_var is still undefined (because this task is defining it.)

One correct way to write this task is as two separate tasks:

  - name: Create a tag object
    set_fact:
      tag_var:
        test: thisisatest

  - name: Create a JSON string for tagging
    set_fact: 
      tag_var_json: "{{ tag_var | to_json }}"

However, set_fact isn't required at all. You can just set the var directly on the task where you use it, which is both more efficient and makes it more tightly scoped.

- name: Update instance tags
    command: oci compute instance update -c {{ compartment }} --freeform-tags "{{ tag_var | to_json }}"
  vars:
    tag_var:
      test: thisisatest
flowerysong
  • 901
  • 4
  • 6