• Playbook条件语句


    Playbook条件语句

    • 在有的时候play会依赖于变量,fact或者前一个任务的执行结果,或者基于上一个任务执行返回的结果而决定如何执行后续的任务,这个时候就需要用到条件判断
    • 应用场景
      • 某个任务要求运行的主机最少要有1G内存或者10G的磁盘
      • 捕获一个命令的输出,根据输出来触发不同的任务
      • 根据不同的操作系统来定义不同的任务
      • 根据目标主机的CPU来定义调优参数

    1. when的基本使用

    • 在ansible中,使用的条件判断是when

    1.1 when的基本示例

    [ansible@master ansible]$ vim when-rhel.yaml
    - name: install vim
    hosts: test
    tasks:
    - name: install vim via yum
    yum:
    name: vim
    state: present
    when: ansible_os_family == "RedHat"
    • ansible_os_family 这个变量可以在setup收集的信息里面找到

      为什么需要用到判断呢?

      因为只有在红帽系的发行版中,包管理工具使用的是yum,而在debian的系列中,使用的apt,所以如果你管理的主机有红帽系的,也有debian系的,那么就需要写一个判断来让他们分开执行

    [ansible@master ansible]$ ansible-playbook when-rhel.yaml
    TASK [install vim via yum] *****************************************************
    ok: [192.168.200.200]
    ok: [192.168.200.210]
    PLAY RECAP *********************************************************************
    192.168.200.200 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    192.168.200.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

    通过这个回显我们可以得知,任务他是要执行的,但是由于我们的系统上有vim,所以他没有发生改变,显示的是ok

    那我们将ansible_os_family == "RedHat" 改为Debian看看呢

    - name: install vim
    hosts: test
    tasks:
    - name: install vim via yum
    yum:
    name: vim
    state: present
    when: ansible_os_family == "Debain"

    执行剧本

    [ansible@master ansible]$ ansible-playbook when-rhel.yaml
    PLAY [install vim] *************************************************************
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.200.200]
    ok: [192.168.200.210]
    TASK [install vim via yum] *****************************************************
    skipping: [192.168.200.210]
    skipping: [192.168.200.200]
    PLAY RECAP *********************************************************************
    192.168.200.200 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
    192.168.200.210 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

    可以看到,他的状态是skipping,也就说跳过的意思,因为他没有跟条件语句匹配上,所以他不会执行

    1.2比较运算符

    在ansible中,支持以下比较运算符

    • ==:比较两个对象是否相等
    • !=:比较两个对象是否不相等
    • >:比较两个对象的大小
    • <
    • >=
    • <=

    1.3 比较运算符示例

    • when: ansible_machine == "x86_64"
    • when: ansible_memtotal_mb >= 1024

    1.4 逻辑运算符

    • and: 逻辑与,当两边都为真时为真
    • or:逻辑或,当有一边为真时为真
    • not:逻辑否,对表达式取反
    • ():可以将多个语句写到一个括号里面,括号内的表达式都是逻辑与的关系

    1.5 逻辑运算符示例

    • when: ansible_distribution == "openEuler" or nsible_distribution == "RedHat"
      • 表示判断操作系统是openEuler或者RedHat任意一者都行
    • when: ansible_machine == "x86_64" and ansible_memtotal_mb > 1024
      • 表示架构必须是x86并且机器的内存得大于1024m才行

    2. 条件判断与block

    • 假设现在的场景是这样的,操作系统刚装完,现在需要你对这些系统进行一些初始化的操作,比如安装一些必要的软件包,关闭防火墙,selinux,但是现在有一个问题,就是这些操作系统并不一定都是红帽,可能还有Debian,Debian上面的操作跟红帽的操作就又不一样了啊

    • 如果我们按照之前的思维,那么就是安装软件包的时候有一个判断语句,关闭selinux又是一个判断语句,这样下来我们就需要写很多一模一样的判断语句了,能不能只写一条,这条判断语句过了之后直接执行对应的一系列任务呢? 是可以的

    2.1 block示例

    [ansible@master ansible]$ vim block.yaml
    - name: block
    hosts: test
    tasks:
    - block:
    - name: install software
    yum:
    name: vim
    state: present
    - name: disable Selinux
    selinux:
    policy: targeted
    state: disabled
    - name: disabled firewalld
    systemd:
    name: firewalld
    state: stopped
    enabled: no
    when: ansible_os_family == "RedHat"
    - block:
    - name: install software
    apt:
    name: vim
    state: present
    when: ansible_os_family == "Debian"

    通过加上block之后,在block里面定义的任务就是一个整体了,那么条件判断也是针对这个block的,如果条件判断返回为真之后,那么这个block里面的所有任务都会被执行

    • 我们的第一个block就是来判断是否为红帽系的系统,如果是的话那么就会执行那3个任务
    • 如果我们使用的系统是Debian系列的话,那么就会执行第二个block了

    2.2 rescue

    block除了能和when一起使用之外,还可以和rescue一起使用,作用是能做错误处理

    [ansible@master ansible]$ vim rescue.yaml
    - name: rescue
    hosts: test
    tasks:
    - block:
    - name: test file exist
    shell: "ls /aaa.txt"
    rescue:
    - name: print file is not exist
    debug:
    msg: 'file is not exist'

    我们的文件 /aaa.txt是不存在的,所以他执行这个任务会报错,但是正常情况下,举报报错就会停止执行了,后面的任务也就不会有输出了,rescue就是来做错误处理的,如果这里面有错误的话,他不会影响剧本执行,反而还会触发resue字段里的任务

    [ansible@master ansible]$ ansible-playbook rescue.yaml
    PLAY [rescue] ******************************************************************
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.200.200]
    ok: [192.168.200.210]
    TASK [test file exist] *********************************************************
    fatal: [192.168.200.210]: FAILED! => {"changed": true, "cmd": "ls /aaa.txt", "delta": "0:00:00.002396", "end": "2024-06-21 10:20:25.001243", "msg": "non-zero return code", "rc": 2, "start": "2024-06-21 10:20:24.998847", "stderr": "ls: cannot access '/aaa.txt': No such file or directory", "stderr_lines": ["ls: cannot access '/aaa.txt': No such file or directory"], "stdout": "", "stdout_lines": []}
    fatal: [192.168.200.200]: FAILED! => {"changed": true, "cmd": "ls /aaa.txt", "delta": "0:00:01.003922", "end": "2024-06-21 10:20:25.992768", "msg": "non-zero return code", "rc": 2, "start": "2024-06-21 10:20:24.988846", "stderr": "ls: cannot access '/aaa.txt': No such file or directory", "stderr_lines": ["ls: cannot access '/aaa.txt': No such file or directory"], "stdout": "", "stdout_lines": []}
    TASK [print file is not exist] *************************************************
    ok: [192.168.200.210] => {
    "msg": "file is not exist"
    }
    ok: [192.168.200.200] => {
    "msg": "file is not exist"
    }
    PLAY RECAP *********************************************************************
    192.168.200.200 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
    192.168.200.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0

    我们可以看到,执行命令报错了,但是任务剧本没有被打断,后面还输出了file is not exist

    那我们来将文件改为存在的,看看rescue还会执行吗

    [ansible@master ansible]$ vim rescue.yaml
    - name: rescue
    hosts: test
    tasks:
    - block:
    - name: test file exist
    shell: "ls /etc/passwd"
    rescue:
    - name: print file is not exist
    debug:
    msg: 'file is not exist'

    执行这个剧本

    [ansible@master ansible]$ ansible-playbook rescue.yaml
    [ansible@master ansible]$ ansible-playbook rescue.yaml
    PLAY [rescue] ******************************************************************
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.200.210]
    ok: [192.168.200.200]
    TASK [test file exist] *********************************************************
    changed: [192.168.200.200]
    changed: [192.168.200.210]
    PLAY RECAP *********************************************************************
    192.168.200.200 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    192.168.200.210 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

    我们可以看到,这个任务执行成功了,他没有输出rescue里面定义的任务

    也就是说,只有block里面的任务出错的时候rescue才会接管任务,平时是不会执行的

    2.3 always

    当block执行失败,rescue才会执行;而无论block失败还是成功,always里面的任务都将会执行

    - name: always
    hosts: test
    tasks:
    - block:
    - name: success
    debug:
    msg: "this is success task"
    - name: faild
    debug:
    msg: "{{ aaa }}"
    rescue:
    - name: print faile
    debug:
    msg: "Task failure"
    always:
    - name: print always
    debug:
    msg: "This task is always performed"

    这个剧本定义了一个成功的任务,一个失败的任务,当有任务失败的时候会触发rescue,当所以任务执行完之后会执行always

    [ansible@master ansible]$ ansible-playbook always.yaml
    [ansible@master ansible]$ ansible-playbook always.yaml
    PLAY [always] ******************************************************************
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.200.210]
    ok: [192.168.200.200]
    TASK [success] *****************************************************************
    ok: [192.168.200.210] => {
    "msg": "this is success task"
    }
    ok: [192.168.200.200] => {
    "msg": "this is success task"
    }
    TASK [faild] *******************************************************************
    fatal: [192.168.200.210]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'aaa' is undefined\n\nThe error appears to be in '/home/ansible/ansible/always.yaml': line 8, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n msg: \"this is success task\"\n - name: faild\n ^ here\n"}
    fatal: [192.168.200.200]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'aaa' is undefined\n\nThe error appears to be in '/home/ansible/ansible/always.yaml': line 8, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n msg: \"this is success task\"\n - name: faild\n ^ here\n"}
    TASK [print faile] *************************************************************
    ok: [192.168.200.210] => {
    "msg": "Task failure"
    }
    ok: [192.168.200.200] => {
    "msg": "Task failure"
    }
    TASK [print always] ************************************************************
    ok: [192.168.200.210] => {
    "msg": "This task is always performed"
    }
    ok: [192.168.200.200] => {
    "msg": "This task is always performed"
    }
  • 相关阅读:
    第八章《Java高级语法》第8节:Java可变参数
    golang学习笔记——Map
    LQ0150 回文日期【枚举】
    Flink的CheckPoint机制
    请问签过版权转让 协议后,接下来是不是要在 author gateway 等待?
    【题解】NowCoder BC64 牛牛的快递
    无代码人工智能:它是什么,它为什么重要?(Noogata)
    [云原生案例2.2 ] Kubernetes的部署安装 【单master集群架构 ---- (二进制安装部署)】网络插件部分
    electron打包时资源下载失败cannot resolve xxx/30.0.9/electron-v30.0.9-win32-ia32.zip
    【会议征稿通知】2024第四届神经网络、信息与通信工程国际学术会议(NNICE 2024)
  • 原文地址:https://www.cnblogs.com/fsdstudy/p/18260065