Skip to content

Instantly share code, notes, and snippets.

@beddari
Last active October 30, 2017 09:14
Show Gist options
  • Save beddari/3bd98f2e7e3aafdf0445fff3d927e15f to your computer and use it in GitHub Desktop.
Save beddari/3bd98f2e7e3aafdf0445fff3d927e15f to your computer and use it in GitHub Desktop.
Ansible THW
---
- name: test
hosts: localhost
connection: local
gather_facts: False
tasks:
# Test each key in a hash for existence, works fine ... I'll accept doing this!
- name: do something based on the existence of nested dict key nested.config.hash.key
debug: msg="{{ nested.config.hash.key }}"
when:
- nested is defined
- nested.config is defined
- nested.config.hash is defined
- nested.config.hash.key is defined
# The stuff below doesnt work ... what is the best way to set a default value?
- name: default nested dict key nested.config.hash.key to a value if it does not exist
debug: msg="{{ nested.config.hash.key | default('YOLO') }}"
# vars:
# nested:
# config:
# hash:
# key: "ftw!"
PLAY [test] **********************************************************************************************
TASK [do something based on the existence of nested dict key nested.config.hash.key] *********************
skipping: [localhost]
TASK [default nested dict key nested.config.hash.key to a value if it does not exist] ********************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error
was: 'nested' is undefined\n\nThe error appears to have been in '/home/beddari/work/smie/test.yml': line 1
8, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending lin
e appears to be:\n\n # The stuff below doesnt work ... how do I do this?\n - name: default nested di
ct key nested.config.hash.key to a value if it does not exist\n ^ here\n\nexception type: <class 'ans
ible.errors.AnsibleUndefinedVariable'>\nexception: 'nested' is undefined"}
to retry, use: --limit @/home/beddari/work/smie/test.retry
PLAY RECAP ***********************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1
@trondhindenes
Copy link

trondhindenes commented Oct 27, 2017

If you assume that if the nested object either exists (with it's entire "dict/child dict") or not at all, I would do:

---
- name: test
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    #  Test each key in a hash for existence, works fine ... I'll accept doing this!
    - name: do something based on the existence of nested dict key nested.config.hash.key
      debug: msg="{{ nested.config.hash.key }}"
      when:
        - nested is defined
        - nested.config is defined
        - nested.config.hash is defined
        - nested.config.hash.key is defined

    - name: set the nested thingy if it doesnt exist
      set_fact:
        nested: 
          config:
            hash:
              key: "YOLO"
      when: not nested is defined


    # The stuff below doesnt work ... what is the best way to set a default value?
    - name: default nested dict key nested.config.hash.key to a value if it does not exist
      debug: msg="{{ nested.config.hash.key | default('YOLO') }}"

  #vars:
  #  nested:
  #    config:
  #      hash:
  #        key: "ftw!"

@trondhindenes
Copy link

This may be a bit more robust, but it's not especially pretty:

---
- name: test
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    #  Test each key in a hash for existence, works fine ... I'll accept doing this!
    - name: do something based on the existence of nested dict key nested.config.hash.key
      debug: msg="{{ nested.config.hash.key }}"
      when:
        - nested is defined
        - nested.config is defined
        - nested.config.hash is defined
        - nested.config.hash.key is defined

#    - name: 'option 1: set the nested thingy if it doesnt exist (assumes that the whole object either is present or not)'
#      set_fact:
#        nested: 
#          config:
#            hash:
#              key: "YOLO"
#      when: not nested is defined

#Option 2: Try and access the lower attribute, and use a rescue (catch) block to fix it if it fails
    - name: Attempt and gracefull roll back demo
      block:
      - name: arcane but working wait to check each level in the dict
        set_fact:
          not_used: "{{ nested.config.hash.key }}"
        register: obj_failed
      rescue: #works as a catch block
        - name: Fix the things
          set_fact:
            nested: 
              config:
                hash:
                  key: "YOLO"



    # The stuff below doesnt work ... what is the best way to set a default value?
    - name: default nested dict key nested.config.hash.key to a value if it does not exist
      debug: 
        msg: "{{ nested.config.hash.key | default('YOLO') }}"

  #vars:
  #  nested:
  #    config:
  #      hash:
  #        key: "ftw!"

@beddari
Copy link
Author

beddari commented Oct 30, 2017

I've concluded that using structured data with Ansible just isn't going to work well. Instead, I'm going to build on lookup plugins and do the required data structures and organization BEFORE passing it to Ansible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment