Dans Article précédent, comparez les données JSON prédéfinies avec les données JSON définies pour voir si les paramètres sont reflétés comme prévu. fait. Cette fois, je voudrais fusionner deux données JSON à l'aide d'Ansible. Plus précisément, avant de configurer les paramètres d'interface Cisco IOS-XE dans RESTCONF, essayez de fusionner les paramètres existants avec des paramètres supplémentaires.
J'ai utilisé CSR1000v 16.9.3 de IOS XE sur le code recommandé CSR de Cisco DevNet Sandbox. C'était. J'ai installé et utilisé Ansible 2.9.2 sur l'environnement virtuel venv de Python 3.6.8.
Importé JSONMerge en tant que plug-in de filtre Ansible. Il s'agit d'un module basé sur Python qui fusionne la tête (données JSON supplémentaires) avec la base (données JSON d'origine) et génère le résultat.
Vous pouvez spécifier la méthode de fusion dans les stratégies de fusion. S'il n'est pas spécifié, ce sera «écraser» et l'ancienne valeur sera écrasée. En fait, je pense qu'il y a de nombreux cas où vous voulez ajouter des éléments aux données du tableau [〇, △]
. Dans ce cas, vous pouvez sélectionner ʻappend (simplement ajouter) ou ʻarrayMergeById
(fusionner si la valeur de clé spécifique dans l'élément est la même, en ajouter une nouvelle).
Un exemple sera présenté plus tard, mais vous pouvez spécifier les données à traiter et comment les traiter de la même manière que JSON Schema.
Installez JSON Merge.
$ pip install jsonmerge
Semblable à cet article, les fichiers suivants sont stockés dans le répertoire filter_plugins
. (En fait, d'autres filtres personnalisés sont également écrits dans le même fichier.)
Ce que nous faisons, ce sont les deux points suivants.
HAS_JSONMERGE
--Retourne une fusion de deux données JSON selon le schéma JSONcustom_filters1.py
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.six import PY3, string_types
from ansible.errors import AnsibleError, AnsibleFilterError
try:
from jsonmerge import Merger
HAS_JSONMERGE = True
except ImportError:
HAS_JSONMERGE = False
class FilterModule(object):
def jsonmerge(self, output1, output2, schema):
if not HAS_JSONMERGE:
raise AnsibleFilterError("JSONMerge not found. Run 'pip install jsonmerge'")
merger = Merger(schema)
merge_result = merger.merge(output1, output2)
return merge_result
def filters(self):
return {
'jsonmerge': self.jsonmerge
}
Identique à Article précédent J'ai utilisé quelque chose.
Playbook Le contenu de chaque tâche est le suivant.
Obtenez les paramètres d'interface existants avec le module restconf_get
(1 de GigabieEthernet1 à 3
a déjà été défini)
Sortie du résultat de la tâche 1
Définissez les paramètres de description, de déblocage (pas d'arrêt) et d'adresse IP GigabitEthernet2
dans la variable de lecture content_data
.
Fusionnez le résultat de la tâche 1 avec content_data
avec le plug-in de filtre jsonmerge
.
À ce stade, dans la variable de tâche schema
, spécifiez la stratégie de fusion du paramètre d'interface (ʻinterface:) à ʻarrayMergeById
. Spécifiez que le nom de l'interface est l'ID (ʻidRef: name`) et le même ID fusionne les paramètres.
playbook_restconf_int_merge1.yml
---
- hosts: cisco
gather_facts: no
vars:
content_data:
ietf-interfaces:interfaces:
interface:
- description: "For TEST"
enabled: true
ietf-ip:ipv4:
address:
- ip: 192.168.1.1
netmask: 255.255.255.0
name: GigabitEthernet2
tasks:
- name: get interface info # (1)
restconf_get:
path: /data/ietf-interfaces:interfaces
register: result_before
- name: display output data # (2)
debug:
msg: "{{ result_before.response }}"
- name: merge existing and setup interface settings # (3)
debug:
msg: "{{ result_before.response | jsonmerge(content_data, schema) }}"
vars:
schema:
properties:
ietf-interfaces:interfaces:
properties:
interface:
mergeStrategy: arrayMergeById
mergeOptions:
idRef: name
Si vous regardez le résultat de la tâche 3, vous pouvez voir qu'ils sont fusionnés sans aucun problème.
$ ansible-playbook -i inventory_restconf1.ini playbook_restconf_int_merge1.yml
PLAY [cisco] **********************************************************************************************************
TASK [get interface info] *********************************************************************************************
ok: [csr1000v-1]
TASK [display output data] ********************************************************************************************
ok: [csr1000v-1] => {
"msg": {
"ietf-interfaces:interfaces": {
"interface": [
{
"description": "MANAGEMENT INTERFACE - DON'T TOUCH ME",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "10.10.20.48",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet1",
"type": "iana-if-type:ethernetCsmacd"
},
{
"enabled": false,
"ietf-ip:ipv4": {},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet2",
"type": "iana-if-type:ethernetCsmacd"
},
{
"description": "Network Interface",
"enabled": false,
"ietf-ip:ipv4": {},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet3",
"type": "iana-if-type:ethernetCsmacd"
}
]
}
}
}
TASK [merge existing and setup interface settings] ********************************************************************
ok: [csr1000v-1] => {
"msg": {
"ietf-interfaces:interfaces": {
"interface": [
{
"description": "MANAGEMENT INTERFACE - DON'T TOUCH ME",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "10.10.20.48",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet1",
"type": "iana-if-type:ethernetCsmacd"
},
{
"description": "For TEST",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.1.1",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet2",
"type": "iana-if-type:ethernetCsmacd"
},
{
"description": "Network Interface",
"enabled": false,
"ietf-ip:ipv4": {},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet3",
"type": "iana-if-type:ethernetCsmacd"
}
]
}
}
}
PLAY RECAP ************************************************************************************************************
csr1000v-1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Pour votre information, collez le résultat des paramètres d'interface réels dans le module ʻuri`.
playbook_restconf_int_merge2.yml
---
- hosts: cisco
gather_facts: no
vars:
content_data:
ietf-interfaces:interfaces:
interface:
- description: "For TEST"
enabled: true
ietf-ip:ipv4:
address:
- ip: 192.168.1.1
netmask: 255.255.255.0
name: GigabitEthernet2
tasks:
- name: merge interface settings
uri:
url: https://{{ansible_host}}:{{ansible_httpapi_port}}/restconf/data/ietf-interfaces:interfaces
method: PATCH
headers:
Content-Type: application/yang-data+json
Accept: application/yang-data+json
body_format: json
body: "{{ content_data | to_json }}"
status_code:
- 200
- 204
url_username: "{{ ansible_user }}"
url_password: "{{ ansible_password }}"
force_basic_auth: yes
validate_certs: no
- name: get interface info
restconf_get:
path: /data/ietf-interfaces:interfaces
register: result
- name: display output data
debug:
msg: "{{ result.response }}"
$ ansible-playbook -i inventory_restconf1.ini playbook_restconf_int_merge2.yml
PLAY [cisco] **********************************************************************************************************
TASK [merge interface settings] ***************************************************************************************
ok: [csr1000v-1]
TASK [get interface info] *********************************************************************************************
ok: [csr1000v-1]
TASK [display output data] ********************************************************************************************
ok: [csr1000v-1] => {
"msg": {
"ietf-interfaces:interfaces": {
"interface": [
{
"description": "MANAGEMENT INTERFACE - DON'T TOUCH ME",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "10.10.20.48",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet1",
"type": "iana-if-type:ethernetCsmacd"
},
{
"description": "For TEST",
"enabled": true,
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.1.1",
"netmask": "255.255.255.0"
}
]
},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet2",
"type": "iana-if-type:ethernetCsmacd"
},
{
"description": "Network Interface",
"enabled": false,
"ietf-ip:ipv4": {},
"ietf-ip:ipv6": {},
"name": "GigabitEthernet3",
"type": "iana-if-type:ethernetCsmacd"
}
]
}
}
}
PLAY RECAP ************************************************************************************************************
csr1000v-1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Dans ce cas, le résultat de fusion attendu a été obtenu. Cependant, si je voulais ajouter plusieurs données de tableau imbriquées au lieu de l'écraser, le schéma JSON était en conflit et ne fonctionnait pas. Il y a peut-être un moyen de le faire, mais j'ai atteint la limite de mon énergie et j'aimerais réessayer: transpirer:
Recommended Posts