J'ai besoin d'aide pour comprendre pourquoi, lorsque je crée un fichier YAML pour un playbook Ansible qui reflète exactement ce qui est spécifié dans la documentation du module, les listes et list_items ne sont pas analysés correctement lorsque le YAML est lu par Python.
Je crois comprendre que lors de la lecture de la documentation sur les modules Ansible sur Github, les éléments sont affichés dans des colonnes pour indiquer leur relation par rapport aux éléments au-dessus et en dessous d'eux. De plus, si un élément est défini comme " liste / éléments = dictionnaire ", cela signifie ce qui suit:
La saisie de l'élément doit être terminée en ajoutant un deux-points et un espace (cela définit les éléments "dictionnaire")
La ligne suivante / suivante doit commencer au même niveau d'indentation (ou plus) et commencer par un tiret et un espace (cela désigne un élément de «liste»)
L'ordre des éléments dans une liste doit être suivi exactement.
Les éléments de liste suivants doivent être au même niveau d'indentation que le premier élément de la liste
Si un sous-élément donné de la liste est lui-même un autre élément " liste / éléments = dictionnaire ", répétez l'étape 2 à nouveau.
(EXEMPLE: extrait du module cisco.ios.ios_ospfv2 ) Donc, si l'élément principal de " processus " est un " liste / éléments = dictionnaire " composé des éléments suivants:
Ensuite, la syntaxe YAML correcte pour ce qui précède serait:
processes: - process_id: 1 areas: - area_id: '0' authentication: message_digest: true network: address: 0.0.0.0 area: 0 wildcard_bits: 255.255.255.255
Cependant, même si je n'obtiens aucune erreur YAML lorsque je démarre mon Playbook, j'obtiens un tas de traces obscures de Python. Mais si je change mon code en CECI (voir ci-dessous), cela fonctionne!
processes: - areas: - area_id: 0 ##dictionary_item - authentication: ##dictionary_item message_digest: true ##boolean - network: - address: '10.1.1.0' ##string - area: '0' ##string - wildcard_bits: 0.0.0.255. ##integer - process_id: 1
Mes questions:
(désolé pour le long post ... je ne savais pas comment le condenser plus loin)
3 Réponses :
Voici une explication générale de ce YAML:
- foo: bar bar: foo - baz: qux qux: baz
processes
: vous pouvez avoir 1 à N processus, donc c'est une liste, et dans ce cas, une liste de dictionnaire. Vous devriez vous attendre à quelque chose comme:- foo: bar bar: foo - baz: qux qux: baz
process_id
: est un int, vous devriez vous attendre:the: jump: over red: foxDonc c'est exactement le même YAML
the: red: fox jump: over
areas
: est une liste de 1 à N zones, sous les areas
clés d'un dictionnaire, imbriquées dans une liste, de processes
clés- the: red: fox jump: over - the: lazy: dog
network
: est un dictionnaire dans un dictionnairefruits: - banana - apple - pear - peach
Donc, en général, faites attention à la façon dont Ansible vous donne également des indices ici: les areas
sont pluralisées pour une bonne raison: parce que c'est une liste de zones. Il en va de même pour les processes
. Alors que le network
est un singulier, donc, comme prévu, ce sera un dictionnaire et non une liste.
list / elements = dictionnaire
Signifie que les processus doivent être une liste où chaque élément est un dictionnaire.
En YAML, c'est un dictionnaire:
foo: some: bar property: bar of: bar the: bar dictionary: bar of: bar key: bar foo: bar
Et voici une liste:
processes: - process_id: 1 areas: - area_id: '0' authentication: message_digest: true - area_id: '1' authentication: message_digest: true - process_id: 2 areas: - area_id: '0' authentication: message_digest: true network: address: 0.0.0.0 area: 0 wildcard_bits: 255.255.255.255
Ensuite, une liste de dictionnaires serait:
processes: - process_id: 1 areas: - area_id: '0' authentication: message_digest: true - area_id: '1' authentication: message_digest: true - process_id: 2 areas: - area_id: '0' authentication: message_digest: true
Notez que, puisqu'il s'agit d'une liste, la même clé peut être reproduite dans les différents éléments de la liste mais ne peut pas être vue deux fois dans le même dictionnaire.
Donc, pour répondre à votre deuxième question, vous avez raison de dire que dans un dictionnaire, l'ordre des touches n'a pas d'importance:
processes: - process_id: 1 # since you are in a dictionary, # process_id can be anywhere in the dictionary, # as the first, last, or anywhere in between key foo: bar baz: qux - process_id: 2 # since you are in a dictionary, # process_id can be anywhere in the dictionary, # as the first, last, or anywhere in between key foo: some baz: thing
Est en effet exactement le même dictionnaire que
processes: - foo: bar baz: qux # since you are in a dictionary, # process_id can be anywhere in the dictionary, # as the first, last, or anywhere in between key process_id: 1 - foo: some baz: thing # since you are in a dictionary, # process_id can be anywhere in the dictionary, # as the first, last, or anywhere in between key process_id: 2
Mais puisque vous faites ici une liste de ce que devrait être un dictionnaire, c'est là que réside votre problème.
Une petite note sur le trait d'union ( -
) aussi, car cela semble vous déranger:
Si vous le préférez, écrivez vos listes comme ceci:
processes: - foo: bar baz: qux - foo: some baz: thing
C'est strictement équivalent à:
processes: - process_id: 1 areas: - area_id: '0' authentication: message_digest: true network: address: 0.0.0.0 area: 0 wildcard_bits: 255.255.255.255
Cela vous aiderait à voir que le trait d'union délimite simplement le fait qu'un nouvel élément de la liste commence là, maintenant vous pouvez le "condenser" et avoir une clé de votre dictionnaire sur la même ligne que le délimiteur "nouvel élément de la liste" ( -
), mais vous n'y êtes pas obligé.
Peut-être pour un langage de programmation orienté objet parallèle, si cela peut vous être utile, vous devriez penser
Ainsi, lorsque la documentation dit liste / éléments = dictionnaire, ils veulent en fait que vous construisiez une liste (ou une collection) où tous les éléments seraient des dictionnaires (ou des objets).
Peut-être que la mise en page sur la page de documentation elle - même est plus facile à lire que le tableau sur GitHub.
Mais là, vous pouvez clairement voir que le dictionnaire de config
contient une liste de processes
qui, elle-même, contient beaucoup de dictionnaires différents, parmi lesquels address_family
, adjacency
, ..., areas
, network
, ...
Merci β.εηοιτ.βε. Cependant, ce qui me trouble ici, c'est que ni les «zones» ni les «réseaux» ne sont purement des dictionnaires. Ils (comme les "processus") sont de type "liste / éléments = dictionnaire". Et étant donné qu'ils sont tous les deux au même niveau (sous processus) et tous les deux du même type ... pourquoi est-ce qu'un trait d'union avant "zones" est acceptable mais PAS acceptable avant "réseau"? C'est presque comme si la documentation déclarait que "réseau" est une "liste / éléments = dictionnaire" alors qu'en réalité c'est purement un dictionnaire. Alors, cherchons-nous un bug de documentation ici?
Parce qu'ils sont censés être listés sous l'un des éléments des processus de liste
Faites attention à la façon dont Ansible vous donne également des indices ici: les areas
sont pluralisées pour une bonne raison, car il s'agit d'une liste de area
. Il en va de même pour les processes
. Alors que le réseau est un singulier, donc, comme prévu, ce sera un dictionnaire et non une liste.
@KeithBogart J'ai ajouté une petite note sur le trait d'union, qui pourrait répondre à l'idée fausse à laquelle vous faites face ici
Merci à tous pour vos idées. J'ai discuté avec d'autres et je pense que c'est un problème d'erreur de documentation pour ce module. L'élément de "réseau" est documenté comme étant "liste / éléments = dictionnaire".
En réalité, le code Python sous-jacent s'attend à le voir comme un dictionnaire (pas une liste). Lorsqu'il est ajouté en tant que dictionnaire, cela fonctionne très bien. S'il vous plaît voir mon lien dans lequel je fournit une capture d'écran de la documentation (incorrecte) ainsi que l'erreur Python qui se produit lorsque "réseau" est configuré en tant que "liste / éléments = dictionnaire". entrez la description de l'image ici
Mise à jour: J'utilisais auparavant la collection Ansible cisco.ios version 1.1.0 (qui nécessite que le paramètre "network" soit entré comme dictionnaire dans le code python du module, "ios_ospfv2").
Lors de la mise à niveau vers la version 1.2.0 de la collection cisco.ios, le paramètre "réseau" ne fonctionnait plus comme un dictionnaire et devait être changé en une liste (qui correspond à la documentation de ce module).
Donc, apparemment, la version d'Ansible Collection que l'on utilise peut changer la façon dont les paramètres sont définis dans les modules. Morale de l'histoire? Assurez-vous d'utiliser la dernière version de la collection dont vous avez besoin. Déterminer la version la plus récente de la collection
Quelle structure de données connaissez-vous? Quel est votre langage de codage principal? Cela vous aiderait-il si nous traduisions cela dans la langue à laquelle vous êtes «habitué»?
La plupart des gens qui "implémentent" yaml comme format de configuration n'ont aucune idée de ce qu'ils implémentent réellement. C'est un format de données si fondamentalement cassé que sa popularité défie ma compréhension. Protégez tous ceux qui pensent que yaml est une bonne idée: faites des recherches, examinez les cas secondaires, voyez dans quoi vous faites vraiment entrer vos utilisateurs: / J'utilise beaucoup trop Ansible à un moment donné, et pendant ce que vous décrivez peut ne pas être nécessairement un bogue, cela tue la convivialité de la chose si vous voulez faire quelque chose qui n'est pas trivial et couvert dans des tutoriels. Par pour le cours ici.
@UnslanderMonica TBH, je comprends partiellement l'aversion de YAML, vous n'êtes pas la première personne que je vois soulever cela. Cela dit, c'est un peu comme n'importe quel langage utilisant
{}
pour indiquer des blocs par rapport à Python utilisant l'indentation pour indiquer des blocs. Donc, les gens préfèrent JSON à YAML, mais c'est comme la plupart des choses: une question de goûts. Il y a cependant des bizarreries dans YAML, mais cette question ne fait pas partie de ces cas.