From b3b961dbdabf84d83bb7bb6b21d681cf0c904b73 Mon Sep 17 00:00:00 2001 From: jonnybravo Date: Mon, 14 Sep 2026 12:43:09 +0200 Subject: [PATCH] Anpassung Powerpoint --- README.md | 36 ++-- ansible_praesentation.pptx | Bin 176746 -> 181854 bytes create_presentation.py | 342 +++++++++++++++++++++++-------------- handout.docx | Bin 14433 -> 15266 bytes handout.md | 51 +++++- 5 files changed, 286 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index fd30e2d..08bdb19 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ lauffähigen Beispiel-Projekt. Alles in Python generiert und reproduzierbar. ``` ansible_präsentation/ -├── ansible_praesentation.pptx # Die fertige Präsentation (19 Folien, 16:9) +├── ansible_praesentation.pptx # Die fertige Präsentation (21 Folien, 16:9) ├── create_presentation.py # Python-Skript, das die .pptx erzeugt ├── handout.md # Handout (Markdown-Quelle) ├── handout.docx # Handout (druckbar/editierbar, für OnlyOffice) @@ -25,7 +25,7 @@ ansible_präsentation/ ## 1. Die Präsentation (`ansible_praesentation.pptx`) -19 Folien, 16:9, in den Ansible-Brandfarben (Rot `#EE0000`, Anthrazit `#1A1918`). +21 Folien, 16:9, in den Ansible-Brandfarben (Rot `#EE0000`, Anthrazit `#1A1918`). | # | Titel | Inhalt | |---|-------|--------| @@ -33,21 +33,23 @@ ansible_präsentation/ | 2 | Was ist Ansible? | Definition, Merkmale (agentenlos, idempotent, …) | | 3 | Architektur | Control Node, Managed Nodes (Diagramm) | | 4 | Vier Kernkonzepte | Playbooks, Inventory, Module, Rollen | -| 5 | YAML-Syntax | Grundregeln + Inventory-Beispiel | -| 6 | Playbook | site.yml mit Tasks & FQCN | -| 7 | Module | 6 Modul-Kategorien | -| 8 | Ad-hoc-Befehle | `ansible`-CLI ohne Playbook | -| 9 | Jinja2 | `{{ variable }}`, Filter, `.j2`-Templates | -| 10 | Gather Facts | Facts auslesen, Custom Facts, `gather_facts` | -| 11 | Variablen & Präzedenz | Quellen + Reihenfolge (wer gewinnt) | -| 12 | FQCN (Definition) | `namespace.collection.modul` | -| 13 | FQCN (Praxis) | Beispiele + Warum | -| 14 | Collections | Was sie sind (6 Bestandteile) | -| 15 | Collections nutzen | Galaxy, Installation, Struktur | -| 16 | Rollen (Konzept) | Wiederverwendbarkeit, Kapselung | -| 17 | Rollen (Struktur) | `roles/webserver/` Verzeichnisbaum | -| 18 | Praxisbeispiel | Playbook mit Rolle + Variablen | -| 19 | Zusammenfassung | Key-Takeaways + Quellen | +| 5 | ansible.cfg | Konfiguration, Suchreihenfolge (wer gewinnt) | +| 6 | ansible.cfg Parameter | Wichtige Werte in [defaults], [privilege_escalation], [ssh_connection] | +| 7 | YAML-Syntax | Grundregeln + Inventory-Beispiel | +| 8 | Playbook | site.yml mit Tasks & FQCN | +| 9 | Module | 6 Modul-Kategorien | +| 10 | Ad-hoc-Befehle | `ansible`-CLI ohne Playbook | +| 11 | Jinja2 | `{{ variable }}`, Filter, `.j2`-Templates | +| 12 | Gather Facts | Facts auslesen, Custom Facts, `gather_facts` | +| 13 | Variablen & Präzedenz | Quellen + Reihenfolge (wer gewinnt) | +| 14 | FQCN (Definition) | `namespace.collection.modul` | +| 15 | FQCN (Praxis) | Beispiele + Warum | +| 16 | Collections | Was sie sind (6 Bestandteile) | +| 17 | Collections nutzen | Galaxy, Installation, Struktur | +| 18 | Rollen (Konzept) | Wiederverwendbarkeit, Kapselung | +| 19 | Rollen (Struktur) | `roles/webserver/` Verzeichnisbaum | +| 20 | Praxisbeispiel | Playbook mit Rolle + Variablen | +| 21 | Zusammenfassung | Key-Takeaways + Quellen | **Design-Hinweis:** Die Präsentation nutzt die Schriftarten **Carlito** (Body) und **DejaVu Sans Mono** (Code), da Calibri/Consolas auf Linux oft fehlen und diff --git a/ansible_praesentation.pptx b/ansible_praesentation.pptx index d237610807ce17aaf1fa14fb941dc6261a257a9a..353ad2d48c614863e619a14a6b719ca06fa3eb96 100644 GIT binary patch delta 31795 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 delta 27458 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 N%p`M?VGk3){{wMTOc?+G diff --git a/create_presentation.py b/create_presentation.py index 4b8f7bd..b7b4864 100644 --- a/create_presentation.py +++ b/create_presentation.py @@ -168,16 +168,19 @@ def text(slide, x, y, w, h, runs, size=14, bold=False, color=BLACK, p.line_spacing = leading if space_after: p.space_after = Pt(space_after) - if isinstance(item, str): - item = {"t": item} - elif isinstance(item, tuple): - item = {"t": item[0], **item[1]} - r = p.add_run(); r.text = item["t"] - r.font.size = Pt(item.get("size", size)) - r.font.bold = item.get("bold", bold) - r.font.italic = item.get("italic", False) - r.font.name = item.get("font", font) - r.font.color.rgb = item.get("color", color) + # item: str | tuple | dict (ein Run) ODER list (mehrere Runs inline) + subs = item if isinstance(item, list) else [item] + for s in subs: + if isinstance(s, str): + s = {"t": s} + elif isinstance(s, tuple): + s = {"t": s[0], **s[1]} + r = p.add_run(); r.text = s["t"] + r.font.size = Pt(s.get("size", size)) + r.font.bold = s.get("bold", bold) + r.font.italic = s.get("italic", False) + r.font.name = s.get("font", font) + r.font.color.rgb = s.get("color", color) return box @@ -191,10 +194,14 @@ def header(slide, kicker, title, dark=False): slide.shapes.add_picture(logo, Inches(12.35), Inches(0.25), Inches(0.62), Inches(0.76)) -def footer(slide, num): +_page_no = 1 # Titel (Folie 1) zeigt keine sichtbare Nummer + +def footer(slide): + global _page_no + _page_no += 1 text(slide, 0.55, 7.08, 9.0, 0.3, "Ansible — moderne Automatisierung", size=8, color=MIDGRAY) - text(slide, 12.2, 7.08, 0.6, 0.3, str(num), size=9, color=MIDGRAY, align=PP_ALIGN.RIGHT) + text(slide, 12.2, 7.08, 0.6, 0.3, str(_page_no), size=9, color=MIDGRAY, align=PP_ALIGN.RIGHT) def _set_run(r, text, font_size, color, bold=False): @@ -304,7 +311,7 @@ rect(s, 9.0, 0, 4.333, 7.5, RED, rounded=False) if os.path.exists(LOGO_WHITE): s.shapes.add_picture(LOGO_WHITE, Inches(0.9), Inches(1.35), Inches(2.1), Inches(2.59)) text(s, 0.9, 4.15, 7.5, 0.4, "MODERNE IT-AUTOMATISIERUNG", size=14, bold=True, color=RED) -text(s, 0.9, 4.55, 8.0, 1.3, "Ansible", size=60, bold=True, color=WHITE) +text(s, 0.9, 4.55, 8.0, 0.95, "Ansible", size=60, bold=True, color=WHITE) text(s, 0.9, 5.75, 7.5, 0.4, "Agentenlos · Idempotent · Deklarativ · YAML", size=16, color=RGBColor(0xD8, 0xD8, 0xD8)) text(s, 0.9, 6.55, 7.5, 0.4, @@ -353,7 +360,7 @@ for big, small in facts: text(s, 9.15, yy, 1.8, 0.5, big, size=22, bold=True, color=BLACK) text(s, 10.95, yy + 0.08, 2.2, 0.5, small, size=11, color=GRAY, leading=1.0) yy += 0.62 -footer(s, 2) +footer(s) # =========================================================================== @@ -380,7 +387,7 @@ for t, d in comp: text(s, 8.95, yy, 3.9, 0.3, t, size=13, bold=True, color=BLACK) text(s, 8.95, yy + 0.28, 3.9, 0.9, d, size=10.5, color=GRAY, leading=1.05) yy += 1.22 -footer(s, 3) +footer(s) # =========================================================================== @@ -400,11 +407,98 @@ card(s, 0.55, 4.3, 6.0, 2.4, "3", "Module", card(s, 6.85, 4.3, 6.0, 2.4, "4", "Rollen & Collections", "Rollen bündeln Tasks/Templates/Variablen zu wiederverwendbaren Einheiten. " "Collections verteilen Module, Rollen & Plugins.") -footer(s, 4) +footer(s) # =========================================================================== -# FOLIE 5 — YAML-Syntax +# FOLIE 5 — ansible.cfg (Konfiguration) +# =========================================================================== +s = new_slide(WHITE) +header(s, "Konfiguration", "ansible.cfg — die Konfigurationsdatei") +text(s, 0.55, 1.55, 12.2, 0.7, + "ansible.cfg steuert das Verhalten von Ansible global. INI-Format mit " + "Sektionen wie [defaults], [privilege_escalation] und [ssh_connection].", + size=13, color=BLACK, leading=1.15) + +# links: Suchreihenfolge (erste gefundene Datei gewinnt) +text(s, 0.55, 2.4, 5.5, 0.3, "SUCHREIHENFOLGE — WER GEWINNT?", size=11, bold=True, color=RED) +order = [ + ("ANSIBLE_CONFIG", "Umgebungsvariable"), + ("./ansible.cfg", "Projektverzeichnis"), + ("~/.ansible.cfg", "Home-Verzeichnis"), + ("/etc/ansible/ansible.cfg", "systemweit"), +] +yy = 2.9 +for i, (p, d) in enumerate(order, 1): + rect(s, 0.55, yy, 0.4, 0.4, RED, rounded=True, radius=0.3) + text(s, 0.55, yy + 0.03, 0.4, 0.34, str(i), size=13, bold=True, + color=WHITE, align=PP_ALIGN.CENTER) + text(s, 1.15, yy + 0.04, 2.55, 0.32, p, size=11.5, bold=True, + color=DARKRED, font=FONT_MONO) + text(s, 3.85, yy + 0.06, 2.2, 0.5, d, size=10, color=GRAY, leading=1.0) + yy += 0.62 +text(s, 0.55, yy + 0.15, 5.5, 0.6, + [[("Erste gefundene Datei gewinnt — ", {"bold": True}), + ("kein Zusammenführen!", {"bold": True, "color": RED})]], + size=11.5, color=BLACK) + +# rechts: Beispiel mit den wichtigsten Werten +code_block(s, 6.4, 2.4, 6.4, [ + "# ansible.cfg (INI-Format)", + "[defaults]", + "inventory = ./inventory.yml", + "remote_user = admin", + "forks = 20", + "host_key_checking = False", + "gather_facts = True", + "roles_path = ./roles", + "", + "[privilege_escalation]", + "become = True", + "become_method = sudo", + "", + "[ssh_connection]", + "pipelining = True", +], font_size=10.5, title="Beispiel") +footer(s) + + +# =========================================================================== +# FOLIE 6 — ansible.cfg Parameter +# =========================================================================== +s = new_slide(WHITE) +header(s, "Konfiguration", "ansible.cfg — wichtige Parameter") + +text(s, 0.55, 1.6, 3.9, 0.35, "[defaults]", size=13, bold=True, color=RED, font=FONT_MONO) +kv_rows(s, 0.55, 2.15, 3.9, [ + ("inventory", "Pfad zur Inventory-Datei"), + ("remote_user", "Standard-SSH-Benutzer"), + ("forks", "parallele Prozesse"), + ("host_key_checking", "SSH-Key-Prüfung"), + ("gather_facts", "Facts sammeln"), + ("roles_path", "Suchpfad für Rollen"), +], key_w=1.65, name_size=10.5, desc_size=10, gap=0.46) + +text(s, 4.7, 1.6, 3.9, 0.35, "[privilege_escalation]", size=13, bold=True, color=RED, font=FONT_MONO) +kv_rows(s, 4.7, 2.15, 3.9, [ + ("become", "sudo aktivieren"), + ("become_method", "sudo / su"), + ("become_user", "Ziel-Benutzer (root)"), + ("become_ask_pass", "Passwort abfragen"), +], key_w=1.7, name_size=10.5, desc_size=10, gap=0.46) + +text(s, 8.85, 1.6, 3.9, 0.35, "[ssh_connection]", size=13, bold=True, color=RED, font=FONT_MONO) +kv_rows(s, 8.85, 2.15, 3.9, [ + ("pipelining", "weniger SSH-Roundtrips"), + ("ssh_args", "zusätzl. SSH-Argumente"), + ("control_path", "ControlMaster-Socket"), +], key_w=1.5, name_size=10.5, desc_size=10, gap=0.46) + +footer(s) + + +# =========================================================================== +# FOLIE 7 — YAML-Syntax # =========================================================================== s = new_slide(WHITE) header(s, "Syntax", "YAML — die Sprache von Ansible") @@ -439,25 +533,25 @@ code_block(s, 6.5, 1.6, 6.3, [ " - git", " - curl", ], font_size=11) -footer(s, 5) +footer(s) # =========================================================================== -# FOLIE 6 — Playbook & Tasks +# FOLIE 8 — Playbook & Tasks # =========================================================================== s = new_slide(WHITE) header(s, "Syntax", "Ein Playbook in der Praxis") text(s, 0.55, 1.55, 5.6, 1.4, - [("Ein Playbook ", {}), - ("definiert, was passieren soll. ", {}), - ("plays", {"bold": True, "color": RED}), - (" wirken auf ", {}), - ("hosts", {"bold": True, "color": RED}), - (", jede ", {}), - ("task", {"bold": True, "color": RED}), - (" ruft genau ein ", {}), - ("Modul", {"bold": True, "color": RED}), - (" auf.", {})], + [[("Ein Playbook ", {}), + ("definiert, was passieren soll. ", {}), + ("plays", {"bold": True, "color": RED}), + (" wirken auf ", {}), + ("hosts", {"bold": True, "color": RED}), + (", jede ", {}), + ("task", {"bold": True, "color": RED}), + (" ruft genau ein ", {}), + ("Modul", {"bold": True, "color": RED}), + (" auf.", {})]], size=12.5, color=BLACK, leading=1.2) code_block(s, 6.5, 1.55, 6.3, [ "---", @@ -477,11 +571,11 @@ code_block(s, 6.5, 1.55, 6.3, [ " state: started", " enabled: true", ], font_size=10.5, title="site.yml") -footer(s, 6) +footer(s) # =========================================================================== -# FOLIE 7 — Module +# FOLIE 9 — Module # =========================================================================== s = new_slide(LIGHT) header(s, "Syntax", "Module — die Arbeitspferde") @@ -502,25 +596,25 @@ for i, (t, d) in enumerate(mods): col = i % 3; row = i // 3 card(s, 0.55 + col * 4.2, 2.6 + row * 1.75, 3.95, 1.5, "•", t, d) text(s, 0.55, 6.15, 12.2, 0.6, - [("Wichtig: Module werden heute über den ", {}), - ("FQCN", {"bold": True, "color": RED}), - (" referenziert (z.B. ", {}), - ("ansible.builtin.apt", {"font": FONT_MONO, "color": DARKRED}), - (").", {})], + [[("Wichtig: Module werden heute über den ", {}), + ("FQCN", {"bold": True, "color": RED}), + (" referenziert (z.B. ", {}), + ("ansible.builtin.apt", {"font": FONT_MONO, "color": DARKRED}), + (").", {})]], size=12, color=BLACK) -footer(s, 7) +footer(s) # =========================================================================== -# FOLIE 8 — Ad-hoc-Befehle +# FOLIE 10 — Ad-hoc-Befehle # =========================================================================== s = new_slide(WHITE) header(s, "Syntax", "Ad-hoc-Befehle — Ansible ohne Playbook") text(s, 0.55, 1.55, 5.7, 1.25, - [("Mit dem ", {}), - ("ansible", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - ("-CLI lassen sich einzelne Module direkt ausführen — ohne Playbook. Ideal " - "für schnelle Checks und einmalige Aktionen.", {})], + [[("Mit dem ", {}), + ("ansible", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + ("-CLI lassen sich einzelne Module direkt ausführen — ohne Playbook. Ideal " + "für schnelle Checks und einmalige Aktionen.", {})]], size=12.5, color=BLACK, leading=1.2) text(s, 0.55, 2.85, 5.7, 0.3, "AUFBAU", size=11, bold=True, color=RED) code_block(s, 0.55, 3.2, 5.7, [ @@ -552,11 +646,11 @@ code_block(s, 6.6, 1.55, 6.2, [ "ansible webserver -m service", " -a \"name=nginx state=restarted\"", ], font_size=10, title="Beispiele") -footer(s, 8) +footer(s) # =========================================================================== -# FOLIE 9 — Jinja2 (Templating) +# FOLIE 11 — Jinja2 (Templating) # =========================================================================== s = new_slide(WHITE) header(s, "Syntax", "Jinja2 — dynamische Inhalte") @@ -565,21 +659,21 @@ text(s, 0.55, 1.55, 12.2, 0.7, "und Dateien dynamisch erzeugt — in Playbooks, aber vor allem in Templates (.j2).", size=13, color=BLACK, leading=1.15) card(s, 0.55, 2.4, 4.0, 1.7, "1", "Variable auflösen", - [("{{ variable }}", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" setzt den Wert einer Variablen an die Stelle im Text ein.", {})]) + [[("{{ variable }}", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" setzt den Wert einer Variablen an die Stelle im Text ein.", {})]]) card(s, 4.75, 2.4, 4.0, 1.7, "2", "Filter anwenden", - [("{{ wert | filter }}", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" transformiert Werte (z.B. ", {}), - ("upper", {"font": FONT_MONO}), - (", ", {}), - ("default", {"font": FONT_MONO}), - (").", {})]) + [[("{{ wert | filter }}", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" transformiert Werte (z.B. ", {}), + ("upper", {"font": FONT_MONO}), + (", ", {}), + ("default", {"font": FONT_MONO}), + (").", {})]]) card(s, 8.95, 2.4, 3.85, 1.7, "3", "Template-Dateien", - [("Dateien mit Endung ", {}), - (".j2", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" werden vom Modul ", {}), - ("template", {"font": FONT_MONO}), - (" gerendert.", {})]) + [[("Dateien mit Endung ", {}), + (".j2", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" werden vom Modul ", {}), + ("template", {"font": FONT_MONO}), + (" gerendert.", {})]]) code_block(s, 0.55, 4.35, 6.0, [ "# Variablen auflösen", "msg: \"Hallo {{ benutzer }}\"", @@ -596,22 +690,22 @@ code_block(s, 6.85, 4.35, 6.0, [ " root {{ web_root }};", "}", ], font_size=10.5, title="nginx.conf.j2") -footer(s, 9) +footer(s) # =========================================================================== -# FOLIE 10 — Gather Facts +# FOLIE 12 — Gather Facts # =========================================================================== s = new_slide(WHITE) header(s, "Facts", "Gather Facts — Systeminformationen") text(s, 0.55, 1.5, 12.2, 0.7, - [("Ansible sammelt beim Start automatisch ", {}), - ("Facts", {"bold": True}), - (" (Systeminfos) über jeden Host — über das Modul ", {}), - ("setup", {"font": FONT_MONO, "color": DARKRED}), - (", standardmäßig ", {}), - ("gather_facts: true", {"font": FONT_MONO, "color": DARKRED}), - (".", {})], + [[("Ansible sammelt beim Start automatisch ", {}), + ("Facts", {"bold": True}), + (" (Systeminfos) über jeden Host — über das Modul ", {}), + ("setup", {"font": FONT_MONO, "color": DARKRED}), + (", standardmäßig ", {}), + ("gather_facts: true", {"font": FONT_MONO, "color": DARKRED}), + (".", {})]], size=13, color=BLACK, leading=1.15) # Links: Facts als einzelne Spalte (breite Schlüssel-Spalte -> kein Umbruch) @@ -639,11 +733,11 @@ code_block(s, 7.55, 2.4, 5.2, [ "# Datei: /etc/ansible/facts.d/app.fact", "# Abruf: {{ ansible_local.app.version }}", ], font_size=11, title="Zugriff & Custom Facts") -footer(s, 10) +footer(s) # =========================================================================== -# FOLIE 11 — Variablen & Auflösung (Präzedenz) +# FOLIE 13 — Variablen & Auflösung (Präzedenz) # =========================================================================== s = new_slide(LIGHT) header(s, "Variablen", "Variablen definieren & auflösen") @@ -682,21 +776,21 @@ for i, (t, d) in enumerate(prec, 1): text(s, 11.0, yy + 0.02, 1.85, 0.34, d, size=9, color=GRAY, font=FONT_MONO) yy += 0.5 text(s, 6.85, yy + 0.1, 6.0, 0.6, - [("Faustregel: ", {"bold": True, "color": RED}), - ("je spezifischer die Quelle, desto höher die Priorität.", {})], + [[("Faustregel: ", {"bold": True, "color": RED}), + ("je spezifischer die Quelle, desto höher die Priorität.", {})]], size=11, color=GRAY) -footer(s, 11) +footer(s) # =========================================================================== -# FOLIE 12 — FQCN (Definition) +# FOLIE 14 — FQCN (Definition) # =========================================================================== s = new_slide(WHITE) header(s, "FQCN", "FQCN — Fully Qualified Collection Name") rect(s, 0.55, 1.55, 12.2, 0.95, LIGHT, line=BORDER, line_w=1.0, rounded=True, radius=0.1) text(s, 0.85, 1.77, 11.6, 0.55, - [("FQCN = ", {"bold": True, "color": RED}), - ("eindeutige, vollständige Referenz auf ein Modul oder Plugin.", {})], + [[("FQCN = ", {"bold": True, "color": RED}), + ("eindeutige, vollständige Referenz auf ein Modul oder Plugin.", {})]], size=16, color=BLACK) text(s, 0.85, 2.75, 11.6, 0.6, "namespace · collection · modul", size=28, bold=True, color=BLACK) @@ -710,16 +804,16 @@ code_block(s, 0.55, 3.6, 12.2, [ "# copy -> modul (die Funktion)", ], font_size=12, title="Beispiel") text(s, 0.55, 6.15, 12.2, 0.5, - [("NICHT verwechseln mit ", {"bold": True}), - ("FQDN", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" (Fully Qualified Domain Name = Hostname)! Der FQCN macht eindeutig, " - "aus welcher Collection ein Modul stammt.", {})], + [[("NICHT verwechseln mit ", {"bold": True}), + ("FQDN", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" (Fully Qualified Domain Name = Hostname)! Der FQCN macht eindeutig, " + "aus welcher Collection ein Modul stammt.", {})]], size=12.5, color=BLACK) -footer(s, 12) +footer(s) # =========================================================================== -# FOLIE 13 — FQCN (Beispiele & Warum) +# FOLIE 15 — FQCN (Beispiele & Warum) # =========================================================================== s = new_slide(WHITE) header(s, "FQCN", "FQCN in der Praxis") @@ -742,23 +836,23 @@ for fqcn, d in ex: text(s, 7.35, 1.6, 5.4, 0.4, "WARUM FQCN?", size=11, bold=True, color=RED) rect(s, 7.35, 2.1, 5.45, 4.35, LIGHT, line=BORDER, line_w=1.0, rounded=True, radius=0.05) text(s, 7.65, 2.35, 4.9, 3.9, [ - ("Seit Ansible 2.10 sind Module in ", {}), - ("Collections", {"bold": True}), - (" gebündelt.\n\n", {}), - ("Der FQCN macht eindeutig, ", {}), - ("welches Modul", {"bold": True}), - (" gemeint ist.\n\n", {}), - ("Er vermeidet ", {}), - ("Namenskollisionen", {"bold": True}), - (" — mehrere Collections können ein gleichnamiges Modul anbieten.\n\n", {}), - ("Faustregel: ", {"bold": True, "color": RED}), - ("immer den FQCN verwenden, nie die Kurzform.", {}), -], size=12.5, color=BLACK, leading=1.25) -footer(s, 13) + [("Seit Ansible 2.10 sind Module in ", {}), + ("Collections", {"bold": True}), + (" gebündelt.", {})], + [("Der FQCN macht eindeutig, ", {}), + ("welches Modul", {"bold": True}), + (" gemeint ist.", {})], + [("Er vermeidet ", {}), + ("Namenskollisionen", {"bold": True}), + (" — mehrere Collections können ein gleichnamiges Modul anbieten.", {})], + [("Faustregel: ", {"bold": True, "color": RED}), + ("immer den FQCN verwenden, nie die Kurzform.", {})], +], size=12.5, color=BLACK, leading=1.25, space_after=8) +footer(s) # =========================================================================== -# FOLIE 14 — Collections (Definition) +# FOLIE 16 — Collections (Definition) # =========================================================================== s = new_slide(LIGHT) header(s, "Collections", "Was sind Collections?") @@ -778,19 +872,19 @@ cols = [ for i, (t, d) in enumerate(cols): col = i % 3; row = i // 3 card(s, 0.55 + col * 4.2, 3.0 + row * 1.6, 3.95, 1.35, "•", t, d) -footer(s, 14) +footer(s) # =========================================================================== -# FOLIE 15 — Collections (Struktur & Galaxy) +# FOLIE 17 — Collections (Struktur & Galaxy) # =========================================================================== s = new_slide(WHITE) header(s, "Collections", "Collections nutzen") text(s, 0.55, 1.55, 5.8, 0.3, "BEZUGSQUELLE", size=11, bold=True, color=RED) text(s, 0.55, 1.9, 5.8, 0.85, - [("Ansible Galaxy", {"bold": True}), - (" (galaxy.ansible.com) ist der zentrale Hub — vergleichbar mit einem " - "Paket-Manager für Ansible-Inhalte.", {})], + [[("Ansible Galaxy", {"bold": True}), + (" (galaxy.ansible.com) ist der zentrale Hub — vergleichbar mit einem " + "Paket-Manager für Ansible-Inhalte.", {})]], size=12, color=BLACK, leading=1.15) text(s, 0.55, 2.85, 5.8, 0.3, "INSTALLATION", size=11, bold=True, color=RED) code_block(s, 0.55, 3.25, 5.8, [ @@ -805,11 +899,11 @@ code_block(s, 0.55, 3.25, 5.8, [ ], font_size=11, title="galaxy") text(s, 6.85, 1.55, 5.9, 0.3, "NAMENSSCHEMA", size=11, bold=True, color=RED) text(s, 6.85, 1.9, 5.9, 0.45, - [("namespace", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" . ", {"color": BLACK, "bold": True}), - ("name", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (" → z.B. ", {}), - ("ansible.posix", {"font": FONT_MONO, "color": DARKRED, "bold": True})], + [[("namespace", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" . ", {"color": BLACK, "bold": True}), + ("name", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (" → z.B. ", {}), + ("ansible.posix", {"font": FONT_MONO, "color": DARKRED, "bold": True})]], size=14) text(s, 6.85, 2.5, 5.9, 0.3, "AUFBAU EINER COLLECTION", size=11, bold=True, color=RED) code_block(s, 6.85, 2.9, 5.9, [ @@ -821,11 +915,11 @@ code_block(s, 6.85, 2.9, 5.9, [ " docs/", " galaxy.yml", ], font_size=11.5, title="ansible.posix") -footer(s, 15) +footer(s) # =========================================================================== -# FOLIE 16 — Rollen (Konzept) +# FOLIE 18 — Rollen (Konzept) # =========================================================================== s = new_slide(LIGHT) header(s, "Rollen", "Wie funktionieren Rollen?") @@ -844,16 +938,16 @@ points = [ for i, (t, d) in enumerate(points): col = i % 2; row = i // 2 card(s, 0.55 + col * 6.2, 3.0 + row * 1.8, 5.95, 1.55, "✓", t, d) -footer(s, 16) +footer(s) # =========================================================================== -# FOLIE 17 — Rollen (Verzeichnisstruktur) +# FOLIE 19 — Rollen (Verzeichnisstruktur) # =========================================================================== s = new_slide(WHITE) header(s, "Rollen", "Die Verzeichnisstruktur einer Rolle") text(s, 0.55, 1.55, 5.5, 0.3, "ANATOMIE", size=11, bold=True, color=RED) -text(s, 0.55, 1.9, 5.5, 0.9, +text(s, 0.55, 1.9, 5.5, 0.6, "Eine Rolle folgt einem festen Aufbau. Jede Datei hat eine klar definierte " "Aufgabe — Ansible lädt sie automatisch.", size=12, color=BLACK, leading=1.15) @@ -886,25 +980,25 @@ code_block(s, 6.7, 1.55, 6.1, [ " meta/", " main.yml", ], font_size=11.5, title="roles/webserver/") -footer(s, 17) +footer(s) # =========================================================================== -# FOLIE 18 — Praxisbeispiel +# FOLIE 20 — Praxisbeispiel # =========================================================================== s = new_slide(LIGHT) header(s, "Praxis", "Alles zusammen: Playbook mit Rolle") text(s, 0.55, 1.55, 5.3, 0.3, "ZUSAMMENSPIEL", size=11, bold=True, color=RED) -text(s, 0.55, 1.9, 5.3, 2.8, - [("Das Playbook referenziert die Rolle ", {}), - ("webserver", {"font": FONT_MONO, "color": DARKRED, "bold": True}), - (". FQCN-Module (", {}), - ("ansible.builtin.*", {"font": FONT_MONO, "color": DARKRED}), - (") arbeiten im Hintergrund.\n\n", {}), - ("1.", {"bold": True, "color": RED}), (" Rolle wird geladen.\n", {}), - ("2.", {"bold": True, "color": RED}), (" Aufgaben & Variablen aus der Rolle gelten.\n", {}), - ("3.", {"bold": True, "color": RED}), (" Idempotenz verhindert doppelte Arbeit.", {})], - size=12, color=BLACK, leading=1.25) +text(s, 0.55, 1.9, 5.3, 2.8, [ + [("Das Playbook referenziert die Rolle ", {}), + ("webserver", {"font": FONT_MONO, "color": DARKRED, "bold": True}), + (". FQCN-Module (", {}), + ("ansible.builtin.*", {"font": FONT_MONO, "color": DARKRED}), + (") arbeiten im Hintergrund.", {})], + [("1.", {"bold": True, "color": RED}), (" Rolle wird geladen.", {})], + [("2.", {"bold": True, "color": RED}), (" Aufgaben & Variablen aus der Rolle gelten.", {})], + [("3.", {"bold": True, "color": RED}), (" Idempotenz verhindert doppelte Arbeit.", {})], +], size=12, color=BLACK, leading=1.25, space_after=6) code_block(s, 6.15, 1.55, 6.6, [ "---", "- name: Webserver ausrollen", @@ -917,11 +1011,11 @@ code_block(s, 6.15, 1.55, 6.6, [ " vars:", " nginx_port: 8080", ], font_size=11, title="deploy.yml") -footer(s, 18) +footer(s) # =========================================================================== -# FOLIE 19 — Zusammenfassung & Quellen +# FOLIE 21 — Zusammenfassung & Quellen # =========================================================================== s = new_slide(LIGHT) header(s, "Fazit", "Zusammenfassung") @@ -949,7 +1043,7 @@ text(s, 10.05, 3.95, 2.5, 1.9, ["docs.ansible.com", "galaxy.ansible.com", "github.com/ansible", "Logo: Wikimedia Commons"], size=9.5, color=GRAY, leading=1.4) -footer(s, 19) +footer(s) # --------------------------------------------------------------------------- diff --git a/handout.docx b/handout.docx index 8441ee4a45963267b1bbf9748c11034adbe64fbf..2c32f802b4b2afcc155d35f1270a7a09901575bc 100644 GIT binary patch delta 6558 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 P!3YsiHnd>KpV9vVT%HF7 delta 5660 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 diff --git a/handout.md b/handout.md index ee4dae7..75af84b 100644 --- a/handout.md +++ b/handout.md @@ -1,6 +1,6 @@ # Ansible — Syntax & Variablen-Handout -Kompakte Referenz zu YAML-Syntax, Ad-hoc-Befehlen, Jinja2, Facts, Variablen-Auflösung und FQCN. +Kompakte Referenz zu YAML-Syntax, Ad-hoc-Befehlen, Jinja2, Facts, Variablen-Auflösung, FQCN und ansible.cfg. --- @@ -195,7 +195,54 @@ ansible.builtin.apt: --- -## 8. Vollständiges Beispiel +## 8. ansible.cfg — Konfiguration + +INI-Datei, die Ansible global steuert. Ansible nutzt die **erste** gefundene +Datei (kein Zusammenführen): + +1. `ANSIBLE_CONFIG` — Umgebungsvariable (expliziter Pfad) +2. `./ansible.cfg` — aktuelles Verzeichnis (Projekt) +3. `~/.ansible.cfg` — Home-Verzeichnis (Benutzer) +4. `/etc/ansible/ansible.cfg` — systemweit (Fallback) + +Wichtige Werte: + +| Sektion | Schlüssel | Bedeutung | +|---------------------------|--------------------|------------------------------------| +| `[defaults]` | `inventory` | Pfad zur Inventory-Datei | +| | `remote_user` | Standard-SSH-Benutzer | +| | `forks` | parallele Prozesse (Default 5) | +| | `host_key_checking`| SSH-Key-Prüfung (True/False) | +| | `gather_facts` | Facts automatisch sammeln | +| | `roles_path` | Suchpfad für Rollen | +| `[privilege_escalation]` | `become` | sudo aktivieren | +| | `become_method` | sudo / su | +| | `become_user` | Ziel-Benutzer (Default root) | +| `[ssh_connection]` | `pipelining` | Performance-Optimierung | +| | `ssh_args` | zusätzliche SSH-Argumente | + +Beispiel: + +```ini +[defaults] +inventory = ./inventory.yml +remote_user = admin +forks = 20 +host_key_checking = False +gather_facts = True +roles_path = ./roles + +[privilege_escalation] +become = True +become_method = sudo + +[ssh_connection] +pipelining = True +``` + +--- + +## 9. Vollständiges Beispiel **Playbook** (`deploy.yml`):