2

我有来自 GitHub 存储库的 JSON 回复,其中包含某个版本的可能下载列表(assets文档中的数组)。

我想在资产以 . 结尾时获取浏览器下载 URLnamex64.AppImage

在 Ansible 中,过滤器是构建在 apon 上的,jmespath并且使用它的终端工具,我可以使用以下表达式查询 url:

assets[?ends_with(name, 'x64.AppImage')].browser_download_url

使用以下 playbook,查询 JSON 文档并将其存储在json_reply变量中。

---
- hosts: local
  tasks:
    - name: Get list of Rambox releases
      uri:
        url: "https://api.github.com/repos/saenzramiro/rambox/releases/latest"
        body_format: json
      register: json_reply

    - name: Filter reply
      debug: URL -> "{{ item }}"
      with_items:
        - "{{ json_reply.json | json_query(json_filter) }}"
      vars:
        - json_filter: assets[?ends_with(name, 'x64.AppImage')].browser_download_url

但是,执行此操作会出现以下错误:

fatal: [localhost]: FAILED! => {
    "msg": "JMESPathError in json_query filter plugin:\nIn function ends_with(), invalid type for value: latest-mac.json, expected one of: ['string'], received: \"unknown\""
}

数组latest-mac.json中的第一个对象在哪里。assets

如何让 Ansible 遍历所有assets数组并应用我的过滤器?

PS:

如果我直接指定它而不是查询是否name以单词结尾,则过滤器起作用:

assets[?name == 'Rambox-0.5.13-x64.AppImage')].browser_download_url

JSON 示例:

{
  "url": "https://api.github.com/repos/saenzramiro/rambox/releases/8001922",
  "prerelease": false,
  "created_at": "2017-10-04T21:14:15Z",
  "published_at": "2017-10-05T01:10:55Z",
  "assets": [
    {
      "url": "https://api.github.com/repos/saenzramiro/rambox/releases/assets/4985942",
      "id": 4985942,
      "name": "latest-mac.json",
      "uploader": {
        "login": "saenzramiro",
        "id": 2694669
      },
      "browser_download_url": "https://github.com/saenzramiro/rambox/releases/download/0.5.13/latest-mac.json"
    },
    {
      "url": "https://api.github.com/repos/saenzramiro/rambox/releases/assets/4985640",
      "id": 4985640,
      "name": "Rambox-0.5.13-x64.AppImage",
      "uploader": {
        "login": "saenzramiro",
        "id": 2694669
       },
       "browser_download_url": "https://github.com/saenzramiro/rambox/releases/download/0.5.13/Rambox-0.5.13-x64.AppImage"
    }
  ],
  "tarball_url": "https://api.github.com/repos/saenzramiro/rambox/tarball/0.5.13"
}
4

3 回答 3

7

JMESPath 过滤器中的类型错误问题在issue 27299中讨论。

您可以使用此修补的 json_query.py过滤器插件。

或者将双重转换应用于您的对象作为解决方法:| to_json | from_json |.
这会将对象转换为 JSON(因此是纯字符串)并返回,因此 json_query 会将字符串视为支持的类型。

于 2017-10-14T16:17:31.557 回答
1
  • 循环遍历每个资产
  • 打印项目的浏览器 URL,如果它以x64.AppImage

不使用的解决方案JMESPath

- name: Filter reply
  debug: var=item.browser_download_url
  with_items: "{{ json_reply.json.assets }}"
  when: item.browser_download_url | regex_search('x64.AppImage$')
于 2017-10-13T22:23:04.590 回答
1

正如@helloV 所说,您可以使用 Ansible 循环来完成此操作,尽管没有理由涉及正则表达式匹配。您可以使用已在使用的相同测试:

- name: Filter reply
  debug:
    var: item.browser_download_url
  with_items: "{{ json_reply.json.assets }}"
  when: item.name.endswith('x64.AppImage')

根本问题似乎是一个 Ansible 错误。该错误来自库中的以下检查jmespath

      if actual_typename not in allowed_types:
          raise exceptions.JMESPathTypeError(
              function_name, current,
              self._convert_to_jmespath_type(actual_typename), types)

在调用此代码时,您的 json 响应中值的数据类型是AnsibleUnsafeText,其中 as allowed_typesis [str, unicode]。我认为值从原生类型到AnsibleUnsafeText类型的转换可能是模块强加的某种标准 Ansible 模块行为uri。我们可以通过使用来解决它curl,如下所示:

- name: Get list of Rambox releases
  command: >
    curl -s "https://api.github.com/repos/saenzramiro/rambox/releases/latest"
  register: json_reply

进而:

- name: Filter reply
  debug:
    var: item.browser_download_url
  with_items: >
    {{ json_reply.stdout|from_json|json_query('assets[?ends_with(name, `x64.AppImage`)]') }}
于 2017-10-14T01:29:08.103 回答