繁体   English   中英

Ansible - 如何在剧本中有条件地反转变量

[英]Ansible - how to conditionally invert variables in a playbook

我需要能够反转存储在从命令行传递给playbook的JSON文件中的变量。

这些是我设置的任务(它们除了变量之外都是相同的 ),这是一个剧本的片段:

- name: Prepare a .sql file
  delegate_to: 127.0.0.1
  mysql_db:
    name: "{{ source['database']['db_name'] }}"
    state: dump
    login_host: "{{ source['database']['host'] }}"
    login_user: "{{ source['database']['user'] }}"
    login_password: "{{ source['database']['password'] }}"
    target: test_db.sql
  when: invert is not defined

- name: Prepare a .sql file (inverted)
  delegate_to: 127.0.0.1
  mysql_db:
    name: "{{ target['database']['db_name'] }}"
    state: dump
    login_host: "{{ target['database']['host'] }}"
    login_user: "{{ target['database']['user'] }}"
    login_password: "{{ target['database']['password'] }}"
    target: test_db.sql
  when: invert is defined

所以当我执行时

ansible-playbook -i hosts playbook.yml --extra-vars "@dynamic_vars.json"

第一个任务被执行。 如果我执行

ansible-playbook -i hosts playbook.yml --extra-vars "@dynamic_vars.json" --extra-vars "invert-yes"

执行第二个任务,它接受与参数相同的哈希,但只交换目标的源(它基本上成为我的剧本中的源)。

正如你所看到的,这是一种非常简单的方法,有很多不必要的重复,我只是不喜欢它。 但是,我想不出能够在命令行恢复变量而不构建更复杂的包含逻辑的更好方法。

也许你可以建议我如何做得更好? 谢谢!

在涉及避免重复的主题时,我是YAML锚点和参考的忠实粉丝。 由于内容是动态的,你可以利用with_items ,它可以用来传递一个参数,如下所示:

- &sqldump
  name: Prepare a .sql file
  delegate_to: 127.0.0.1
  mysql_db:
    name: "{{ item['database']['db_name'] }}"
    state: dump
    login_host: "{{ item['database']['host'] }}"
    login_user: "{{ item['database']['user'] }}"
    login_password: "{{ item['database']['password'] }}"
    target: test_db.sql
  when: invert is not defined
  with_items:
    - source


- <<: *sqldump
  name: Prepare a .sql file (inverted)
  when: invert is defined
  with_items:
    - target

第二个任务是第一个任务的完美克隆,然后覆盖namecondition和循环with_items以传递target而不是source


在阅读了@ydaetskcoR的答案之后,听起来您在某些情况下需要使用来自其中一个或另一个字典的数据。 也许在那种情况下,根据invert参数来定义var全局是有意义的。 您的vars文件可能如下所示:

---

source:
  database: ...
  db_name: ...

target:
  database: ...
  db_name: ...

data: "{{ target if invert is defined else source }}"

然后,您可以在所有任务中使用data ,而无需进一步处理条件。

- name: Prepare a .sql file
  delegate_to: 127.0.0.1
  mysql_db:
    name: "{{ data['database']['db_name'] }}"
    state: dump
    login_host: "{{ data['database']['host'] }}"
    login_user: "{{ data['database']['user'] }}"
    login_password: "{{ data['database']['password'] }}"
    target: test_db.sql

当然,这样你就有了一个固定的任务名称,它不随你传递的参数而改变。

如果您尝试执行相同的操作但只想根据主机/组指定不同的变量,那么更好的方法可能是将这些变量设置为主机/组变量并将其作为单个任务运行。

如果我们设置我们的库存文件有点像这样:

[source_and_target-nodes:children]
source-nodes
target-nodes

[source-nodes]
source database_name='source_db' database_login_user='source_user' database_login_pass='source_pass'

[target-nodes]
target database_name='target_db' database_login_user='target_user' database_login_pass='target_pass'

然后我们可以在source_and_target-nodes处定位任务,如下所示:

- name: Prepare a .sql file
  hosts: source_and_target-nodes
  mysql_db:
    name: "{{ database_name }}"
    state: dump
    login_host: "{{ inventory_hostname }}"
    login_user: "{{ database_login_user }}"
    login_password: "{{ database_login_pass }}"
    target: test_db.sql

如果您需要在问题中使用delegate_to ,那么您将无法轻松访问其他主机的主机变量,但如果您只是需要在本地运行该游戏,则可以在主机中将ansible_connection设置为local / group vars或设置connection: local播放中的connection: local

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM