web-dev-qa-db-fra.com

fusion de dictionnaires en ansible

Je suis en train de créer un rôle pour installer PHP en utilisant ansible, et j'ai des difficultés à fusionner les dictionnaires. J'ai essayé plusieurs façons de le faire, mais je n'arrive pas à le faire travailler comme je le veux:

# A vars file:
my_default_values:
  key = value

my_values:
  my_key = my_value


# In a playbook, I create a task to attempt merging the
# two dictionaries (which doesn't work):

- debug: msg="{{ item.key }} = {{ item.value }}"
  with_dict: my_default_values + my_values

# I have also tried:

- debug: msg="{{ item.key }} = {{ item.value }}"
  with_dict: my_default_values|union(my_values)

# I have /some/ success with using j2's update,
# but you can't use j2 syntax in "with_dict", it appears.
# This works:

- debug: msg="{{ my_default_values.update(my_values) }}"

# But this doesn't:

- debug: msg="{{ item.key }} = {{ item.value }}"
  with_dict: my_default_values.update(my_values)

Existe-t-il un moyen de fusionner deux dictionnaires, donc je peux l'utiliser avec "with_dict"?

41
Berry Langerak

Dans Ansible 2.0, il existe un filtre Jinja, combine , pour cela:

- debug: msg="{{ item.key }} = {{ item.value }}"
  with_dict: "{{ my_default_values | combine(my_values) }}"
68
augurar

Si vous voulez fusionner le hachage, je voudrais activer la fonction de fusion du hachage dans ansible. Dans votre fichier de configuration ansible activez la fusion de hachage .

Avec hash_behaviour = merge vous pouvez avoir deux fichiers var avec le même nom de variable:

defaults.yml:

values:
  key: value

overrides.yml:

values:
  my_key: my_value

Pour que les deux vars soient fusionnés, vous devrez inclure les deux fichiers var:

ansible-playbook some-play.yml ... [email protected]  [email protected]

Et vous vous retrouverez avec ceci:

TASK: [debug var=values] ********************************************************
ok: [localhost] => {
    "values": {
        "key": value,
        "my_key": my_value
    }
}

Appeler la mise à jour sur une variable peut être fait dans Jinja mais en général, ce sera compliqué, je ne le ferais pas en dehors de vos modèles et même essayer de l'éviter complètement.

11
jarv

Il est désormais possible d'utiliser l'ancre et d'étendre les fonctionnalités de YAML:

---
- hosts: localhost
  vars:
    my_default_values: &def
      key: value
    my_values:
      <<: *def
      my_key: my_value
  tasks:
    - debug: var=my_default_values
    - debug: var=my_values

Résultat:

TASK [debug]
ok: [localhost] => {
    "my_default_values": {
        "key": "value"
    }
}

TASK [debug] 
ok: [localhost] => {
    "my_values": {
        "key": "value", 
        "my_key": "my_value"
    }
}

Je ne sais pas pourquoi cela n'a pas été mentionné auparavant.

6
leiiv

Si vous avez besoin du dictionnaire fusionné plusieurs fois, vous pouvez le définir sur une nouvelle "variable":

- set_fact: _my_values="{{ my_default_values|combine(my_values) }}"

- debug: msg="{{ item.key }} = {{ item.value }}"
  with_dict: _my_values
3
Nat

Essayez ce rôle depuis Ansible Galaxy.

Je l'ai fait il y a quelque temps pour la même raison. Il peut fusionner en profondeur les dictionnaires de plusieurs fichiers vars et définir la priorité personnalisée de la fusion.

Ce rôle peut fonctionner sous Ansible 2.0+

1
eugene0707