使用带有starts_with的Ansible中的json_query过滤器时的JMESPathTypeError

时间:2017-06-14 13:24:53

标签: ansible boto3

我正在尝试过滤来自Ansible的boto3的结果。

当我在没有“[?starts_with(...)]”的结果上使用json查询时,它运行良好,但在添加starts_with语法时:

{u'boto3': u'1.4.4', u'state_machines': 
[{u'state_machine_arn': u'<state machine arn 1>', u'name': u'hello_world_sfn', u'creation_date': u'2017-05-16 14:26:39.088000+00:00'}, 
{u'state_machine_arn': u'<state machine arn 2>', u'name': u'my_private_sfn', u'creation_date': u'2017-06-08 07:25:49.931000+00:00'}, 
{u'state_machine_arn': u'<state machine arn 3>', u'name': u'alex_sfn', u'creation_date': u'2017-06-14 08:35:07.123000+00:00'}], 
u'changed': True}" }

为了过滤结果:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: JMESPathTypeError: In function contains(), invalid type for value: <lamdba_name>, expected one of: ['array', 'string'], received: "unknown" fatal: [localhost]: FAILED!
=> {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}

我希望获得第一个state_machine_arn值:“state machine arn 1”

但相反,我得到了例外:

var packageGroupSchema = new Schema(
    {
        packageGroupCode: { type: String, required: true, unique: true},
        packageGroupName: { type: String, required: true },
        description: String,
        **moduleId: { type: Schema.Types.ObjectId, required: true },**
        active: Boolean,
        createdDate: { type: Date, default: Date.now},
        lastUpdatedDate: { type: Date, default: Date.now}
    },
    { 
        toJSON: { virtuals: true }
    }
);

packageGroupSchema.virtual('moduleData', {
  ref: 'Module', 
  localField: 'moduleId',
  foreignField: '_id',
  justOne: true
});

可能是什么问题?

2 个答案:

答案 0 :(得分:2)

问题是json_query过滤器需要获得带有ascii字符串的字典,但是你提供的字符串是unicode字符串(请注意输入中的u'blabla')。

这是json_query的一个问题,显然已经在Ansible 2.2.1中引入了(尽管还不是很清楚),这里有一些更多细节: https://github.com/ansible/ansible/issues/20379#issuecomment-284034650

我希望这在未来的版本中得到修复,但是现在这是一个对我们有用的解决方法:

"{{ results | to_json | from_json | json_query(jmespath_query) }}"

其中jmespath_query是包含starts_with查询的变量。 这种往返于json的技巧将unicode字符串转换为ASCII字符串:)

答案 1 :(得分:0)

除了在各处编写| to_json | from_json | json_query(…)之外,您还可以通过创建以下json_query文件来猴子补丁Ansible的filter_plugins/json_bug_workaround.py过滤器:

import json
from ansible.parsing.ajson import AnsibleJSONEncoder
from ansible.plugins.filter.json_query import json_query 

class FilterModule(object):
    def filters(self):
        return {
            # Workaround for Unicode bug https://stackoverflow.com/a/44547305
            'json_query': lambda data, query: json_query(
                json.loads(json.dumps(data, cls=AnsibleJSONEncoder)),
                query
            ),
        }

然后,您可以自然地使用| json_query(…)。此填充程序相当于为您呼叫| to_json | from_json

您可以将其放在您的角色(roles/role_name/filter_plugins/json_bug_workaround.py)内或Ansible's plugin search path中的任何位置。