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?
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.
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 .