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

时间:2019-05-16 20:13:27

标签: json list loops ansible ansible-inventory

我有一个问题,我得到了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脚本,但是却出现错误,提示“条件结果为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"
}

1 个答案:

答案 0 :(得分:1)

首先,这是一个格式设置提示:将when上的block条件移到顶部,以便控制。当您将其放在底部时,这并不明显:

- 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 }}"

您正在使用debugwith_together任务中执行正确的操作:您需要执行此操作才能将om_out中的结果与{{1 }}:

sid_list

在尝试执行sql脚本时,您应该做同样的事情。摆脱- name: Print om out debug: msg: sid output is {{ item.0 }} om output is {{ item.1 }} with_together: - "{{ sid_list }}" - "{{ om_out }}" ,因为您只有一个任务,而不能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_listsid.1中的对应值。