Ansible根据特定条件过滤包含数据以运行任务

85次阅读
没有评论

问题描述

有一个包含多个yml文件的目录,这些文件设置了要部署的不同软件实例的参数。目录结构如下所示:

instance1:
  ip: 127.0.0.3
  servername: mycoolserver
  instancetype: testing

这些参数被使用include_vars加载到一个名为instances的变量中。为了在这些实例上执行不同的任务,主要的site.yml文件中有类似以下结构的代码块:

- name: Start software container 1
  include_tasks: software-container-1.yml
  loop: "{{ instances | flatten(levels=1) }}"

这样做的设计(继承而来,所以请不要对我太苛责)指定目录中可以有多个实例参数的文件,每个实例类型有多个文件,且有不同的实例。这种设计的主要目的是不需要事先指定有多少个实例,因为Ansible是在服务器上从一个共同的playbook运行的,而不是从一个中央服务器登录到不同的服务器,这在环境的安全设计上是不可能的。

现在,用户想要筛选instances变量,以仅包含特定instancetype(例如testing)的所有项。

解决方案

请注意以下操作可能受到版本差异的影响。

有几种方法可以实现根据特定条件筛选instances变量的目的。下面将介绍两种选项:设置新的事实(fact)或在任务中进行筛选。以下是针对这两种选项的解决方案。

方案1:使用json_query过滤器

如果你想要使用较为简洁的方法,可以考虑使用json_query过滤器。这需要使用JMESPath查询语法,它可以帮助你对JSON或类似JSON结构的数据进行筛选和提取。

  1. 修改你的site.yml文件,将loop部分修改如下:
loop: "{{ instances | json_query(query) }}"
  1. 在你的playbook的变量部分,定义一个新的变量,例如filtered_instances_query,并将其设置为你想要的筛选条件。例如,对于只想保留instancetypetesting的实例,可以这样设置:
filtered_instances_query: "[?instancetype=='testing']"
  1. 在任务的前面,使用set_fact模块创建一个新的变量,将过滤后的结果赋给这个变量:
- name: Set filtered instances variable
  set_fact:
    filtered_instances: "{{ instances | json_query(filtered_instances_query) }}"

方案2:在循环内部进行筛选

另一种方法是在循环内部筛选实例。这种方法比较直接,但可能需要在每个任务中都进行筛选,稍显繁琐。

在你的site.yml中,可以这样做:

- name: Start software container 1
  include_tasks: software-container-1.yml
  loop: "{{ instances }}"
  when: item.instancetype == 'testing'

这会在循环内部根据instancetype进行筛选,只有当instancetypetesting时才执行任务。

无论你选择哪种方法,都可以根据你的偏好和代码组织需求来决定。希望这些解决方案能够帮助你实现根据特定条件筛选instances变量的目标。

请注意,上述示例中的代码仅供参考,可能需要根据你的实际需求进行适当的修改。


这些就是根据你的问题描述所提供的解决方案。根据你的实际情况,选择合适的方法来实现对instances变量的筛选。希望这些解决方案能够帮助你完成你的任务。如果你有任何进一步的问题或需要更多的帮助,请随时提问。

正文完