2017-10-13 68 views
0

我有一個來自GitHub存儲庫的JSON回覆,其中包含某個版本的可能下載列表(文檔中的assets數組)。在Ansible中過濾JSON文檔

我想獲取瀏覽器下載URL當資產的namex64.AppImage結尾時。

在Ansible,過濾器是內置APON jmespath和使用它的終端工具,我可以用下面的表達式查詢的網址:

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

用下面的劇本中,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" 
} 

回答

2

在JMESPath過濾器類型錯誤的問題在issue 27299討論。

您可以使用此patched json_query.py過濾器插件。

或將雙重轉換應用於您的對象作爲解決方法:| to_json | from_json |
這會將對象轉換爲JSON(因此爲純字符串)並返回,因此json_query會將字符串視爲受支持的類型。

1
  • 循環每一個資產
  • 打印項目的瀏覽器的URL,如果它不使用JMESPathx64.AppImage

解決方案結束:

- name: Filter reply 
    debug: var=item.browser_download_url 
    with_items: "{{ json_reply.json.assets }}" 
    when: item.browser_download_url | regex_search('x64.AppImage$') 
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錯誤。這個錯誤來自the following checkjmespath庫:

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

這段代碼被稱爲點,值在你的JSON響應的數據類型爲AnsibleUnsafeText,其中作爲allowed_types[str, unicode]。我認爲從本地類型到AnsibleUnsafeText類型的值的轉換可能是由uri模塊施加的某種標準Ansible模塊行爲。我們可以解決它通過使用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`)]') }} 
+1

的問題是在這裏討論:https://github.com/ansible/ansible/issues/27299#issuecomment-331068246和解決方法就是使用'| to_json | from_json |' –

+0

@KonstantinSuvorov你提出的解決辦法是最好的解決方案,因爲它避免了循環在上述文檔。如果您發佈答案,我會接受它。 –