使用默认值处理 from_json 过滤器失败的优雅方法 [英] Elegant way to handle from_json filter failure with default value

查看:51
本文介绍了使用默认值处理 from_json 过滤器失败的优雅方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻求您的想法,以便在 from_json 过滤器失败发生时优雅地处理它.

我在 ansible 角色中有一个通用任务,我用来在 sonatype nexus 存储库管理器中调用不同的 groovy 脚本(完整角色是 在 github 上可用)

- name: 调用 Groovy 脚本 {{ script_name }}里:url: "{{ nexus_api_scheme }}://{{ nexus_api_hostname }}:{{ nexus_api_port }}\{{ nexus_api_context_path }}{{ nexus_rest_api_endpoint }}/{{ script_name }}/run"用户:'管理员'密码:{{ current_nexus_admin_password }}"标题:内容类型:文本/纯文本"方法:POSTforce_basic_auth: 是validate_certs: "{{ nexus_api_validate_certs }}"正文:{{ args | to_json }}"注册:script_run

我调用的脚本都返回一个json映射

<代码>{"name": "脚本名称""result": "任何用作常规返回语句的内容"}

注意:没有办法从groovy向这张地图添加任何其他内容,我只能在result

中将数据推回ansible

现在,我想使用 result 进一步详细说明我的脚本调用是否导致 ansible 中的错误、更改或 ok 状态.一些 groovy 脚本是完全ansible 感知"的,并且会在 result 中返回一个转义的 json 字符串,我可以用它来检查错误/更改.但是(暂时......)其他一些脚本不是可感知的"(或者我无法自己更改它们)并且将在 result 中返回一个简单的字符串(在大多数情况下没有任何可用信息).

现在我真正的问题是:如果我得到一个 json 结果,我想用它来检查失败或更改.如果它不是 json 结果,我将仅依靠 http 200 获得成功(直到可以修复脚本).

我几乎完成了以下任务:

 failed_when: >-script_run.status != 200或者(script_run.json.result | from_json | default({})).error |默认(假)|布尔值changed_when: >-(script_run.json.result | from_json | default({})).changed |默认(假)|布尔值

不幸的是,当 result 是一个简单的字符串时,from_json 会触发一个错误(Expecting value: line 1 column 1 (char 0)) 之前可以应用默认值,我的剧本就到此为止.

我目前的解决方法是在尝试读取 json 之前添加另一个条件来检查 result 是否以 { 开头,但我对此并不满意(因为json 字符串可能仍然损坏并仍然导致错误)

如果你们有关于如何使用默认值优雅地处理这个 json 解码错误或很好地检查字符串是否可以在 ansible 中解码为 json 的经验/想法,我会接受所有建议.

解决方案

我发现在 failed_when/changed_when 中编写复杂的东西很容易失控.您是否尝试过创建过滤器然后执行类似 failed_when: script_run | 的操作?my_role_failed ?

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

过滤器位于您的 ansible 角色中,位于 filter_plugins/ 下,因此分发不应该成为问题.您可以创建仅定义过滤器的空 ansible 角色,然后将它们包含在其他角色中(通过 meta/main.yml)以在那里使用.

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 (the full role is available on github)

- 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.

解决方案

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.

这篇关于使用默认值处理 from_json 过滤器失败的优雅方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆