我如何 运行 在 ansible playbook 中使用 multi select 调查的 ansible AWX 中的条件变量进行简单循环?

How can i run simple loop with conditional variables in ansible playbook from ansible AWX with multi select survey?

目标是在多个数据库中创建用户,每个数据库都有自己的端口、ip 和 priv 集。在主机中,我只传递名称并根据名称定义所有变量。

这是来自 AWX 的变量 JSON:

{ “用户名”:“ansible”, “密码”:“123456”, “主持人”: [ "yan_local", “QA1_Backgammon” ], “权限”:“SELECT,显示视图” }

没有只有一台主机的循环部分,它工作正常

我正在尝试循环,但它不起作用

这是我的代码:

  hosts: 127.0.0.1
  vars:
     port: "{{ '3306' if host == 'yan_local' else '3310' if host == 'DEV_Backgammon' else '3320' if host == 'DEV_Spades' else '3330' if host == 'DEV_Rummy' else '3311' if host == 'QA1_Backgammon' else '3321' if host == 'QA1_Spades' else '3331' if host == 'QA1_Rummy' else '3341' if host == 'QA1_Domino' else '3351' if host == 'QA1_CasualRummy' else '3313' if host == 'QA2_Backgammon' else '3323' if host == 'QA2_Spades' else '3312' if host == 'Stage_Backgammon' else '3322' if host == 'Stage_Spades' else '3332' if host == 'Stage_Rummy' }}"
     database_name: "{{ '10.42.0.38' if host == 'yan_local' else '172.31.0.176' if host == 'DEV_Backgammon' else '172.31.0.176' if host == 'DEV_Spades' else '172.31.0.176' if host == 'DEV_Rummy' else '172.31.0.176' if host == 'QA1_Backgammon' else '172.31.0.176' if host == 'QA1_Spades' else '172.31.0.176' if host == 'QA1_Rummy' else '172.31.0.176' if host == 'QA1_Domino' else '172.31.0.176' if host == 'QA1_CasualRummy' else '172.31.0.176' if host == 'QA2_Backgammon' else '172.31.0.176' if host == 'QA2_Spades' else '172.31.0.176' if host == 'Stage_Backgammon' else '172.31.0.176' if host == 'Stage_Spades' else '172.31.0.176' if host == 'Stage_Rummy' }}"
     database: "{{ 'yan' if host == 'yan_local' else 'backgammon' if host == 'DEV_Backgammon' else 'spades' if host == 'DEV_Spades' else 'rummy' if host == 'DEV_Rummy' else 'backgammon' if host == 'QA1_Backgammon' else '3321' if host == 'spades' else 'rummy' if host == 'QA1_Rummy' else 'backgammon' if host == 'QA1_Domino' else 'rummy' if host == 'QA1_CasualRummy' else 'backgammon' if host == 'QA2_Backgammon' else '3323' if host == 'spades' else 'backgammon' if host == 'Stage_Backgammon' else 'spades' if host == 'Stage_Spades' else '3332' if host == 'rummy' }}"
     dbpassword_yan: "{{ lookup('amazon.aws.aws_secret', 'qa/ansible', region='us-west-2') | from_json | json_query('password') }}"
     dbpassword_qa: "{{ lookup('amazon.aws.aws_secret', 'qa/ansible', region='us-west-2') | from_json | json_query('db_pass') }}"
     dbpassword: "{{ lookup('vars', 'dbpassword_yan') if host == 'yan_local' else lookup('vars', 'dbpassword_qa') if host != 'yan_local' }}"
     host: []

  tasks:
  - name:  
    pip:
       name: "{{ item }}"
       state: present
    with_items:
          - PyMySQL
          - boto
          - boto3
          - botocore
          - jmespath   
          
    
  - name: Database details
    debug: 
       msg: '{{ database_name }}/{{ database }}-{{ host }}:{{ port }}'
     
  - name: Create database user with name "{{ username }}" and password "{{ password }}" 
    community.mysql.mysql_user:
        login_host: "{{ item }}"
        login_port: "{{ '3306' if host == 'yan_local' else '3310' if host == 'DEV_Backgammon' else '3320' if host == 'DEV_Spades' else '3330' if host == 'DEV_Rummy' else '3311' if host == 'QA1_Backgammon' else '3321' if host == 'QA1_Spades' else '3331' if host == 'QA1_Rummy' else '3341' if host == 'QA1_Domino' else '3351' if host == 'QA1_CasualRummy' else '3313' if host == 'QA2_Backgammon' else '3323' if host == 'QA2_Spades' else '3312' if host == 'Stage_Backgammon' else '3322' if host == 'Stage_Spades' else '3332' if host == 'Stage_Rummy' }}"
        login_user: "{{ lookup('amazon.aws.aws_secret', 'qa/ansible', region='us-west-2') | from_json | json_query('user') }}"
        login_password: "{{ dbpassword }}"
        host: '%'
        password: "{{ password }}"
        name: "{{ username }}"
        priv: "{{ 'yan' if host == 'yan_local' else 'backgammon' if host == 'DEV_Backgammon' else 'spades' if host == 'DEV_Spades' else 'rummy' if host == 'DEV_Rummy' else 'backgammon' if host == 'QA1_Backgammon' else '3321' if host == 'spades' else 'rummy' if host == 'QA1_Rummy' else 'backgammon' if host == 'QA1_Domino' else 'rummy' if host == 'QA1_CasualRummy' else 'backgammon' if host == 'QA2_Backgammon' else '3323' if host == 'spades' else 'backgammon' if host == 'Stage_Backgammon' else 'spades' if host == 'Stage_Spades' else '3332' if host == 'rummy' }}.*:{{ permissions }}"
        state: present
    when: username != "root23" and username != "root22"
    loop: "{{ database_name }}"

    
  - name: Database details
    debug: 
       msg: '{{ database_name }}/{{ database }}-{{ host }}:{{ port }}'```

I'm getting error:

```{
  "msg": "The task includes an option with an undefined variable. The error was: {{ '10.42.0.38' if host == 'yan_local' else '172.31.0.176' if host == 'DEV_Backgammon' else '172.31.0.176' if host == 'DEV_Spades' else '172.31.0.176' if host == 'DEV_Rummy' else '172.31.0.176' if host == 'QA1_Backgammon' else '172.31.0.176' if host == 'QA1_Spades' else '172.31.0.176' if host == 'QA1_Rummy' else '172.31.0.176' if host == 'QA1_Domino' else '172.31.0.176' if host == 'QA1_CasualRummy' else '172.31.0.176' if host == 'QA2_Backgammon' else '172.31.0.176' if host == 'QA2_Spades' else '172.31.0.176' if host == 'Stage_Backgammon' else '172.31.0.176' if host == 'Stage_Spades' else '172.31.0.176' if host == 'Stage_Rummy' }}: the inline if-expression on line 1 evaluated to false and no else section was defined.\n\nThe error appears to be in '/runner/project/sql-playbook.yml': line 25, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - name: Database details\n    ^ here\n",
  "_ansible_no_log": false
}```

我建议根据以下内容更改变量的定义:

---
- hosts: localhost
  gather_facts: false

  vars:
    host: QA1_Backgammon
    json_awx:
      username: ansible
      password: 123456
      host:
        - yan_local
        - QA1_Backgammon
      permissions: "SELECT,SHOW VIEW"

    dbhosts:
      - name: yan_local
        login_port: 3306
        login_host: '10.42.0.38'
        login_user: 'login'
        login_password: 'password'
        database: yan
        host: '%'
      - name: QA1_Backgammon
        login_port: 3311
        login_host: '172.31.0.176'
        login_user: 'login'
        login_password: 'password'
        database: backgammon
        host: '%'

  tasks:
    - name: Set dbh variable
      vars:
        entry: "{{ dbhosts
                    | selectattr('name','equalto',item)
                    | flatten
                    | combine({ 'permissions':json_awx.permissions,
                                'username':json_awx.username,
                                'password':json_awx.password }) }}"
      set_fact:
        dbh: "{{ dbh
                  | default([])
                  + [ entry ] }}"
      loop: "{{ json_awx.host }}"

    - name: Create database user 
      debug:
        msg:
          login_host: "{{ item.login_host }}"
          login_port: "{{ item.login_port }}"
          login_user: "{{ item.login_user }}"
          login_password: "{{ item.login_password }}"
          host: "{{ item.host }}"
          password: "{{ item.password }}"
          name: "{{ item.username }}"
          priv: "{{ item.database }}.*:{{ item.permissions }}"
      loop: "{{ dbh }}"
      when:
        - item.username != 'root22'
        - item.username != 'root23'
        - item.name == host

和输出

PLAY [localhost] **********************************************************************************

TASK [Set dbh variable] ***************************************************************************
ok: [localhost] => (item=yan_local)
ok: [localhost] => (item=QA1_Backgammon)

TASK [Create database user] ***********************************************************************
skipping: [localhost] => (item={'name': 'yan_local', 'login_port': 3306, 'login_host': '10.42.0.38', 'login_user': 'login', 'login_password': 'password', 'database': 'yan', 'host': '%', 'permissions': 'SELECT,SHOW VIEW', 'username': 'ansible', 'password': 123456})
ok: [localhost] => (item={'name': 'QA1_Backgammon', 'login_port': 3311, 'login_host': '172.31.0.176', 'login_user': 'login', 'login_password': 'password', 'database': 'backgammon', 'host': '%', 'permissions': 'SELECT,SHOW VIEW', 'username': 'ansible', 'password': 123456}) => {
    "msg": {
        "host": "%",
        "login_host": "172.31.0.176",
        "login_password": "password",
        "login_port": "3311",
        "login_user": "login",
        "name": "ansible",
        "password": "123456",
        "priv": "backgammon.*:SELECT,SHOW VIEW"
    }
}

PLAY RECAP ****************************************************************************************

答案是:

我可以对 [host] 数组中的每个项目执行 set_facts 并使用 when 条件创建另一个数组,例如:

    set_fact: 
     dbs: "{{dbs|default([]) + [{'host': {'port': 3332, 'database': 'rummy', 'database_name': '172.31.0.176', 'dbpassword': dbpassword_qa }}] }}"
    when: item == 'Stage_Rummy'    
    loop:
      "{{host}}"

  - name: set_facts
    set_fact: 
     dbs: "{{dbs|default([]) + [{'host': {'port': 3322, 'database': 'spades', 'database_name': '172.31.0.176', 'dbpassword': dbpassword_qa }}] }}"
    when: item == 'Stage_Spades'    
    loop:
      "{{host}}"

  - name: set_facts
    set_fact: 
     dbs: "{{dbs|default([]) + [{'host': {'port': 3306, 'database': 'yan', 'database_name': '10.42.0.184', 'dbpassword': dbpassword_yan }}] }}"
    when: item == 'yan_local'    
    loop:
      "{{host}}"    

然后我可以遍历新数组:

    community.mysql.mysql_user:
        login_host: "{{ item.host.database_name }}"
        login_port: "{{ item.host.port }}"
        login_user: "{{ lookup('amazon.aws.aws_secret', 'qa/ansible', region='us-west-2') | from_json | json_query('user') }}"
        login_password: "{{ item.host.dbpassword }}"
        host: '%'
        password: "{{ password }}"
        name: "{{ username }}"
        priv: '{{ item.host.database }}.*:{{ permissions }}'
        state: present
    when: username != "root" and username != "root22"
    loop:
       "{{ dbs }}"

假设我只从AWX传输yan_local,它只会触发第三个任务并首先忽略2个,或者它会包含所有3个主机,然后它会用这3个主机创建数组dbs。

{dbs|default([]) 语法将创建新数组(如果不存在空值)并添加 set_facts.

提供的值