结果中嵌套项目的Ansible循环

时间:2019-11-27 17:54:29

标签: dictionary ansible

用ansable部署ubuntu 18.04服务器时,我遇到了以下问题:

我要安装的某些软件包既不在官方存储库中,也不在PPA中。因此,我必须从github下载并安装它们。

我检查是否已经用dpkg-query -W安装了一个软件包,并且仅在返回代码为1时运行以下安装任务。像这样:

# ripgrep
- name: "Check if ripgrep is installed"
  command: dpkg-query -W ripgrep
  register: ripgrep_dpkg_check
  failed_when: ripgrep_dpkg_check.rc > 1
  changed_when: ripgrep_dpkg_check.rc == 1

- name: "Install ripgrep from github
  apt:
     deb: "https://github.com/BurntSushi/ripgrep/releases/download/11.0.2/ripgrep_11.0.2.deb"
  when: ripgrep_dpkg_check.rc == 1

这对于单个程序包来说很好,但是对于多个程序包来说却很乏味。

所以我想到了循环遍历包含我的包裹信息的哈希:

extrapackages:
 - { name: ripgrep , version: 2.0, url: awfawf }
 - { name: fd, version: 1.4, url: awfdawf }

然后遍历它:

- name: "Check if package is installed"
  command: "dpkg-query -W {{ item.name }}"
  register: dpkg_check
  loop: "{{ extrapackages }}"

这给了我

"dpkg_check": {
    "changed": true,
        "msg": "All items completed",
        "results": [
        {
            "ansible_loop_var": "item",
            "changed": true,
            "cmd": [
                "dpkg-query",
            "-W",
            "ripgrep"
            ],
            "delta": "0:00:00.015585",
            "end": "2019-11-27 17:18:42.951019",
            "failed": false,
            "invocation": {
                "module_args": {
                    "_raw_params": "dpkg-query -W ripgrep",
                    "_uses_shell": false,
                    "argv": null,
                    "chdir": null,
                    "creates": null,
                    "executable": null,
                    "removes": null,
                    "stdin": null,
                    "stdin_add_newline": true,
                    "strip_empty_ends": true,
                    "warn": true
                }
            },
            "item": {
                "name": "ripgrep",
                "url": "awfawf",
                "version": 2.0
            },
            "rc": 0,
            "start": "2019-11-27 17:18:42.935434",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "ripgrep\t11.0.2",
            "stdout_lines": [
                "ripgrep\t11.0.2"
            ]
        },
        {
            "ansible_loop_var": "item",
            "changed": true,
            "cmd": [
                "dpkg-query",
            "-W",
            "fd"
            ],
            "delta": "0:00:00.015857",
            "end": "2019-11-27 17:18:43.137177",
            "failed": false,
            "invocation": {
                "module_args": {
                    "_raw_params": "dpkg-query -W fd",
                    "_uses_shell": false,
                    "argv": null,
                    "chdir": null,
                    "creates": null,
                    "executable": null,
                    "removes": null,
                    "stdin": null,
                    "stdin_add_newline": true,
                    "strip_empty_ends": true,
                    "warn": true
                }
            },
            "item": {
                "name": "fd",
                "url": "awfdawf",
                "version": 1.4
            },
            "rc": 0,
            "start": "2019-11-27 17:18:43.121320",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "fd\t7.4.0",
            "stdout_lines": [
                "fd\t7.4.0"
            ]
        }
    ]
}

现在,我想对所有具有rc = 1的循环项运行apt。用伪代码,我想要类似的东西:

for package in dpkg_check.results:
    if package.rc = 1:
        apt install package.item.url

像这样的事情有可能在ansible吗?

2 个答案:

答案 0 :(得分:1)

使用json_query。例如

- apt:
    name: "{{ dpkg_check.results|
              json_query('[?rc == `1`].item.url') }}"

首先使用调试对其进行测试。例如

- debug:
    msg: "{{ dpkg_check.results|
             json_query('[?rc == `1`].item.url') }}"

(未经测试)

答案 1 :(得分:1)

非常感谢@Vladimir Botka,这正是我想要的。

我的工作解决方案:

- name: "Check if extra packages are installed"                                                                                                                                                                               
  command: "dpkg-query -W {{ item.name }}"                                                                                                                                                                                    
  register: dpkg_check                                                                                                                                                                                                        
  loop: "{{ extrapackages }}"                                                                                                                                                                                                 
  failed_when: dpkg_check.rc > 1                                                                                                                                                                                              
  changed_when: dpkg_check.rc == 1                                                                                                                                                                                            

- name: "Install missing extra packages"                                                                                                                                                                                      
  apt:                                                                                                                                                                                                                        
  deb: "{{ item }}"                                                                                                                                                                                                         
  loop: "{{ dpkg_check.results|json_query('[?rc == `1`].item.url') }}"                                                                                                                                                        
  when: dpkg_check.changed