简体   繁体   English

Ansible - 从文件中读取字典项并与循环一起使用

[英]Ansible - Read dict items from file and use with loop

I am trying to take this effort a little further and want to download multiple files from BitBucket having different parent directories.我试图把这种努力远一点,想从不同的父目录到位桶下载多个文件。 So I am trying to use the below script.所以我试图使用下面的脚本。

I want to put the mappings in a separate file and read it into the script, so that at subsequent times, I can just update that file, without having to touch the script.我想将映射放在一个单独的文件中并将其读入脚本,以便在随后的时间,我可以只更新该文件,而无需触及脚本。

- name: Download connector scripts
  get_url:
    url: "http://bbserver:7990/projects/myproject/repos/myrepo/raw/{{ item.filename }}?at=refs%2Fheads%2Fmaster"
    dest: "{{ item.dest }}"
    url_username: '{{ bb_username }}'
    url_password: '{{ bb_password }}'
    force_basic_auth: yes
  loop: "{{ lookup('file', 'scriptnamesnpaths.txt').splitlines() }}"
  register: showdlstatus
  become: yes
  become_user: '{{ bb_username }}'
- debug: var=showdlstatus

And my scriptnamesnpaths.txt looks like this我的scriptnamesnpaths.txt看起来像这样

{filename: 'scripts/dir1/script1.sh',      dest: "/scripts/dir1/"}
{filename: 'scripts/dir1/script2.sh',      dest: "/scripts/dir1/"}
{filename: 'scripts/dir2/script3.sh',      dest: "/scripts/dir2/"}
{filename: 'releases/file1.json',          dest: "/scripts/releases/"}
{filename: 'releases/file2.json',          dest: "/scripts/releases/"}

I basically want to download different scripts from different paths in bitbucket to different locations on the server.我基本上想从 bitbucket 中的不同路径下载不同的脚本到服务器上的不同位置。

The error I am getting with this construct is我用这个构造得到的错误是

 {"msg": "The task includes an option with an undefined variable. 
 The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'filename'

Which part am I doing wrong or missing?我做错或遗漏了哪一部分? I also tried with loop: "{{ lookup('dict', 'scriptnamesnpaths.txt').splitlines() }}"我也尝试过loop: "{{ lookup('dict', 'scriptnamesnpaths.txt').splitlines() }}"

But get error about dict definition.但是得到关于 dict 定义的错误。

Any pointers or help is appreciated.任何指针或帮助表示赞赏。

Thank you谢谢

Rather than using a file lookup, it might be easiest just to make a group_vars file so that Ansible reads it for you automatically.与其使用file查找, 不如创建一个group_vars文件,以便 Ansible 自动为您读取它可能是最简单的。

That is, if you create a file groups_vars/all.yml with this content:也就是说,如果您使用以下内容创建文件groups_vars/all.yml

connector_scripts:
  - {filename: 'scripts/dir1/script1.sh',      dest: "/scripts/dir1/"}
  - {filename: 'scripts/dir1/script2.sh',      dest: "/scripts/dir1/"}
  - {filename: 'scripts/dir2/script3.sh',      dest: "/scripts/dir2/"}
  - {filename: 'releases/file1.json',          dest: "/scripts/releases/"}
  - {filename: 'releases/file2.json',          dest: "/scripts/releases/"}

You could then write your task like this:然后你可以这样写你的任务:

- name: Download connector scripts
  get_url:
    url: "http://bbserver:7990/projects/myproject/repos/myrepo/raw/{{ item.filename }}?at=refs%2Fheads%2Fmaster"
    dest: "{{ item.dest }}"
    url_username: '{{ bb_username }}'
    url_password: '{{ bb_password }}'
    force_basic_auth: yes
  loop: "{{ connector_scripts }}"
  register: showdlstatus
  become: yes
  become_user: '{{ bb_username }}'

If you really want to use a file lookup, you'll need to deal with the fact that for each iteration of your loop , the variable item is a string .如果你真的想用一个file查找,你需要处理的事实,你的每一次迭代loop中,变量item是一个字符串 You can't ask for something like item.filename because a string doesn't have an attribute filename (which is the source of the error you're seeing).您不能要求诸如item.filename类的item.filename因为字符串没有属性filename (这是您看到的错误的来源)。 You would need to de-serialize each line before using it, for example:您需要在使用前反序列化每一行,例如:

- name: Download connector scripts
  get_url:
    url: "http://bbserver:7990/projects/myproject/repos/myrepo/raw/{{ (item|from_yaml).filename }}?at=refs%2Fheads%2Fmaster"
    dest: "{{ (item|from_yaml).dest }}"
    url_username: '{{ bb_username }}'
    url_password: '{{ bb_password }}'
    force_basic_auth: yes
  loop: "{{ connector_scripts }}"
  register: showdlstatus
  become: yes
  become_user: '{{ bb_username }}'

You could simplify that a bit by moving the from_yaml call to a vars section so you only have to do it once:您可以通过将from_yaml调用移动到vars部分来稍微简化一下,这样您只需执行一次:

- name: Download connector scripts
  get_url:
    url: "http://bbserver:7990/projects/myproject/repos/myrepo/raw/{{ item_converted.filename }}?at=refs%2Fheads%2Fmaster"
    dest: "{{ item_converted.dest }}"
    url_username: '{{ bb_username }}'
    url_password: '{{ bb_password }}'
    force_basic_auth: yes
  vars:
    item_converted: "{{ item|from_yaml }}"
  loop: "{{ connector_scripts }}"
  register: showdlstatus
  become: yes
  become_user: '{{ bb_username }}'

...but I think it's much easier to simply use the first solution and drop a file into group_vars . ...但我认为简单地使用第一个解决方案并将文件放入group_vars

Is there a particular reason for favoring putting the filenames/destinations in a script rather than the task?是否有特别的理由倾向于将文件名/目标放在脚本中而不是任务中? This would be a simplified version of the task with vars included in it:这将是包含 vars 的任务的简化版本:

- name: Download connector scripts
  get_url:
    url: "http://example.com/{{ item.key }}"
    dest: "{{ item.value }}"
  loop: "{{ files | dict2items }}"
  vars:
    files:
      filename1: "/path/to/dest/dir/"
      filename2: "/path/to/dest/dir/"

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

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