Elegant way to handle from_json filter failure wit

2019-09-03 04:45发布

问题:

I'm seeking for your ideas to elegantly handle a from_json filter failure when it happens.

I have a generic task in an ansible role that I use to call different groovy script in sonatype nexus repository manager

- name: Calling Groovy script {{ script_name }}
  uri:
    url: "{{ nexus_api_scheme }}://{{ nexus_api_hostname }}:{{ nexus_api_port }}\
      {{ nexus_api_context_path }}{{ nexus_rest_api_endpoint }}/{{ script_name }}/run"
    user: 'admin'
    password: "{{ current_nexus_admin_password }}"
    headers:
      Content-Type: "text/plain"
    method: POST
    force_basic_auth: yes
    validate_certs: "{{ nexus_api_validate_certs }}"
    body: "{{ args | to_json }}"
  register: script_run

The scripts I call all return a json map

{
"name": "name of the script"
"result": "whatever was used as a groovy return statement"
}

Note: there is no way to add anything else to this map from groovy, I can only push data back to ansible in the result

Now, I want to use result to further detail if my script call leads to an error, a change or an ok status in ansible. Some groovy scripts are fully "ansible aware" and will return in result an escaped json string I can use to check for error/changes. But (for time being...) some other scripts are not "ansible aware" (or I cannot change them myself) and will return in result a simple string (without any usable information in most cases).

Now my real problem: If I get a json result I want to use it to check for failure or change. If its not a json result, I'll just rely on the http 200 for a success (until the script can be fixed).

I was almost there with the following options to my task:

  failed_when: >-
    script_run.status != 200
    or
    (script_run.json.result | from_json | default({})).error | default(false) | bool
  changed_when: >-
    (script_run.json.result | from_json | default({})).changed | default(false) | bool

Unfortunatelly, when result is a simple string, from_json will fire an error (Expecting value: line 1 column 1 (char 0)) before the default can be applied and my playbook ends there.

My current workaround is to add another condition to check if result starts with a { before trying to read json but I'm not really happy with this (as the json string might still be corrupted and still lead to an error)

If any of you have experience/idea on how to gracefully handle this json decode error with a default value or to nicelly check if a string can be decoded as json in ansible, I'll take all suggestions.

回答1:

(this is copy/pasted from the comments above)

i found out that writing complex stuff in failed_when/changed_when can get easily out of hand. Have you tried creating a filter and then do something like failed_when: script_run | my_role_failed ?

https://gist.github.com/tuxfight3r/37048ba536575277f5f4d26813d69489

filters live inside your ansible role, under filter_plugins/, so distribution shouldnt be an issue. You can go as far as creating empty ansible roles that only define filters and then include them in other roles (through meta/main.yml) to be used there.



标签: ansible