模板化字符串时出现模板错误:需要名称或编号。字符串:使用 Ansible 读取 JSON 时
template error while templating string: expected name or number. String: when reading JSON using Ansible
下面是我的示例this1.json
[
{
"?xml": {
"attributes": {
"encoding": "UTF-8",
"version": "1.0"
}
}
},
{
"domain": [
{
"name": "mydom"
},
{
"domain-version": "12.2.1.3.0"
},
{
"server": [
{
"name": "AdminServer"
},
{
"ssl": {
"name": "AdminServer"
}
},
{
"listen-port": "12400"
},
{
"listen-address": "mydom.host1.bank.com"
}
]
},
{
"server": [
{
"name": "myserv1"
},
{
"ssl": [
{
"name": "myserv1"
},
{
"login-timeout-millis": "25000"
}
]
},
{
"log": [
{
"name": "myserv1"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
]
}
]
},
{
"server": [
{
"name": "myserv2"
},
{
"ssl": {
"name": "myserv2"
}
},
{
"reverse-dns-allowed": "false"
},
{
"log": [
{
"name": "myserv2"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
]
},
{
"server-start": [
{
"name": "CANVL01"
},
{
"java-vendor": "Sun"
},
{
"java-home": "/web/bea/platform1221/jdk"
}
]
}
]
}
]
}
]
下面的代码能够从 log
数组中提取 file-name
元素。
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './this1.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ filename.0.log[1]['file-name'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
filename: "{{ item.server | selectattr('log', 'defined') }}"
when: item.server is defined and (item.server | selectattr('log', 'defined')) != []
在类似的行中,我希望提取 server-start
数组的 java-home
元素。下面是相同的代码:
- name: display CPATH
debug:
msg: "{{ server.0.name }} -> {{ cpath.0.'server-start'[2]['java-home'] }}"
loop: "{{ jsondata[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
cpath: "{{ item.server | selectattr('server-start', 'defined') }}"
when: item.server is defined and (item.server | selectattr('server-start', 'defined')) != []
但是,我得到这个错误:
skipping: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]})
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected name or number. String: {{ server.0.name }} -> {{ cpath.0.'server-start'[2]['java-home'] }}"}
我尝试了以下方法,但其中 none 有效:
msg: "{{ server.0.name }} -> {{ cpath.0.\"server-start\"[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.server-start[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.'[server-start]'[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.[server-start][2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.['server-start'][2]['java-home'] }}"
None 这行得通。你能推荐一下吗?
注意:这只是一个示例 json,server-start
的位置可能会有所不同。因此使用 selectattr
试试这个剧本:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file2.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ cpath[0]['server-start'][2]['java-home'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
cpath: "{{ item.server | selectattr('server-start', 'defined') }}"
when: item.server is defined and (item.server | selectattr('server-start', 'defined')) != []
结果:
skipping: [localhost] => (item={'name': 'mydom'})
skipping: [localhost] => (item={'domain-version': '12.2.1.3.0'})
skipping: [localhost] => (item={'server': [{'name': 'AdminServer'}, {'ssl': {'name': 'AdminServer'}}, {'listen-port': '12400'}, {'listen-address': 'mydom.host1.bank.com'}]})
skipping: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]})
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'reverse-dns-allowed': 'false'}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}, {'server-start': [{'name': 'CANVL01'}, {'java-vendor': 'Sun'}, {'java-home': '/web/bea/platform1221/jdk'}]}]}) => {
"msg": "myserv2 -> /web/bea/platform1221/jdk"
}
下面是我的示例this1.json
[
{
"?xml": {
"attributes": {
"encoding": "UTF-8",
"version": "1.0"
}
}
},
{
"domain": [
{
"name": "mydom"
},
{
"domain-version": "12.2.1.3.0"
},
{
"server": [
{
"name": "AdminServer"
},
{
"ssl": {
"name": "AdminServer"
}
},
{
"listen-port": "12400"
},
{
"listen-address": "mydom.host1.bank.com"
}
]
},
{
"server": [
{
"name": "myserv1"
},
{
"ssl": [
{
"name": "myserv1"
},
{
"login-timeout-millis": "25000"
}
]
},
{
"log": [
{
"name": "myserv1"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
]
}
]
},
{
"server": [
{
"name": "myserv2"
},
{
"ssl": {
"name": "myserv2"
}
},
{
"reverse-dns-allowed": "false"
},
{
"log": [
{
"name": "myserv2"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
]
},
{
"server-start": [
{
"name": "CANVL01"
},
{
"java-vendor": "Sun"
},
{
"java-home": "/web/bea/platform1221/jdk"
}
]
}
]
}
]
}
]
下面的代码能够从 log
数组中提取 file-name
元素。
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './this1.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ filename.0.log[1]['file-name'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
filename: "{{ item.server | selectattr('log', 'defined') }}"
when: item.server is defined and (item.server | selectattr('log', 'defined')) != []
在类似的行中,我希望提取 server-start
数组的 java-home
元素。下面是相同的代码:
- name: display CPATH
debug:
msg: "{{ server.0.name }} -> {{ cpath.0.'server-start'[2]['java-home'] }}"
loop: "{{ jsondata[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
cpath: "{{ item.server | selectattr('server-start', 'defined') }}"
when: item.server is defined and (item.server | selectattr('server-start', 'defined')) != []
但是,我得到这个错误:
skipping: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]})
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected name or number. String: {{ server.0.name }} -> {{ cpath.0.'server-start'[2]['java-home'] }}"}
我尝试了以下方法,但其中 none 有效:
msg: "{{ server.0.name }} -> {{ cpath.0.\"server-start\"[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.server-start[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.'[server-start]'[2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.[server-start][2]['java-home'] }}"
msg: "{{ server.0.name }} -> {{ cpath.0.['server-start'][2]['java-home'] }}"
None 这行得通。你能推荐一下吗?
注意:这只是一个示例 json,server-start
的位置可能会有所不同。因此使用 selectattr
试试这个剧本:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', './file2.json') | from_json }}"
tasks:
- name: display
debug:
msg: "{{ server.0.name }} -> {{ cpath[0]['server-start'][2]['java-home'] }}"
loop: "{{ json[1].domain }}"
vars:
server: "{{ item.server | selectattr('name', 'defined') }}"
cpath: "{{ item.server | selectattr('server-start', 'defined') }}"
when: item.server is defined and (item.server | selectattr('server-start', 'defined')) != []
结果:
skipping: [localhost] => (item={'name': 'mydom'})
skipping: [localhost] => (item={'domain-version': '12.2.1.3.0'})
skipping: [localhost] => (item={'server': [{'name': 'AdminServer'}, {'ssl': {'name': 'AdminServer'}}, {'listen-port': '12400'}, {'listen-address': 'mydom.host1.bank.com'}]})
skipping: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': [{'name': 'myserv1'}, {'login-timeout-millis': '25000'}]}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]})
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'reverse-dns-allowed': 'false'}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}, {'server-start': [{'name': 'CANVL01'}, {'java-vendor': 'Sun'}, {'java-home': '/web/bea/platform1221/jdk'}]}]}) => {
"msg": "myserv2 -> /web/bea/platform1221/jdk"
}