Search code examples
ansiblejson-query

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


I have the following code in my Ansible 2.9 to basically display the output of another ansible task that creates VMs and order that output into a readable format:

- 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}"

This works fine if I'm just creating more than 1 (eg: 2) VMs. However, when I create just 1 VM, the ansible fails with the following error:

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"
}

Can anyone shed a light on why the json_query would work against the output of more than 2 VMs - but not against just the one? And what can be changed in the code above to make it successful in both cases?

Update (thanks for the tip!), here is the stdout (defined as 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"
    }

Update: I tried the suggestion by Vladimir (thanks so much) and changed my code as below :

- 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

However this is failing with an error :

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

Any idea what else I could be doing wrong..?

Thanks! J


Solution

  • Use test mapping to select the correct query for a dictionary and a list. For example,

        - 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
    

    Next option is to use the filter type_debug that shows the type of a variable. For example, in this case

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

    gives

        "msg": "dict"