Ansible 'NoneType' object is not iterable" 在 json_query 期间出现错误

Ansible 'NoneType' object is not iterable" error when during a json_query

我的 Ansible 2.9 中有以下代码,基本上显示另一个创建 VM 的 ansible 任务的输出,并将该输出排序为可读格式:

- name: VM creation ouput
  debug:
    msg: "{{ result.stdout | from_json | json_query(jmesquery)  | sort(attribute='VM') }}"
  vars:
    jmesquery: "[].{VM: ResultName, CreatedSuccessfully: ErrorInfo.IsSuccess, PercentCompleted: Progress, CreationTimeCompleted: ReadableEndTime.DateTime}"

如果我只是创建超过 1 个(例如:2 个)VM,这会很好地工作。 但是,当我只创建 1 个 VM 时,ansible 失败并出现以下错误:

fatal: [localhost]: FAILED! => {
    "msg": "Unexpected templating type error occurred on ({{ result.stdout | from_json | json_query(jmesquery) | sort(attribute='VM') }}): 'NoneType' object is not iterable"
}

任何人都可以阐明为什么 json_query 会针对 2 个以上 VM 的输出起作用 - 而不是只针对一个 VM 的输出吗?在上面的代码中可以更改什么以使其在这两种情况下都成功?

更新(感谢提示!),这里是标准输出(定义为result.stdout):

    "stdout": {
        "ErrorInfo": {
            "CSMMessageString": "Error Code : Success ; Message :  ; Recommended Action : ",
            "CloudProblem": "",
            "Code": 0,
            "DetailedCode": 0,
            "DetailedErrorCode": "",
            "DetailedSource": 0,
            "DisplayableErrorCode": 0,
            "ErrorCodeString": "0",
            "ErrorType": 0,
            "Exception": null,
            "ExceptionDetails": "",
            "Formatter": {},
            "GetMessageFormatterHandler": null,
            "IsConditionallyTerminating": false,
            "IsDeploymentBlocker": false,
            "IsMomAlert": false,
            "IsSuccess": true,
            "IsTerminating": false,
            "MessageParameters": {},
            "MomAlertSeverity": 0,
            "Problem": "",
            "RecommendedAction": "",
            "RecommendedActionCLI": "",
            "ShowDetailedError": false
        },
        "Progress": "100%",
        "ReadableEndTime": {
            "DateTime": "Monday, June 8, 2020 10:24:02 AM",
            "DisplayHint": 2,
            "value": "/Date(1591575842677)/"
        },
        "ResultName": "MyVM"
    }

更新:我尝试了 Vladimir 的建议(非常感谢)并更改了我的代码如下:

- name: VM creation details
  debug:
    msg: "{{ result.stdout | from_json | json_query(jmesquery) }}"
  vars:
    jmesquery: "{VM: ResultName,
                     CreatedSuccessfully: ErrorInfo.IsSuccess,
                     PercentCompleted: Progress,
                     CreationTimeCompleted: ReadableEndTime.DateTime}"
  when: stdout is mapping
  ignore_errors: true

- name: VM creation details
  debug:
    msg: "{{ result.stdout | from_json | json_query(jmesquery) }}"
  vars:
    jmesquery: "[].{VM: ResultName,
                        CreatedSuccessfully: ErrorInfo.IsSuccess,
                        PercentCompleted: Progress,
                        CreationTimeCompleted: ReadableEndTime.DateTime}"
  when: stdout is not mapping
  ignore_errors: true

然而,这是失败的错误:

TASK [createvm : VM creation details] ***************************************************************************************************************************************************************************
task path: /test/server.yml:41
skipping: [myserver] => {}

TASK [createvm : VM creation details] ***************************************************************************************************************************************************************************
task path: /test/server.yml:52
fatal: [myserver]: FAILED! => {
    "msg": "the field 'args' has an invalid value ({u'msg': u'{{ result.stdout | from_json | json_query(jmesquery) }}'}), and could not be converted to an dict.The error was: No JSON object could be decoded\n\nThe error appears to be in '/test/server': line 52, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: VM creation details\n  ^ here\n"
}
...ignoring

知道我还做错了什么吗?

谢谢! J

您收到错误是因为您将一个空结果传送到 sort 过滤器,它需要一个列表。您从 json_query 表达式中得到一个空结果,因为您从 [] 开始,它指的是一个列表,但 result.stdout 是一个字典,而不是一个列表。以下产生有效结果:

    - debug:
        msg: "{{ result.stdout | from_json | json_query(jmesquery) }}"
      vars:
        jmesquery: "{VM: ResultName, CreatedSuccessfully: ErrorInfo.IsSuccess, PercentCompleted: Progress, CreationTimeCompleted: ReadableEndTime.DateTime}"

使用您在问题中提供的示例数据,生成:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "CreatedSuccessfully": true,
        "CreationTimeCompleted": "Monday, June 8, 2020 10:24:02 AM",
        "PercentCompleted": "100%",
        "VM": "MyVM"
    }
}

此处sort没有任何内容,因为结果是单个项目,而不是列表。

使用测试 mapping select 字典和列表的正确查询。例如,

    - debug:
        msg: "{{ stdout|json_query(jmesquery) }}"
      vars:
        jmesquery: "{VM: ResultName,
                     CreatedSuccessfully: ErrorInfo.IsSuccess,
                     PercentCompleted: Progress,
                     CreationTimeCompleted: ReadableEndTime.DateTime}"
      when: stdout is mapping

    - debug:
        msg: "{{ stdout|json_query(jmesquery) }}"
      vars:
        jmesquery: "[].{VM: ResultName,
                        CreatedSuccessfully: ErrorInfo.IsSuccess,
                        PercentCompleted: Progress,
                        CreationTimeCompleted: ReadableEndTime.DateTime}"
      when: stdout is not mapping

下一个选项是使用显示变量类型的过滤器 type_debug。例如,在这种情况下

    - debug:
        msg: "{{ stdout|type_debug }}"

给予

    "msg": "dict"