Agent2_Ansible : spécialiste Ansible pour l'automatisation du réseau local
- agent2_ansible.py : script principal (XMPP + MQTT) - config/system_prompt.txt : prompt spécialisé Ansible - skills/ansible_exec.py : ANSIBLE: (ad-hoc) + PLAYBOOK: (playbooks) - skills/memory.py, prompt_memory.py : chemins corrigés pour agent2_ansible - ansible/ansible.cfg + inventory/hosts : configuration de base Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,11 +10,11 @@ from pathlib import Path
|
|||||||
from slixmpp import ClientXMPP
|
from slixmpp import ClientXMPP
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
|
|
||||||
sys.path.insert(0, "/opt/agent2_debian13")
|
sys.path.insert(0, "/opt/agent2_ansible")
|
||||||
from skills.loader import load_skills, run_skills
|
from skills.loader import load_skills, run_skills
|
||||||
|
|
||||||
# ── CONFIG ───────────────────────────────────────────────────────────────
|
# ── CONFIG ───────────────────────────────────────────────────────────────
|
||||||
CONFIG_DIR = Path("/opt/agent2_debian13/config")
|
CONFIG_DIR = Path("/opt/agent2_ansible/config")
|
||||||
CONFIG_FILE = CONFIG_DIR / "config.json"
|
CONFIG_FILE = CONFIG_DIR / "config.json"
|
||||||
PROMPT_FILE = CONFIG_DIR / "system_prompt.txt"
|
PROMPT_FILE = CONFIG_DIR / "system_prompt.txt"
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ class AgentBot(ClientXMPP):
|
|||||||
self.send_presence()
|
self.send_presence()
|
||||||
await self.get_roster()
|
await self.get_roster()
|
||||||
self.send_message(mto=ADMIN_JID,
|
self.send_message(mto=ADMIN_JID,
|
||||||
mbody="Agent2_Debian13 en ligne !",
|
mbody="Agent2_Ansible en ligne !",
|
||||||
mtype='chat')
|
mtype='chat')
|
||||||
|
|
||||||
async def message(self, msg):
|
async def message(self, msg):
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = /opt/agent2_ansible/ansible/inventory
|
||||||
|
roles_path = /opt/agent2_ansible/ansible/roles
|
||||||
|
host_key_checking = False
|
||||||
|
retry_files_enabled = False
|
||||||
|
stdout_callback = yaml
|
||||||
|
timeout = 60
|
||||||
|
|
||||||
|
[privilege_escalation]
|
||||||
|
become = False
|
||||||
|
become_method = sudo
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Inventaire Ansible - Réseau local
|
||||||
|
# Ajouter les hôtes selon l'infrastructure réelle
|
||||||
|
|
||||||
|
[local]
|
||||||
|
localhost ansible_connection=local
|
||||||
|
|
||||||
|
[servers]
|
||||||
|
# exemple : srv1 ansible_host=192.168.7.10 ansible_user=root
|
||||||
|
# exemple : srv2 ansible_host=192.168.7.11 ansible_user=debian
|
||||||
|
|
||||||
|
[workstations]
|
||||||
|
# exemple : pc1 ansible_host=192.168.7.50 ansible_user=sylvain
|
||||||
|
|
||||||
|
[all:vars]
|
||||||
|
ansible_python_interpreter=/usr/bin/python3
|
||||||
+39
-21
@@ -1,35 +1,52 @@
|
|||||||
Tu es agent2_debian13, un agent autonome spécialisé dans l'administration de systèmes Debian.
|
Tu es agent2_ansible, un agent autonome spécialisé dans l'automatisation et l'orchestration d'infrastructure via Ansible.
|
||||||
Tu travailles sous les ordres d'agent1 qui te délègue des tâches via MQTT.
|
Tu travailles sous les ordres d'agent1 qui te délègue des tâches via MQTT.
|
||||||
Tu as accès au système réel et peux exécuter des commandes shell.
|
Tu gères les machines du réseau local via Ansible (playbooks, modules ad-hoc, inventaire).
|
||||||
|
|
||||||
Tes domaines de compétence :
|
Tes domaines de compétence :
|
||||||
- Gestion des paquets : apt, dpkg, snap
|
- Exécution de playbooks Ansible sur les hôtes du réseau local
|
||||||
- Services systemd : start, stop, enable, status, journalctl
|
- Commandes ad-hoc Ansible (ping, shell, copy, apt, service, etc.)
|
||||||
- Conteneurs : LXC, LXD, Docker sur Debian
|
- Gestion de l'inventaire Ansible
|
||||||
- Machines virtuelles : KVM/QEMU, libvirt
|
- Déploiement de configurations sur plusieurs machines simultanément
|
||||||
- Réseau Debian : interfaces, /etc/network, NetworkManager
|
- Installation et gestion de paquets à distance
|
||||||
- Sécurité : ufw, fail2ban, SSH, sudoers
|
- Gestion de services systemd à distance
|
||||||
- Fichiers de config système : fstab, crontab, hosts
|
- Copie et gestion de fichiers sur les hôtes distants
|
||||||
- Surveillance : top, htop, df, du, netstat, ss
|
- Collecte de facts (informations système) sur les hôtes
|
||||||
|
|
||||||
Formats de commandes disponibles :
|
Formats de commandes disponibles :
|
||||||
|
|
||||||
EXEC: <commande shell>
|
ANSIBLE: <arguments>
|
||||||
→ Exécuter une commande sur le système et récupérer le résultat
|
→ Exécute une commande ansible (ad-hoc) sur les hôtes
|
||||||
→ Exemples :
|
→ Exemples :
|
||||||
EXEC: systemctl status nginx
|
ANSIBLE: all -m ping
|
||||||
EXEC: apt install -y curl
|
ANSIBLE: all -m shell -a "uptime"
|
||||||
EXEC: docker ps -a
|
ANSIBLE: webservers -m apt -a "name=nginx state=present" --become
|
||||||
EXEC: journalctl -u ssh --no-pager -n 20
|
ANSIBLE: all -m gather_facts --tree /tmp/facts
|
||||||
|
ANSIBLE: all -m service -a "name=nginx state=restarted" --become
|
||||||
|
|
||||||
|
PLAYBOOK: <playbook.yml> [options]
|
||||||
|
→ Exécute un playbook Ansible
|
||||||
|
→ Les playbooks sont dans /opt/agent2_ansible/ansible/playbooks/
|
||||||
|
→ Exemples :
|
||||||
|
PLAYBOOK: site.yml
|
||||||
|
PLAYBOOK: deploy.yml --limit webservers
|
||||||
|
PLAYBOOK: update.yml --tags packages
|
||||||
|
PLAYBOOK: hardening.yml --check
|
||||||
|
|
||||||
|
EXEC: <commande shell>
|
||||||
|
→ Exécuter une commande locale (utile pour inspecter l'inventaire, les logs, etc.)
|
||||||
|
→ Exemples :
|
||||||
|
EXEC: ansible-inventory --list
|
||||||
|
EXEC: cat /opt/agent2_ansible/ansible/inventory/hosts
|
||||||
|
EXEC: ls /opt/agent2_ansible/ansible/playbooks/
|
||||||
|
|
||||||
SEARCH: <requête>
|
SEARCH: <requête>
|
||||||
→ Recherche web si besoin de documentation
|
→ Recherche web si besoin de documentation Ansible
|
||||||
|
|
||||||
READ: <url>
|
READ: <url>
|
||||||
→ Lire une page de documentation
|
→ Lire une page de documentation
|
||||||
|
|
||||||
REMEMBER: <clé> | <valeur>
|
REMEMBER: <clé> | <valeur>
|
||||||
→ Mémoriser une information
|
→ Mémoriser une information (ex: IP d'un hôte, configuration)
|
||||||
|
|
||||||
RECALL: <clé>
|
RECALL: <clé>
|
||||||
→ Récupérer une information mémorisée
|
→ Récupérer une information mémorisée
|
||||||
@@ -37,9 +54,10 @@ RECALL: <clé>
|
|||||||
⚠ RÈGLES :
|
⚠ RÈGLES :
|
||||||
- Tu reçois des tâches d'agent1 via MQTT et tu lui réponds via MQTT
|
- Tu reçois des tâches d'agent1 via MQTT et tu lui réponds via MQTT
|
||||||
- Tu peux aussi recevoir des instructions directement de sylvain via XMPP
|
- Tu peux aussi recevoir des instructions directement de sylvain via XMPP
|
||||||
- Pour toute tâche système : utilise EXEC: pour l'exécuter réellement, pas juste expliquer
|
- Pour toute tâche Ansible : utilise ANSIBLE: ou PLAYBOOK: pour l'exécuter réellement
|
||||||
- Enchaîne plusieurs EXEC: si nécessaire pour accomplir une tâche complexe
|
- Enchaîne plusieurs commandes si nécessaire pour accomplir une tâche complexe
|
||||||
- Vérifie toujours le résultat d'une commande avant de passer à la suivante
|
- Vérifie toujours le résultat d'une commande avant de passer à la suivante
|
||||||
- Si une commande échoue, analyse l'erreur et adapte-toi
|
- Si une commande échoue, analyse l'erreur et adapte-toi
|
||||||
- Signale à agent1 si une tâche est hors de ton domaine Debian
|
- Signale à agent1 si une tâche est hors de ton domaine Ansible
|
||||||
- Réponds toujours en français avec un résumé clair de ce qui a été fait
|
- Réponds toujours en français avec un résumé clair de ce qui a été fait
|
||||||
|
- Pour les opérations risquées (suppression, modification critique), utilise --check d'abord
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
"""
|
||||||
|
Skill : ANSIBLE / PLAYBOOK
|
||||||
|
Exécute des commandes Ansible (ad-hoc ou playbooks) sur les hôtes du réseau local.
|
||||||
|
|
||||||
|
Commandes :
|
||||||
|
ANSIBLE: <arguments>
|
||||||
|
→ Exécute ansible avec les arguments fournis
|
||||||
|
→ Exemples :
|
||||||
|
ANSIBLE: all -m ping
|
||||||
|
ANSIBLE: all -m shell -a "uptime"
|
||||||
|
ANSIBLE: webservers -m apt -a "name=nginx state=present" --become
|
||||||
|
|
||||||
|
PLAYBOOK: <playbook.yml> [options]
|
||||||
|
→ Exécute ansible-playbook depuis le dossier playbooks/
|
||||||
|
→ Exemples :
|
||||||
|
PLAYBOOK: site.yml
|
||||||
|
PLAYBOOK: deploy.yml --limit webservers --tags packages
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
SKILL_NAME = "ansible_exec"
|
||||||
|
TRIGGER = None
|
||||||
|
TRIGGERS = {
|
||||||
|
"ANSIBLE:": "ansible_adhoc",
|
||||||
|
"PLAYBOOK:": "ansible_playbook",
|
||||||
|
}
|
||||||
|
|
||||||
|
ANSIBLE_DIR = Path("/opt/agent2_ansible/ansible")
|
||||||
|
PLAYBOOKS_DIR = ANSIBLE_DIR / "playbooks"
|
||||||
|
ANSIBLE_CFG = ANSIBLE_DIR / "ansible.cfg"
|
||||||
|
|
||||||
|
TIMEOUT = 120 # secondes (les commandes réseau peuvent être longues)
|
||||||
|
MAX_CHARS = 5000
|
||||||
|
|
||||||
|
# Variables d'environnement pour ansible
|
||||||
|
import os
|
||||||
|
ANSIBLE_ENV = {
|
||||||
|
**os.environ,
|
||||||
|
"ANSIBLE_CONFIG": str(ANSIBLE_CFG),
|
||||||
|
"ANSIBLE_FORCE_COLOR": "0",
|
||||||
|
"ANSIBLE_NOCOLOR": "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _run(cmd: list) -> str:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=TIMEOUT,
|
||||||
|
env=ANSIBLE_ENV,
|
||||||
|
cwd=str(ANSIBLE_DIR),
|
||||||
|
)
|
||||||
|
stdout = result.stdout.strip()
|
||||||
|
stderr = result.stderr.strip()
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
if stdout:
|
||||||
|
output += stdout
|
||||||
|
if stderr:
|
||||||
|
output += ("\n[stderr] " + stderr) if output else "[stderr] " + stderr
|
||||||
|
if not output:
|
||||||
|
output = "(aucune sortie)"
|
||||||
|
|
||||||
|
if len(output) > MAX_CHARS:
|
||||||
|
output = output[:MAX_CHARS] + "\n...[tronqué]"
|
||||||
|
|
||||||
|
status = "OK" if result.returncode == 0 else "Erreur (code {})".format(result.returncode)
|
||||||
|
return "[{}] $ {}\n{}".format(status, " ".join(cmd), output)
|
||||||
|
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
return "Timeout : la commande a dépassé {}s.".format(TIMEOUT)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return "Erreur : ansible n'est pas installé ou introuvable dans le PATH."
|
||||||
|
except Exception as e:
|
||||||
|
return "Erreur d'exécution : {}".format(e)
|
||||||
|
|
||||||
|
|
||||||
|
def ansible_adhoc(args: str) -> str:
|
||||||
|
args = args.strip()
|
||||||
|
if not args:
|
||||||
|
return "Erreur : arguments vides. Exemple : ANSIBLE: all -m ping"
|
||||||
|
cmd = ["ansible"] + args.split()
|
||||||
|
return _run(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def ansible_playbook(args: str) -> str:
|
||||||
|
args = args.strip()
|
||||||
|
if not args:
|
||||||
|
return "Erreur : playbook non spécifié. Exemple : PLAYBOOK: site.yml"
|
||||||
|
|
||||||
|
parts = args.split()
|
||||||
|
playbook = parts[0]
|
||||||
|
options = parts[1:]
|
||||||
|
|
||||||
|
# Chemin absolu si non fourni
|
||||||
|
playbook_path = Path(playbook)
|
||||||
|
if not playbook_path.is_absolute():
|
||||||
|
playbook_path = PLAYBOOKS_DIR / playbook
|
||||||
|
|
||||||
|
if not playbook_path.exists():
|
||||||
|
return "Erreur : playbook introuvable : {}".format(playbook_path)
|
||||||
|
|
||||||
|
cmd = ["ansible-playbook", str(playbook_path)] + options
|
||||||
|
return _run(cmd)
|
||||||
+1
-1
@@ -9,7 +9,7 @@ SKILL_NAME = "memory"
|
|||||||
TRIGGER = None
|
TRIGGER = None
|
||||||
TRIGGERS = {"REMEMBER:": "remember", "RECALL:": "recall"}
|
TRIGGERS = {"REMEMBER:": "remember", "RECALL:": "recall"}
|
||||||
|
|
||||||
DB_PATH = Path("/opt/agent2_debian13/memory.db")
|
DB_PATH = Path("/opt/agent2_ansible/memory.db")
|
||||||
|
|
||||||
def _get_conn():
|
def _get_conn():
|
||||||
conn = sqlite3.connect(DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ TRIGGERS = {
|
|||||||
"PROMPT_DEL:": "prompt_del",
|
"PROMPT_DEL:": "prompt_del",
|
||||||
}
|
}
|
||||||
|
|
||||||
DB_PATH = Path("/opt/agent2_debian13/chroma_db")
|
DB_PATH = Path("/opt/agent2_ansible/chroma_db")
|
||||||
|
|
||||||
# Phase 1 : embedding factice (hash MD5 → vecteur 16 dims)
|
# Phase 1 : embedding factice (hash MD5 → vecteur 16 dims)
|
||||||
# Phase 2 : remplacer par un vrai modèle (ex: sentence-transformers)
|
# Phase 2 : remplacer par un vrai modèle (ex: sentence-transformers)
|
||||||
|
|||||||
Reference in New Issue
Block a user