Dieser Teil ist für fortgeschrittene Anwender und größere Organisationen gedacht, die Plugins professionell entwickeln und verteilen möchten.
Entscheidungsbaum:
Brauche ich erweiterte Plugin-Features?
├─ Mehrere Teams nutzen ähnliche Plugins? → Collections
├─ Proprietäre Hardware ohne SSH/WinRM? → Connection-Plugins
├─ Dynamische Cloud-Infrastruktur mit CMDB? → Inventory-Plugins
├─ Produktive Plugin-Entwicklung im Team? → Best Practices
└─ Standard-Plugins reichen aus? → Stopp hier, Teil 4 nicht nötig
Relevante Szenarien:
Ziel: Security-Plugins als Collection verpacken
Struktur:
collections/ansible_collections/company/security/
├── galaxy.yml # Metadaten
├── plugins/
│ ├── filter/
│ │ ├── password_strength.py # Passwort-Validierung
│ │ └── crypto_utils.py # Hash-Funktionen
│ ├── lookup/
│ │ └── vault_api.py # HashiCorp Vault
│ └── callback/
│ └── audit_logger.py # Compliance-Logging
└── docs/
└── README.md # Nutzungsdokumentation
Minimal-Konfiguration (galaxy.yml):
namespace: company
name: security
version: 1.0.0
description: Security-Plugins für Ansible
authors:
- "Security Team <security@company.com>"
dependencies:
"community.general": ">=5.0.0"
tags: [security, vault, compliance]Verwendung:
---
- name: Security Collection verwenden
hosts: localhost
collections:
- company.security
tasks:
- name: Passwort validieren
debug:
msg: "Stark: {{ 'MyPassword123!' | password_strength > 80 }}"
- name: Vault-Secret laden
set_fact:
api_key: "{{ lookup('vault_api', 'secret/api/key') }}"Seltene, aber wichtige Fälle:
Problemstellung: Netzwerk-Appliance nur über REST-API steuerbar
# plugins/connection/rest_api.py (vereinfacht)
from ansible.plugins.connection import ConnectionBase
class Connection(ConnectionBase):
transport = 'rest_api'
def exec_command(self, cmd, in_data=None, sudoable=True):
# Command als API-Call ausführen
payload = {'command': cmd}
response = self._api_request('POST', '/execute', payload)
return response['exit_code'], response['stdout'], response['stderr']
def _api_request(self, method, endpoint, data=None):
# HTTP-Request an Gerät
# Implementierung abhängig von Geräte-API
passAnwendung:
# inventory
[appliances]
firewall01 ansible_connection=rest_api ansible_host=192.168.1.1Realitätscheck: In 99% der Fälle reicht das
uri-Modul aus.
Typische Anwendungsfälle:
Problemstellung: Hosts kommen aus internem CMDB-System
# plugins/inventory/company_cmdb.py (vereinfacht)
from ansible.plugins.inventory import BaseInventoryPlugin
class InventoryModule(BaseInventoryPlugin):
NAME = 'company_cmdb'
def parse(self, inventory, loader, path, cache=True):
# CMDB-API abfragen
servers = self._fetch_servers_from_cmdb()
for server in servers:
# Host hinzufügen
inventory.add_host(server['hostname'])
inventory.set_variable(server['hostname'], 'ansible_host', server['ip'])
# Gruppierung nach Umgebung
env_group = f"env_{server['environment']}"
inventory.add_group(env_group)
inventory.add_child(env_group, server['hostname'])Konfiguration (inventory.yml):
plugin: company.infrastructure.company_cmdb
cmdb_url: https://cmdb.company.com/api
environment_filter: [production, staging]Minimales Testing-Setup:
# tests/test_filters.py
import pytest
from plugins.filter.string_utils import to_slug
def test_to_slug_basic():
assert to_slug('My Service!') == 'my-service'
def test_to_slug_error():
with pytest.raises(Exception):
to_slug(123)Test ausführen:
pip install pytest
pytest tests/Minimal-Pipeline
(.github/workflows/test.yml):
name: Test Plugins
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install ansible pytest
- name: Run tests
run: pytest tests/
- name: Test plugin in playbook
run: ansible-playbook test-plugins.ymlPlugin-Metriken sammeln:
# plugins/callback/performance_monitor.py (vereinfacht)
class CallbackModule(CallbackBase):
def v2_runner_on_ok(self, result):
# Plugin-Nutzung tracken
if 'lookup(' in str(result._task.args):
plugin_name = self._extract_plugin_name(result)
duration = getattr(result, '_duration', 0)
# Metriken senden (Prometheus, DataDog, etc.)
self._send_metric('plugin_execution_time', duration,
tags={'plugin': plugin_name})Mehrstufiges Rollout:
# 1. Entwicklung: Lokale Tests
ansible-playbook test.yml --check
# 2. Staging: Collection-Beta
ansible-galaxy collection install company.utils:1.1.0-beta
# 3. Produktion: Stable Release
ansible-galaxy collection install company.utils:1.1.0Lohnt sich bei:
Lohnt sich nicht bei:
Aktuelle Trends (2024/2025):
Plugin-Code ist Infrastruktur-Code:
Empfohlener Entwicklungspfad:
Realitätscheck: 90% aller Organisationen brauchen nur:
Collections, Connection- und Inventory-Plugins sind Spezialdisziplinen für große Organisationen mit sehr spezifischen Anforderungen.
Die meisten Plugin-Anforderungen lassen sich mit den Grundlagen aus Teil 1-3 lösen.