Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
193 views
in Technique[技术] by (71.8m points)

How to NOT to loop in ansible if one of the variable is undefined

Here is my script , i am trying to send a message to multiple slack channels, using loops. I have defined variable inside variable.

    - name: send msg to slack
      community.general.slack:
         token: XXXXXXXXXXXX
         blocks:
           - type: section
             text:
              type: mrkdwn
              text: |-
               ****text message********
         channel: '{{ item.slack_channel }}'
         username: 'slackbot'
         parse: 'full'
      loop: "{{ slack | default([]) | selectattr('slack_channel') | list }}"
      when: inventory_hostname ==  'abc.xyz'

vars

slack:
      - slack_channel: '#mychannel'
      - slack_channel: '{{ slackchannel1|default(None) }}'
      - slack_channel: '{{ slackchannel2|default(None) }}'

slackchanne1 and slackchannel2 variable are optional, sometimes i will define value but sometimes i won't define value

What i want is -

When a script is triggered, message has to send to all slack channels, but if the variable is not defined then i don't want loop to run and get fail, incase if it run and no variable found then it should't say play failed, it has to skip that loop cause no value is defined for variable slackchannel1 and slackchannel2 , at the end play should be successful with single defined variable vlaue - slack_channel: #mychannel

error i am getting

fatal: [abc.xyz]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'msg'

The error appears to be in 'tasks/slack.yml': line 303, column 7, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


    - name: send msg to slack
      ^ here
"}
question from:https://stackoverflow.com/questions/65909300/how-to-not-to-loop-in-ansible-if-one-of-the-variable-is-undefined

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use default(None) to avoid error "'slackchannel1' is undefined"

    slack:
      - slack_channel: '#mychannel'
      - slack_channel: '{{ slackchannel1|default(None) }}'
      - slack_channel: '{{ slackchannel2|default(None) }}'

Then, select defined items

loop: "{{ slack | default([]) | selectattr('slack_channel') | list }}"

Quoting from selectattr

If no test is specified, the attribute’s value will be evaluated as a boolean.


For example, the playbook

shell> cat playbook.yml
- hosts: localhost
  vars:
    slack:
      - slack_channel: '#mychannel'
      - slack_channel: '{{ slackchannel1|default(None) }}'
      - slack_channel: '{{ slackchannel2|default(None) }}'

  tasks:
    - debug:
        msg: "{{ item.slack_channel }}"
      loop: "{{ slack | default([]) | selectattr('slack_channel') | list }}"
shell> ansible-playbook playbook.yml

gives

ok: [localhost] => (item={'slack_channel': '#mychannel'}) => 
  msg: '#mychannel'

When the variable is defined

shell> ansible-playbook playbook.yml -e slackchannel2=test

the playbook gives

ok: [localhost] => (item={'slack_channel': '#mychannel'}) => 
  msg: '#mychannel'
ok: [localhost] => (item={'slack_channel': 'test'}) => 
  msg: test

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...