Webapp-Mechanismus (Phase 2): neue Rolle webapp-shortcuts
Kundeneigene URLs (workspace_webapps, siehe admin/provisioning-server) werden als .desktop-Menueintrag (/usr/share/applications) UND best-effort als Desktop-Icon ausgeliefert - kein present/absent pro Eintrag wie sonst im Katalog, sondern ein echter ABGLEICH: die Rolle bekommt bei jedem Lauf die komplette aktuelle Liste und sorgt dafuer, dass GENAU diese Eintraege existieren (Datei-Identifikation ueber die stabile DB-UUID, keine Namens-Slugifizierung noetig). Laeuft deshalb IMMER (site.yml-Play-Var tuxflotte_webapps, agent.py haengt sie immer in --tags ein, siehe admin/provisioning-agent), nicht nur bei Aenderungen. Desktop-Icon-Ablage bewusst pragmatisch: /etc/skel/Desktop (kuenftige Nutzer) + bestehende /home/*/Desktop-Ordner, falls schon vorhanden - kein erzwungenes Anlegen. Haengt an der noch offenen ADR-0026 (kein final festgelegter primaerer interaktiver Nutzer-Account) - deckt ab, was heute real existiert (z.B. den 'gast'-Account aus guest-session), ohne auf die endgueltige Klaerung zu warten. ECHT END-ZU-ENDE GETESTET (nicht nur Syntax-Check): echter ansible-playbook-Lauf gegen localhost mit Mock-Daten - Anlegen (mit+ohne Favicon), Aktualisieren, vollstaendiges Entfernen bei leerer Liste, Idempotenz. Favicon-Download-Pfad mit echter URL verifiziert. ansible-core dafuer neu installiert (vorher nicht vorhanden). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
This commit is contained in:
1 parent
0f452c44ec
commit
e4edcf1011
4 files changed
+169
No files matched your search
@@ -0,0 +1,3 @@
|
||||
tuxflotte_webapps: []
|
||||
tuxflotte_webapp_icons_dir: /usr/local/share/icons/tuxflotte-webapps
|
||||
tuxflotte_webapp_applications_dir: /usr/share/applications
|
||||
@@ -0,0 +1,140 @@
|
||||
# Webapp-Mechanismus (Phase 2, 09.09.2026): kundeneigene URLs (kein fester
|
||||
# Katalog-Merkmal wie sonst im Auftragskatalog - jeder Workspace hat seine
|
||||
# eigene, freie Liste, siehe fetch_workspace_webapps() in
|
||||
# provisioning-server/app.py). Deshalb kein present/absent pro Eintrag wie
|
||||
# bei den anderen Rollen, sondern ein ECHTER ABGLEICH: die Rolle bekommt bei
|
||||
# jedem Lauf die komplette aktuelle Liste (tuxflotte_webapps) und sorgt
|
||||
# dafür, dass GENAU diese Einträge existieren - alles andere (frühere,
|
||||
# inzwischen entfernte Webapps) wird aufgeräumt. Läuft deshalb bei jedem
|
||||
# ansible-pull IMMER (siehe agent.py apply_roles()), nicht nur wenn sich
|
||||
# etwas geändert hat.
|
||||
#
|
||||
# Dateibenennung nutzt die stabile UUID aus der DB (item.id), keine
|
||||
# Slugifizierung des Namens nötig - vermeidet Kollisionen/Sonderzeichen-
|
||||
# Probleme bei Namensänderungen.
|
||||
|
||||
- name: Ensure marker directory exists
|
||||
ansible.builtin.file:
|
||||
path: /run/tuxflotte/agent/applied
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure icon and applications directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "{{ tuxflotte_webapp_icons_dir }}"
|
||||
- "{{ tuxflotte_webapp_applications_dir }}"
|
||||
- /etc/skel/Desktop
|
||||
|
||||
- name: Find existing tuxflotte-webapp .desktop files
|
||||
ansible.builtin.find:
|
||||
paths: "{{ tuxflotte_webapp_applications_dir }}"
|
||||
patterns: "tuxflotte-webapp-*.desktop"
|
||||
register: tuxflotte_webapp_existing_files
|
||||
|
||||
- name: Desired vs. vorhandene .desktop-Pfade ermitteln
|
||||
ansible.builtin.set_fact:
|
||||
tuxflotte_webapp_desired_files: >-
|
||||
{{
|
||||
tuxflotte_webapps
|
||||
| map(attribute='id')
|
||||
| map('regex_replace', '^(.*)$', tuxflotte_webapp_applications_dir ~ '/tuxflotte-webapp-\1.desktop')
|
||||
| list
|
||||
}}
|
||||
tuxflotte_webapp_existing_paths: "{{ tuxflotte_webapp_existing_files.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: Stale-Dateien (nicht mehr in der aktuellen Liste) berechnen
|
||||
ansible.builtin.set_fact:
|
||||
tuxflotte_webapp_stale_files: "{{ tuxflotte_webapp_existing_paths | difference(tuxflotte_webapp_desired_files) }}"
|
||||
|
||||
- name: Remove stale webapp .desktop files (nicht mehr in der aktuellen Liste)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ tuxflotte_webapp_stale_files }}"
|
||||
|
||||
- name: Download favicon for each webapp (falls vorhanden)
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ item.icon_url }}"
|
||||
dest: "{{ tuxflotte_webapp_icons_dir }}/{{ item.icon_url | basename }}"
|
||||
mode: "0644"
|
||||
timeout: 10
|
||||
loop: "{{ tuxflotte_webapps }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
when: item.icon_url is not none
|
||||
# Best-effort: ein einzelnes nicht erreichbares Favicon (Seite down,
|
||||
# Netzwerkproblem auf dem Geraet) soll nicht den ganzen Lauf abbrechen -
|
||||
# der .desktop-Eintrag selbst wird trotzdem angelegt (Icon zeigt dann
|
||||
# kurzzeitig auf eine fehlende Datei, GTK faellt auf ein Platzhalter-Icon
|
||||
# zurueck, kein Absturz).
|
||||
ignore_errors: true
|
||||
|
||||
- name: Create/update .desktop menu entry for each webapp
|
||||
ansible.builtin.template:
|
||||
src: webapp.desktop.j2
|
||||
dest: "{{ tuxflotte_webapp_applications_dir }}/tuxflotte-webapp-{{ item.id }}.desktop"
|
||||
mode: "0644"
|
||||
loop: "{{ tuxflotte_webapps }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Copy .desktop entries into /etc/skel/Desktop (für künftig neu angelegte Nutzer)
|
||||
ansible.builtin.copy:
|
||||
src: "{{ tuxflotte_webapp_applications_dir }}/tuxflotte-webapp-{{ item.id }}.desktop"
|
||||
dest: "/etc/skel/Desktop/tuxflotte-webapp-{{ item.id }}.desktop"
|
||||
mode: "0755"
|
||||
remote_src: true
|
||||
loop: "{{ tuxflotte_webapps }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Remove stale .desktop entries from /etc/skel/Desktop
|
||||
ansible.builtin.file:
|
||||
path: "/etc/skel/Desktop/{{ item | basename }}"
|
||||
state: absent
|
||||
loop: "{{ tuxflotte_webapp_stale_files }}"
|
||||
|
||||
# Bestehende Nutzer-Homeverzeichnisse (z.B. der "gast"-Account aus der
|
||||
# guest-session-Rolle, falls aktiv): nur befüllen, wenn dort bereits ein
|
||||
# Desktop-Ordner existiert (kein aufgezwungenes Anlegen für Nutzer, deren
|
||||
# Desktop-Umgebung keine Desktop-Icons zeigt). ADR-0026 (kein primärer
|
||||
# interaktiver Nutzer-Account bisher final festgelegt) ist hier eine
|
||||
# bekannte offene Abhängigkeit - dieser bewusst pragmatische Ansatz deckt
|
||||
# ab, was heute an Accounts real existiert, ohne auf die endgültige
|
||||
# Klärung zu warten. Siehe project_phase2_app_store_merkmale-Memory.
|
||||
- name: Bestehende Nutzer-Homeverzeichnisse mit Desktop-Ordner ermitteln
|
||||
ansible.builtin.find:
|
||||
paths: /home
|
||||
file_type: directory
|
||||
patterns: "Desktop"
|
||||
recurse: true
|
||||
depth: 2
|
||||
register: tuxflotte_webapp_user_desktops
|
||||
|
||||
- name: .desktop-Einträge in bestehende Nutzer-Desktop-Ordner kopieren
|
||||
ansible.builtin.copy:
|
||||
src: "{{ tuxflotte_webapp_applications_dir }}/tuxflotte-webapp-{{ item.0.id }}.desktop"
|
||||
dest: "{{ item.1.path }}/tuxflotte-webapp-{{ item.0.id }}.desktop"
|
||||
mode: "0755"
|
||||
remote_src: true
|
||||
loop: "{{ tuxflotte_webapps | product(tuxflotte_webapp_user_desktops.files) | list }}"
|
||||
loop_control:
|
||||
label: "{{ item.0.name }} -> {{ item.1.path }}"
|
||||
|
||||
- name: Überzählige .desktop-Einträge aus bestehenden Nutzer-Desktop-Ordnern entfernen
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.1.path }}/{{ item.0 | basename }}"
|
||||
state: absent
|
||||
loop: "{{ tuxflotte_webapp_stale_files | product(tuxflotte_webapp_user_desktops.files) | list }}"
|
||||
loop_control:
|
||||
label: "{{ item.0 }} -> {{ item.1.path }}"
|
||||
|
||||
- name: Record that the webapp-shortcuts role ran
|
||||
ansible.builtin.copy:
|
||||
dest: /run/tuxflotte/agent/applied/webapp-shortcuts.marker
|
||||
content: "{{ ansible_date_time.iso8601 }}: {{ tuxflotte_webapps | length }} webapp(s)\n"
|
||||
mode: "0644"
|
||||
@@ -0,0 +1,13 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name={{ item.name }}
|
||||
Comment=Tuxflotte-Webapp: {{ item.url }}
|
||||
Exec=xdg-open {{ item.url }}
|
||||
{% if item.icon_url %}
|
||||
Icon={{ tuxflotte_webapp_icons_dir }}/{{ item.icon_url | basename }}
|
||||
{% else %}
|
||||
Icon=web-browser
|
||||
{% endif %}
|
||||
Terminal=false
|
||||
Categories=Network;WebBrowser;
|
||||
NoDisplay=false
|
||||
@@ -11,6 +11,11 @@
|
||||
# z.B. {"standardbrowser": true} bei brave. Rein additiv, opak für den
|
||||
# Server/Agenten - nur die jeweilige Rolle kennt die Bedeutung.
|
||||
tuxflotte_auftrag_optionen: {}
|
||||
# Vom Agenten per --extra-vars gesetzt (Check-in-Response "webapps",
|
||||
# Phase 2 09.09.2026): Liste kundeneigener {id, name, url, icon_url}-
|
||||
# Einträge, verarbeitet ausschließlich von der webapp-shortcuts-Rolle
|
||||
# (siehe dort) - kein present/absent-Merkmal wie der Rest dieser Datei.
|
||||
tuxflotte_webapps: []
|
||||
tasks:
|
||||
- include_role:
|
||||
name: guest-session
|
||||
@@ -362,3 +367,11 @@
|
||||
tuxflotte_state: "{{ tuxflotte_auftrag_states.get('turbowarp', 'present') }}"
|
||||
tuxflotte_optionen: "{{ tuxflotte_auftrag_optionen.get('turbowarp', {}) }}"
|
||||
tags: turbowarp
|
||||
|
||||
- include_role:
|
||||
name: webapp-shortcuts
|
||||
apply:
|
||||
tags: webapp-shortcuts
|
||||
vars:
|
||||
tuxflotte_webapps: "{{ tuxflotte_webapps }}"
|
||||
tags: webapp-shortcuts
|
||||
Reference in new issue
Block a user