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