Ich habe eine komplizierte Umgebung mit Stufen und Benutzern für mehrere Systeme.
Die Stufen sind: dev, int usw.
Jede Stufe hat einen Benutzer für eine Anwendung, nennen wir den Benutzer john. Das führt Zu einem Benutzer, der für dev und johni für int und so weiter verwendet wird.
Um die Systemverwaltung zu abstrahieren, da alle Systeme in den Stufen gleich sind, habe ich diese Datenstruktur Erstellt:
users:
john:
dev:
name: "johnd"
int:
name: "johni"
Jetzt habe ich eine Rolle "collect_user_information", die alle Arten von Informationen aus LDAP sammelt und mit Hilfe von set_fact in einer Variablen speichert.
- name: Get the userhome out of LDAP
Shell: 'getent passwd {{ users[ user ][ stage ].name }} | cut -d: -f6'
register: user_home
Und set_fact:
- name: set facts for LDAP user
set_fact:
"{{user}}":
name: "{{ users[ user ][ stage ].name }}"
home: "{{ user_home.stdout }}"
Um die Variable zu sichern, verwende ich:
- name: debug output for myuser
debug: var="{{user}}"
Die Debug-Ausgabe sieht vielversprechend aus.
TASK [collect_user_information : debug output for user] *******
ok: [Host1] => {
"john": {
"home": "/home/johni",-
"name": "johni"
}
}
Jetzt möchte ich eine Rolle ausführen, um die Benutzer zu Hause zu erstellen.
- { role: create_user_home, user: "john" }
Zuerst mache ich die Einträge meiner Variablen:
- 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"
}
}
Nun möchte ich diese Datenstruktur verwenden. Ich würde vermuten, dass ich auf die Werte zugreifen kann, indem ich auf "{{user.name}}" oder "{{user ['name']}}" verweise.
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"}
Nun, wie funktioniert das?
Okay, ich habe die Lösung selbst gefunden.
Zuerst erstelle ich eine zusätzliche Schicht (myuser) in meiner Datenstruktur und verwende eine andere Notation.
- 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 }}" } }'
Dies gibt mir einen Debug-Dump wie folgt zurück:
TASK [collect_user_information : debug output for myuser] ***********
ok: [Host1] => {
"myuser": {
"john": {
"home": "/home/johni",
"name": "johni"
}
}
}
Jetzt kann ich die Werte meiner Datenstruktur verwenden. Denken Sie daran, dass "Benutzer" bin durch Argument an die Rolle übergeben wurde.
- name: Create home directories for user
user:
name: "{{ myuser[ user ].name }}"
home: "{{ myuser[ user ].home }}"
Shell: "/bin/bash"
register: "create_user_home"
tags: [ 'user' ]
Hoffentlich hilft das.
Das Ganze ist hier zu knifflig - Sie möchten eine dynamische Variable definieren, bei der der Variablenname der Benutzername ist, z. john
, während john
ein Dikt ist, das zwei Schlüssel enthält, nämlich .name
und .home
.
Ihr erster Versuch ist fehlgeschlagen, weil Sie versucht haben, auf user.name
zu verweisen, die sich auf den Schlüssel name
eines Diktiers user
beziehen, jedoch nicht auf ein Diktum namens john
.
Da Sie irgendwo ein goldenes Diktum users
definiert haben, müssen Sie die Dinge nicht wirklich kompliziert machen. Sie können den Namen immer mit users[user][stage].name
und user_home.stdout
für das Heimatverzeichnis referenzieren.
Wenn Sie der Meinung sind, dass die Syntax zu lästig ist. Wir können zu Ihrem ursprünglichen Ansatz zurückkehren, indem Sie ein weiteres Diktat erstellen, um den Namen und das Heimatverzeichnis zu speichern. Im folgenden Fall bezieht sich user
immer auf den aktuellen Benutzer, den Sie bereitstellen:
- name: set facts for LDAP user
set_fact:
user:
name: "{{ users[username][stage].name }}"
home: "{{ user_home.stdout }}"
Damit können Sie user.name
und user.home
in allen nachfolgenden Aufgaben verwenden. Beachten Sie die vierte Zeile. Ich habe die Variable, die Sie der Rolle übergeben, in username
umbenannt, um eine Kollision zu vermeiden.
Update:
Unterstützung für mehrere Benutzer:
- 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 }}"
Lesen Sie mehr aus Verwenden Sie das Register mit einer Schleife .