web-dev-qa-db-fra.com

Créer des variables set_fact dans un rôle et les utiliser dans un autre

J'ai un environnement compliqué avec des étapes et des utilisateurs pour plusieurs systèmes.

Les étapes sont: dev, int, etc.

Chaque étape a un utilisateur pour une application, appelons l'utilisateur john. Cela conduit À un utilisateur johnd pour dev et johni pour int et ainsi de suite.

Pour résumer la gestion du système, puisque tous les systèmes des étapes sont les mêmes, J'ai créé cette structure de données:

users:
  john:
    dev:
      name: "johnd"
    int:
      name: "johni"

Maintenant, j'ai un rôle "collect_user_information" qui collecte toutes sortes d'informations de LDAP et les stocke dans une variable à l'aide de set_fact.

- name: Get the userhome out of LDAP
  Shell: 'getent passwd {{ users[ user ][ stage ].name }} | cut -d: -f6'
  register: user_home

Et set_fact:

- name: set facts for LDAP user
  set_fact:
    "{{user}}":
      name: "{{ users[ user ][ stage ].name }}"
      home: "{{ user_home.stdout }}"

Pour vider la variable, j'utilise:

- name: debug output for myuser
  debug: var="{{user}}"

La sortie de débogage semble prometteuse.

TASK [collect_user_information : debug output for user] *******
ok: [Host1] => {
  "john": {
     "home": "/home/johni",-
     "name": "johni"
  }
}

Maintenant, je voudrais exécuter un rôle pour créer la maison des utilisateurs.

- { role: create_user_home, user: "john" }

Je commence par vider les entrées de ma variable:

- name: debug role create_user_home output for variable user
  debug: var=user

TASK [create_user_home : debug role create_user_home output for variable user] ***********
ok: [Host1] => {
    "user": "john"
}

- name: debug role create_user_home output for variable john
  debug: var={{ user }}

TASK [create_user_home : debug role create_user_home output for variable john] **********
ok: [Host1] => {
    "john": {
        "home": "/home/johni",-
        "name": "johni"
    }
}       

Maintenant, j'aimerais utiliser cette structure de données. Je suppose que je peux accéder aux valeurs en faisant référence à "{{user.name}}" ou "{{user ['name']}} '', mais ni ne fonctionne.

TASK [create_user_home : Create home directories for john] ***********************
fatal: [Host1]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible.parsing.yaml.objects.AnsibleUnicode object' has no attribute 'home'\n\nThe error appears to have been in '/etc/ansible/roles/create_user_home/tasks/main.yml': line 37, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n#-------------------------------------------------------------------------------\n- name: Create home directories for john\n  ^ here\n"}

Comment ça marche?

4
iamcheko

Ok j'ai trouvé la solution moi-même.

Tout d'abord, je crée une couche supplémentaire (myuser) dans ma structure de données et utilise une notation différente.

- name: set facts for LDAP user
  set_fact:
  myuser: '{ "{{user}}": { "name": "{{ users[ user ][ stage ].name }}", "home": "{{ user_home.stdout }}", "gid": "{{ user_gid.stdout}}", "group": "{{ user_primarygroup.stdout }}" } }'

Cela me renvoie un dump de débogage comme ceci:

TASK [collect_user_information : debug output for myuser] ***********
ok: [Host1] => {
    "myuser": {
        "john": {
            "home": "/home/johni",
            "name": "johni"
        }
    }
}

Maintenant, je peux utiliser les valeurs de ma structure de données. Rappelez-vous que "utilisateur" bin a été transmis au rôle par argument.

- name: Create home directories for user
  user:
    name: "{{ myuser[ user ].name }}"
    home: "{{ myuser[ user ].home }}"
    Shell: "/bin/bash"
  register: "create_user_home"
  tags: [ 'user' ]

J'espère que cela pourra aider.

1
iamcheko

Tout est trop compliqué ici - vous voulez définir une variable dynamique où le nom de la variable est le nom d'utilisateur, par exemple. john, while john est un dict contenant deux clés qui sont .name et .home.

Votre première tentative a échoué car vous tentiez de faire référence à user.name qui fait référence à la clé name d'un dict user, mais pas à un dict appelé john.

Puisque vous avez défini un dictée d'or users quelque part, vous n'avez pas vraiment besoin de compliquer les choses. Vous pouvez toujours référencer le nom avec users[user][stage].name et user_home.stdout pour le répertoire personnel.

Si vous pensez que la syntaxe est trop compliquée. Nous pouvons revenir à votre approche initiale en créant un autre dict pour stocker le nom et le répertoire personnel. Dans le cas suivant, user fait toujours référence à l'utilisateur actuel que vous provisivez:

- name: set facts for LDAP user
  set_fact:
    user:
      name: "{{ users[username][stage].name }}"
      home: "{{ user_home.stdout }}"

Pour que vous puissiez utiliser user.name et user.home dans les tâches suivantes. Notez la 4ème ligne, j'ai renommé la var que vous passez au rôle en username pour éviter les collisions.


Mise à jour:

Support pour plusieurs utilisateurs:

- name: Get the user home out of LDAP
  Shell: 'getent passwd {{ users[item][stage].name }} | cut -d: -f6'
  register: homes
  with_items: "{{ users }}"

# item.item is the username, item.stdout is the home dir
- debug: msg="{{ users[item.item][stage].name }}'s home is {{ item.stdout }}"
  with_items: "{{ homes.results }}"

En savoir plus sur Utilisation du registre avec une boucle .

0
Chris Lam