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