`hostvars` 变量无法访问另一台主机的变量吗?

huangapple go评论72阅读模式
英文:

Variables of another host not accessible via the `hostvars` variable?

问题

这是您的翻译内容:

"我有一个针对两个不同主机运行的playbook。以下是这些play的部分内容:

- name: 备份数据库
  hosts: host1
  roles:
    - backup_database
  vars:
    db_backup_path: "{{ hostvars.localhost.temp_dir.path + '/' + backup_filename }}"

- name: 检查备份是否存在
  hosts: localhost
  roles:
    - aws
  tasks:
    - debug:
        var: hostvars['host1']['db_backup_path']

运行时出现了错误:

任务包含一个未定义变量的选项。错误信息是:'ansible.vars.hostvars.HostVarsVars object' 没有属性 'db_backup_path'。

显然,我在前一个play中分配了该变量,那么为什么第二个play无法访问它呢?"

英文:

I have a playbook running plays against 2 different hosts. Here are the plays:

- name: Backup database
  hosts: host1
  roles:
    - backup_database
  vars:
    db_backup_path: "{{ hostvars.localhost.temp_dir.path + '/' + backup_filename }}"

- name: Check the backup exists
  hosts: localhost
  roles:
    - aws
  tasks:
    - debug:
        var: hostvars['host1']['db_backup_path']

Running this threw an error:
> The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'db_backup_path'.

I obviously assigned that variable in the previous play, so why would the second play not be able to access it?

答案1

得分: 2

以下是翻译的内容:

这在变量文档页面中有描述:

您可以根据您希望该值具有的范围来决定在何处设置变量。Ansible 有三个主要的范围:

  • 全局:这是由配置、环境变量和命令行设置的。
  • Play:每个 Play 及其中包含的结构,包括 vars 条目(vars;vars_files;vars_prompt),角色默认值和 vars。
  • 主机:直接与主机关联的变量,例如清单、include_vars、事实或已注册任务的输出。

来源:https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#scoping-variables

因此,在您的情况下,通过在 Play 级别使用 vars,您的变量 db_backup_path 仅对该 Play 可见。

如果您希望变量对您的角色和第二个 Play 都可见,您可以在 pre_tasks 中使用 set_fact 任务。因此,在您的情况下,类似于:

- hosts: host1
  gather_fact: false

  pre_tasks:
    - set_fact:
        db_backup_path: >-
          {{ hostvars.localhost.temp_dir.path }}/{{ backup_filename }}

  roles:
    - backup_database
    

- hosts: localhost
  gather_fact: false

  roles:
    - aws

  tasks:
    - debug:
        var: hostvars.host1.db_backup_path

请注意,Ansible 团队中也有声音更喜欢使用 include_roleimport_role 而不是 role 关键字,这是 Ansible 中的一个例外。因此,您的 Playbook 也可以这样写:

- hosts: host1
  gather_fact: false    

  tasks:
    - set_fact:
        db_backup_path: >-
          {{ hostvars.localhost.temp_dir.path }}/{{ backup_filename }}

    - import_role: 
        name: backup_database
    

- hosts: localhost
  gather_fact: false

  tasks:
    - import_role: 
        name: aws

    - debug:
        var: hostvars.host1.db_backup_path

在我看来,这种写法更容易阅读,因为任务将按您阅读它们的顺序发生。

英文:

This is described in the variables documentation page:

> You can decide where to set a variable based on the scope you want
> that value to have. Ansible has three main scopes:
>
> * Global: this is set by config, environment variables and the command line
> * Play: each play and contained structures, vars entries (vars; vars_files; vars_prompt), role defaults and vars.
> * Host: variables directly associated to a host, like inventory, include_vars, facts or registered task outputs

<sup>Source: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#scoping-variables&lt;/sup&gt;

So, in your case, by using a vars at the play level, your variable db_backup_path is only visible for that play.

What you can do, if you want to variable to be accessible by both your role and your second play is to use a set_fact task in a pre_tasks.

So, in your case, something like:

- hosts: host1
  gather_fact: false

  pre_tasks:
    - set_fact:
        db_backup_path: &gt;-
          {{ hostvars.localhost.temp_dir.path }}/{{ backup_filename }}

  roles:
    - backup_database
    

- hosts: localhost
  gather_fact: false

  roles:
    - aws

  tasks:
    - debug:
        var: hostvars.host1.db_backup_path

Mind that there are also voices in the Ansible team itself that would prefer the usage of include_role and import_role over the role keyword, which is a exception in Ansible.

So, your playbook could also be written:

- hosts: host1
  gather_fact: false    

  tasks:
    - set_fact:
        db_backup_path: &gt;-
          {{ hostvars.localhost.temp_dir.path }}/{{ backup_filename }}

    - import_role: 
        name: backup_database
    

- hosts: localhost
  gather_fact: false

  tasks:
    - import_role: 
        name: aws

    - debug:
        var: hostvars.host1.db_backup_path

Which is, in my opinion, easier to read as the tasks are going to happen in the same chronological order as you read them.

huangapple
  • 本文由 发表于 2023年6月13日 02:00:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459200.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定