如何循环遍历两个列表并添加条件语句以在一个条件为真时执行某些操作

How to loop through two lists & add conditional statement to execute something when one condition is true

我有一个问题,我得到了 sid 列表和数据库 open_mode,当以下两个条件满足时,我正在尝试 运行 数据库上的 sql 脚本:

  1. 数据库名称应以“1”结尾。
  2. DB Open_Mode 应该是 'READ WRITE'.

我正在使用 ansible 动态清单从主机获取 sid 并循环遍历该列表,但我无法使用这两个条件来完成我添加的条件。

- hosts: all
  gather_facts: false
  strategy: free
  tasks:
  - include_vars: roles/oracle/vars/install_vars.yaml
    vars:
     var_list:
        - script_name

  - set_fact:
      ORACLE_HOMES_DIR: "/u01/app/oracle/product"
      DB_HOME: "{{ ORACLE_HOMES_DIR }}/{{ ORACLE_VERSION }}/dbinst_1"

  - name: Copy script to host
    copy:
      src: "{{ playbook_dir }}/{{ script_name }}"
      dest: "/tmp/"
      owner: "{{ USER_ORACLE }}"
      group: "{{ GROUP_ORACLE }}"
      mode: 0755

  - name: Verify if the DB is open READ WRITE (or) not
    become_user: "{{ USER_ORACLE }}"
    environment:
      ORACLE_SID: "{{ sid }}"
      ORACLE_HOME: "{{ ORACLE_HOME }}"
    shell: "echo \"set pagesize 0\n select trim(open_mode) from v\$database;\" | {{ORACLE_HOME}}/bin/sqlplus -S / as sysdba"
    with_items: "{{ hostvars[inventory_hostname]['sid_list'] }}"
    loop_control:
      loop_var: sid
    register: om

  - name: Get list of sid that are open in READ WRITE mode
    set_fact:
      sid_list: "{{ om.results | selectattr('sid','search','1$') | map (attribute='sid') | list }}"

  - name: Get the OPEN MODE output of the sid's from the list
    set_fact:
      om_out: "{{ om.results | selectattr('stdout') | map (attribute='stdout') | list }}"

  - name: execute sql script
    become_user: "{{ USER_ORACLE }}"
    environment:
      ORACLE_SID: "{{ item.0 }}"
      ORACLE_HOME: "{{ ORACLE_HOME }}"
    shell: "{{ ORACLE_HOME }}/bin/sqlplus / as sysdba @/tmp/{{ script_name }}"
    when: item.1 == 'READ WRITE'
    with_together:
      - "{{ sid_list }}"
      - "{{ om_out }}"

我希望剧本在数据库上执行 SQL 脚本,但我收到错误提示 "conditional result was False"

TASK [Get list of sid that are open in READ WRITE mode] ****************************************************************************************************************************************************
task path: /uhome/abhi/ansible/sql_script_execute.yaml:44
ok: [dwracdb1] => {
    "ansible_facts": {
        "sid_list": [
            "abhitest1",
            "dw1"
        ]
    },
    "changed": false
}

TASK [Get the SQL output from all the sid's] ***************************************************************************************************************************************************************
task path: /uhome/abhi/ansible/sql_script_execute.yaml:48
ok: [dwracdb1] => {
    "ansible_facts": {
        "om_out": [
            "READ WRITE",
            "READ WRITE"
        ]
    },
    "changed": false
}

TASK [Print om out] ****************************************************************************************************************************************************************************************
task path: /uhome/abhi/ansible/sql_script_execute.yaml:52
ok: [dwracdb1] => (item=[u'abhitest1', u'READ WRITE']) => {
    "msg": "sid output is abhitest1 om output is READ WRITE"
}
ok: [dwracdb1] => (item=[u'dw1', u'READ WRITE']) => {
    "msg": "sid output is dw1 om output is READ WRITE"
}

TASK [execute sql script] **********************************************************************************************************************************************************************************
task path: /uhome/abhi/ansible/sql_script_execute.yaml:61
fatal: [dwracdb1]: FAILED! => {
    "msg": "The conditional check 'item.1 == 'READ WRITE'' failed. The error was: error while evaluating conditional (item.1 == 'READ WRITE'): 'item' is undefined\n\nThe error appears to have been in '/uhome/abhi/ansible/sql_script_execute.yaml': line 61, 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: execute sql script\n    ^ here\n"
}

首先,一个格式提示:将 block 上的 when 条件移到顶部,以便它控制的内容一目了然。当你把它放在底部时不明显:

- block:
  when:
    - hostvars[inventory_hostname]['sid_list'] is defined

在此任务中,您将收集多个结果(sid_list 中的每个条目一个):

- name: Verify if the DB is open READ WRITE (or) not
  become_user: "{{ USER_ORACLE }}"
  environment:
    ORACLE_SID: "{{ sid }}"
    ORACLE_HOME: "{{ ORACLE_HOME }}"
  shell: "echo \"set pagesize 0\n select trim(open_mode) from v\$database;\" | {{ORACLE_HOME}}/bin/sqlplus -S / as sysdba"
  with_items: "{{ hostvars[inventory_hostname]['sid_list'] }}"
  loop_control:
    loop_var: sid
  register: om

- name: Get list of sid that are open in READ WRITE mode
  set_fact:
    sid_list: "{{ om.results | selectattr('sid','search','1$') | map (attribute='sid') | list }}"

这就是为什么当您 运行 这个任务时,您最终会得到一个结果列表:

- name: Get the SQL output from all the sid's
  set_fact:
    om_out: "{{ om.results | selectattr(\"stdout\",'equalto','READ WRITE') | map (attribute='stdout') | list }}"

您在 debug 任务中使用 with_together 做了正确的事情:您需要这样做才能将 om_out 中的结果与 sid_list:

- name: Print om out
  debug:
   msg: sid output is {{ item.0 }} om output is {{ item.1 }}
  with_together:
    - "{{ sid_list }}"
    - "{{ om_out }}"

您在尝试执行 sql 脚本时应该做同样的事情。去掉 block,因为你只有一个任务,你不能 loop 一个块:

  - name: execute sql script
    become_user: "{{ USER_ORACLE }}"
    environment:
      ORACLE_SID: "{{ sid.0 }}"
      ORACLE_HOME: "{{ ORACLE_HOME }}"
    shell: "{{ ORACLE_HOME }}/bin/sqlplus / as sysdba @/tmp/{{ script_name }}"
    when:
      - sid.1 == 'READ WRITE'
    with_together:
      - "{{ sid_list }}"
      - "{{ om_out }}"
    loop_control:
      loop_var: sid

在此循环中,sid.0将是sid_list的值,而sid.1将是om_out的对应值。