Ansible、YAML 和语法
Ansible, YAML, and Syntax
我正在尝试创建一个 Ansible 配置,该配置将 运行 剧本并利用单个变量文件创建具有多个项目的单个配置。我正在尝试以下语法,但它失败了。我该如何解决这个问题?
vars/main.yml
---
or1host1:
- interface: 1/1
description: or1-servertest
TRUNK: true
allowedVlans: 101-103
NVLAN: true
nativeVLAN: 101
ACCESS: false
accessVlan: none
PC: true
pcNUM: 10
- interface: 1/2
description: or1-servertest2
TRUNK: false
allowedVlans: 101-103
NVLAN: false
nativeVLAN: 101
ACCESS: true
accessVlan: none
PC: true
pcNUM: 10
templates/nxos.j2
{% for interface in or1host1 %}
interface Ethernet{{item.interface}}
description {{item.description}}
{% if item.TRUNK %}
switchport mode trunk
switchport trunk allowed vlan {{item.allowedVlans}}
spanning-tree port type edge trunk
{% if item.NVLAN %}
switchport trunk native vlan {{item.nativeVLAN}}
{% endif %}
{% endif %}
{% if item.ACCESS %}
switchport mode access
switchport access vlan {{item.accessVlan}}
spanning-tree port type edge
{% endif %}
{% if item.PC %}
channel-group {{item.pcNUM}} mode active
{% endif %}
no shut
{% endfor %}
我在 运行 运行剧本时收到以下错误。
PLAY [Generate Configuration Files] *******************************************
GATHERING FACTS ***************************************************************
ok: [localhost]
TASK: [nxos | Generate configuration files] ***********************************
fatal: [localhost] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'interface'", 'failed': True}
fatal: [localhost] => {'msg': 'One or more items failed.', 'failed': True, 'changed': False, 'results': [{'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'interface'", 'failed': True}]}
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/home/gituser/site.retry
localhost : ok=1 changed=0 unreachable=1 failed=
0
这里有几件事。首先,当您不处于 JSON 模式时,您确实必须注意缩进。当您缩进具有 4 个项目的列表项时,所有其他列表项都需要具有相同数量的空格。你的第二个项目有 6 个空格,如果没有完全松散的元素 interface: 1/2
,这将是一个语法错误,这是这里的主要问题,因为它没有意义,也没有办法解析成数据结构。在一个列表中,您可以有任意数量的列表项,但同一级别上没有松散的属性。我想你是想把它放在第二个列表项中。两者都更正后看起来像这样:
---
or1-host1:
- { interface: 1/1,
description: or1-servertest,
TRUNK: true, allowedVlans: 101-103,
NVLAN: true, nativeVLAN: 101,
ACCESS: false, accessVlan: none,
PC: true, pcNUM: 10
}
- { interface: 1/2,
description: or1-servertest2,
TRUNK: false, allowedVlans: 101-103,
NVLAN: false, nativeVLAN: 101,
ACCESS: true, accessVlan: none,
PC: true, pcNUM: 10
}
虽然 JSON 是 YML 的有效子集,但我发现严格使用 YML 语法更具可读性,它看起来像:
---
or1-host1:
- interface: 1/1
description: or1-servertest
TRUNK: true
allowedVlans: 101-103
NVLAN: true
nativeVLAN: 101
ACCESS: false
accessVlan: none
PC: true
pcNUM: 10
- interface: 1/2
description: or1-servertest2
TRUNK: false
allowedVlans: 101-103
NVLAN: false
nativeVLAN: 101
ACCESS: true
accessVlan: none
PC: true
pcNUM: 10
...
在您的模板中,您将无法像那样访问 1/1
或 1/2
。也许您想遍历模板中的接口?我不确定。
{% for interface in or1-host1 %}
...
{% endfor %}
我认为您将不得不重命名 or1-host1
,因为由于连字符,这看起来不像是有效的变量名称,or1_host1
可以。
终于明白了,看下面的例子。
~/vars/mail.yml
---
nxos:
- {hostname: testhost}
interfaces:
- {ACCESS: 'true', NVLAN: 'true', PC: 'true', TRUNK: 'true', accessVlan: '1', allowedVlans: 500-600,
desC: serverhost-1005, intF: eth1/1, nativeVLAN: '56', pcNUM: '23'}
- {ACCESS: 'true', NVLAN: 'true', PC: 'true', TRUNK: 'true', accessVlan: '1', allowedVlans: 500-600,
desC: serverhost-1006, intF: eth1/2, nativeVLAN: '56', pcNUM: '23'}
~/templates/nxos.j2
HOST: {{item.hostname}}
-----------------------------------------------------------
-----------------------------------------------------------
{%for i in interfaces %}
interface Ethernet{{i.intF}}
description {{i.desC}}
{% if i.TRUNK %}
switchport mode trunk
switchport trunk allowed vlan {{i.allowedVlans}}
spanning-tree port type edge trunk
{% if i.NVLAN %}
switchport trunk native vlan {{i.nativeVLAN}}
{% endif %}
{% endif %}
{% if i.ACCESS %}
switchport mode access
switchport access vlan {{i.accessVlan}}
spanning-tree port type edge
{% endif %}
{% if i.PC %}
channel-group {{i.pcNUM}} mode active
{% endif %}
no shut
!
{% endfor %}
配置
HOST: testhost
-----------------------------------------------------------
-----------------------------------------------------------
interface Etherneteth1/1
description serverhost-1005
switchport mode trunk
switchport trunk allowed vlan 500-600
spanning-tree port type edge trunk
switchport trunk native vlan 56
switchport mode access
switchport access vlan 1
spanning-tree port type edge
channel-group 23 mode active
no shut
!
interface Etherneteth1/2
description serverhost-1006
switchport mode trunk
switchport trunk allowed vlan 500-600
spanning-tree port type edge trunk
switchport trunk native vlan 56
switchport mode access
switchport access vlan 1
spanning-tree port type edge
channel-group 23 mode active
no shut
!
我正在尝试创建一个 Ansible 配置,该配置将 运行 剧本并利用单个变量文件创建具有多个项目的单个配置。我正在尝试以下语法,但它失败了。我该如何解决这个问题?
vars/main.yml
---
or1host1:
- interface: 1/1
description: or1-servertest
TRUNK: true
allowedVlans: 101-103
NVLAN: true
nativeVLAN: 101
ACCESS: false
accessVlan: none
PC: true
pcNUM: 10
- interface: 1/2
description: or1-servertest2
TRUNK: false
allowedVlans: 101-103
NVLAN: false
nativeVLAN: 101
ACCESS: true
accessVlan: none
PC: true
pcNUM: 10
templates/nxos.j2
{% for interface in or1host1 %}
interface Ethernet{{item.interface}}
description {{item.description}}
{% if item.TRUNK %}
switchport mode trunk
switchport trunk allowed vlan {{item.allowedVlans}}
spanning-tree port type edge trunk
{% if item.NVLAN %}
switchport trunk native vlan {{item.nativeVLAN}}
{% endif %}
{% endif %}
{% if item.ACCESS %}
switchport mode access
switchport access vlan {{item.accessVlan}}
spanning-tree port type edge
{% endif %}
{% if item.PC %}
channel-group {{item.pcNUM}} mode active
{% endif %}
no shut
{% endfor %}
我在 运行 运行剧本时收到以下错误。
PLAY [Generate Configuration Files] *******************************************
GATHERING FACTS ***************************************************************
ok: [localhost]
TASK: [nxos | Generate configuration files] ***********************************
fatal: [localhost] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'interface'", 'failed': True}
fatal: [localhost] => {'msg': 'One or more items failed.', 'failed': True, 'changed': False, 'results': [{'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'str object' has no attribute 'interface'", 'failed': True}]}
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/home/gituser/site.retry
localhost : ok=1 changed=0 unreachable=1 failed=
0
这里有几件事。首先,当您不处于 JSON 模式时,您确实必须注意缩进。当您缩进具有 4 个项目的列表项时,所有其他列表项都需要具有相同数量的空格。你的第二个项目有 6 个空格,如果没有完全松散的元素 interface: 1/2
,这将是一个语法错误,这是这里的主要问题,因为它没有意义,也没有办法解析成数据结构。在一个列表中,您可以有任意数量的列表项,但同一级别上没有松散的属性。我想你是想把它放在第二个列表项中。两者都更正后看起来像这样:
---
or1-host1:
- { interface: 1/1,
description: or1-servertest,
TRUNK: true, allowedVlans: 101-103,
NVLAN: true, nativeVLAN: 101,
ACCESS: false, accessVlan: none,
PC: true, pcNUM: 10
}
- { interface: 1/2,
description: or1-servertest2,
TRUNK: false, allowedVlans: 101-103,
NVLAN: false, nativeVLAN: 101,
ACCESS: true, accessVlan: none,
PC: true, pcNUM: 10
}
虽然 JSON 是 YML 的有效子集,但我发现严格使用 YML 语法更具可读性,它看起来像:
---
or1-host1:
- interface: 1/1
description: or1-servertest
TRUNK: true
allowedVlans: 101-103
NVLAN: true
nativeVLAN: 101
ACCESS: false
accessVlan: none
PC: true
pcNUM: 10
- interface: 1/2
description: or1-servertest2
TRUNK: false
allowedVlans: 101-103
NVLAN: false
nativeVLAN: 101
ACCESS: true
accessVlan: none
PC: true
pcNUM: 10
...
在您的模板中,您将无法像那样访问 1/1
或 1/2
。也许您想遍历模板中的接口?我不确定。
{% for interface in or1-host1 %}
...
{% endfor %}
我认为您将不得不重命名 or1-host1
,因为由于连字符,这看起来不像是有效的变量名称,or1_host1
可以。
终于明白了,看下面的例子。
~/vars/mail.yml
---
nxos:
- {hostname: testhost}
interfaces:
- {ACCESS: 'true', NVLAN: 'true', PC: 'true', TRUNK: 'true', accessVlan: '1', allowedVlans: 500-600,
desC: serverhost-1005, intF: eth1/1, nativeVLAN: '56', pcNUM: '23'}
- {ACCESS: 'true', NVLAN: 'true', PC: 'true', TRUNK: 'true', accessVlan: '1', allowedVlans: 500-600,
desC: serverhost-1006, intF: eth1/2, nativeVLAN: '56', pcNUM: '23'}
~/templates/nxos.j2
HOST: {{item.hostname}}
-----------------------------------------------------------
-----------------------------------------------------------
{%for i in interfaces %}
interface Ethernet{{i.intF}}
description {{i.desC}}
{% if i.TRUNK %}
switchport mode trunk
switchport trunk allowed vlan {{i.allowedVlans}}
spanning-tree port type edge trunk
{% if i.NVLAN %}
switchport trunk native vlan {{i.nativeVLAN}}
{% endif %}
{% endif %}
{% if i.ACCESS %}
switchport mode access
switchport access vlan {{i.accessVlan}}
spanning-tree port type edge
{% endif %}
{% if i.PC %}
channel-group {{i.pcNUM}} mode active
{% endif %}
no shut
!
{% endfor %}
配置
HOST: testhost
-----------------------------------------------------------
-----------------------------------------------------------
interface Etherneteth1/1
description serverhost-1005
switchport mode trunk
switchport trunk allowed vlan 500-600
spanning-tree port type edge trunk
switchport trunk native vlan 56
switchport mode access
switchport access vlan 1
spanning-tree port type edge
channel-group 23 mode active
no shut
!
interface Etherneteth1/2
description serverhost-1006
switchport mode trunk
switchport trunk allowed vlan 500-600
spanning-tree port type edge trunk
switchport trunk native vlan 56
switchport mode access
switchport access vlan 1
spanning-tree port type edge
channel-group 23 mode active
no shut
!