【问题标题】:run ansible task only if tag is NOT specified仅在未指定标签时运行 ansible 任务
【发布时间】:2020-10-30 23:01:33
【问题描述】:

假设我只想在命令行提供的标记列表中的特定标记为 NOT 时运行任务,即使指定了其他标记也是如此。其中,只有最后一个在所有情况下都能按我的预期工作:

- hosts: all
  tasks:
    - debug:
        msg: 'not TAG (won't work if other tags specified)'
      tags: not TAG

    - debug:
        msg: 'always, but not if TAG specified (doesn't work; always runs)'
      tags: always,not TAG

    - debug:
        msg: 'ALWAYS, but not if TAG in ansible_run_tags'
      when: "'TAG' not in ansible_run_tags"
      tags: always

尝试使用不同的 CLI 选项,您会希望看到为什么我觉得这有点令人困惑:

ansible-playbook tags-test.yml -l HOST
ansible-playbook tags-test.yml -l HOST -t TAG
ansible-playbook tags-test.yml -l HOST -t OTHERTAG

问题:(a) 这是预期的行为吗? (b) 有没有更好的方法或我缺少的一些逻辑?

我很惊讶我不得不深入研究(未记录的,AFAICT)变量ansible_run_tags


修正:建议我发布我的实际用例。我正在使用 ansible 来驱动 Debian 系列系统上的系统更新。我试图在最后通知是否需要重新启动除非提供了标签reboot,在这种情况下会导致重新启动(并等待系统恢复)。这是相关的sn-p:

- name: check and perhaps reboot
  block:
  - name: Check if a reboot is required
    stat:
      path: /var/run/reboot-required
      get_md5: no
    register: reboot
    tags: always,reboot

  - name: Alert if a reboot is required
    fail:
      msg: "NOTE: a reboot required to finish uppdates."
    when:
      - ('reboot' not in ansible_run_tags)
      - reboot.stat.exists
    tags: always

  - name: Reboot the server
    reboot:
      msg: rebooting after Ansible applied system updates
    when: reboot.stat.exists or ('force-reboot' in ansible_run_tags)
    tags: never,reboot,force-reboot

我认为我最初的问题仍然有可取之处,但我也愿意接受完成相同功能的替代方法。

【问题讨论】:

  • 标签不应该以这种方式使用。如果您提供-t TAG,您通常希望所有标记的任务都将被执行,而不是具有“非标记”标记的任务。
  • 我知道我可能会改变标签使用规则,但我希望第一个示例 (tags: not TAG) 每次没有标签或标签的任何组合时都会运行,除了 TAG 是指定的。如果你愿意,我可以给你一个具体的例子,说明为什么我会觉得这很有用。
  • 是的,请。因为好像是XY-problem
  • 根据实际用例进行了修改。

标签: tags ansible


【解决方案1】:

为了完整起见,由于只有 @paul-sweeney 提供了任何替代解决方案,我将用我当前的最佳解决方案回答我自己的问题,并让人们挑选/投票他们最喜欢的:

---
- name: run only if 'TAG' not specified
  debug:
    msg: 'ALWAYS, but not if TAG in ansible_run_tags'
  when: "'TAG' not in ansible_run_tags"
  tags: always

【讨论】:

    【解决方案2】:

    我知道这是一个老问题,但我有类似的要求。

    这可能是最好的另一种实现方式......但是......有时它可能很有用。

    如果指定了标签,我将通过设置一个事实来实现它,然后仅在未设置该事实时才输出消息,例如:

    --- - 名称:“测试任务仅在标签缺失时运行” 主持人:全部 任务: - 名称:“如果给定标签,则禁止消息” set_fact:suppress_message=yes 标签: 重启,从不 - 名称:“消息” 调试: 味精:“你没有说‘重启’” 何时:suppress_message 未定义

    【讨论】:

    • 我喜欢这种想法,而且我确信这是个人偏好,将“行为”分散到多个任务中是我倾向于反对(倾斜?)反对的一件事。跨度>
    • 当然,不同意将其作为目标,但我不知道如何在一项任务中做到这一点,这确实符合您的要求,而且您说“我也愿意接受完成相同功能的替代方法。” :-)
    • 我们这样做是为了避免使用标签来控制某些东西时缺少的功能。当我们使用 set_fact 和标签来设置标志来控制播放的流程时,我们试图违背 ansible 的本质,它是声明性的而不是命令性的。换句话说:这样做是命令式编程,而不是声明状态。
    【解决方案3】:

    我认为我们有用于控制的状态(例如:启动、重新启动、停止)、安装状态(存在、不存在)和组件(网络服务器、数据库、...)。 Ansible 缺乏对这 3 个维度的良好分离,并且将这 3 个维度混合在一个标签系统中会导致混乱。

    例如,如果您有一个 'webserver' 和一个 'DB' 标签,您希望使用 'restart' 标签来“重启” DB 而不是 webserver。 但是如果数据库和网络服务器的“重启”任务在同一个任务文件中,并且“重启”标签与“重启”标签相同,它将无法同时启动数据库和网络服务器......

    因此,您可能必须将 webserver 和 DB 任务分隔在 2 个单独的文件中,并在包含级别使用标签。

    使用标签意味着你有一个选项树,而不是一个选项矩阵。

    我喜欢标签的概念,但不能在条件表达式中使用它这一事实使其不那么吸引人。

    我建议在角色中声明标签,但将它们映射到变量中作为首要任务。所以'restart'和'db'标签将成为我角色中的布尔变量并使用when:而不是标签:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-23
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      相关资源
      最近更新 更多