|
|
|
|
@ -49,6 +49,10 @@ except ImportError:
|
|
|
|
|
# CONFIGURATION SH DEPLOYER
|
|
|
|
|
# ============================================
|
|
|
|
|
|
|
|
|
|
# Chemins Splunk
|
|
|
|
|
SPLUNK_HOME = os.environ.get('SPLUNK_HOME', '/opt/splunk')
|
|
|
|
|
APP_HOME = os.path.join(SPLUNK_HOME, 'etc', 'apps', 'pusher_app_prem')
|
|
|
|
|
|
|
|
|
|
# Configuration du SH Deployer (peut être surchargée par les paramètres)
|
|
|
|
|
SH_DEPLOYER_CONFIG = {
|
|
|
|
|
"enabled": True,
|
|
|
|
|
@ -132,6 +136,31 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
response = {"hostname": get_splunk_hostname()}
|
|
|
|
|
self.wfile.write(json.dumps(response).encode())
|
|
|
|
|
|
|
|
|
|
elif path == '/license/file':
|
|
|
|
|
# Charger la licence depuis le fichier sur le serveur
|
|
|
|
|
license_file = os.path.join(APP_HOME, 'local', 'license.lic')
|
|
|
|
|
|
|
|
|
|
if os.path.exists(license_file):
|
|
|
|
|
try:
|
|
|
|
|
with open(license_file, 'r') as f:
|
|
|
|
|
license_content = f.read()
|
|
|
|
|
response = {
|
|
|
|
|
"success": True,
|
|
|
|
|
"content": license_content
|
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
response = {
|
|
|
|
|
"success": False,
|
|
|
|
|
"error": f"Erreur lecture fichier: {str(e)}"
|
|
|
|
|
}
|
|
|
|
|
else:
|
|
|
|
|
response = {
|
|
|
|
|
"success": False,
|
|
|
|
|
"error": "Aucun fichier de licence sur le serveur"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.wfile.write(json.dumps(response).encode())
|
|
|
|
|
|
|
|
|
|
elif path == '/health':
|
|
|
|
|
# Health check
|
|
|
|
|
response = {
|
|
|
|
|
@ -214,8 +243,9 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
# ENDPOINTS LICENCE
|
|
|
|
|
# ============================================
|
|
|
|
|
|
|
|
|
|
if path == '/license/upload':
|
|
|
|
|
# Uploader une nouvelle licence
|
|
|
|
|
if path == '/license/upload' or path == '/license/save':
|
|
|
|
|
# Sauvegarder la licence sur le serveur (fichier)
|
|
|
|
|
# La validation RSA est faite côté client
|
|
|
|
|
content_length = int(self.headers.get('Content-Length', 0))
|
|
|
|
|
body = self.rfile.read(content_length).decode('utf-8')
|
|
|
|
|
|
|
|
|
|
@ -228,16 +258,40 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
if not license_content:
|
|
|
|
|
response = {"success": False, "error": "Contenu de licence vide"}
|
|
|
|
|
else:
|
|
|
|
|
response = save_license_file(license_content)
|
|
|
|
|
# Sauvegarder le fichier de licence
|
|
|
|
|
try:
|
|
|
|
|
local_dir = os.path.join(APP_HOME, 'local')
|
|
|
|
|
os.makedirs(local_dir, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
license_path = os.path.join(local_dir, 'license.lic')
|
|
|
|
|
|
|
|
|
|
with open(license_path, 'w') as f:
|
|
|
|
|
f.write(license_content)
|
|
|
|
|
|
|
|
|
|
os.chmod(license_path, 0o600)
|
|
|
|
|
|
|
|
|
|
logger.info(f"Licence sauvegardée: {license_path}")
|
|
|
|
|
response = {
|
|
|
|
|
"success": True,
|
|
|
|
|
"message": "Licence sauvegardée sur le serveur",
|
|
|
|
|
"path": license_path
|
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Erreur sauvegarde licence: {e}")
|
|
|
|
|
response = {
|
|
|
|
|
"success": False,
|
|
|
|
|
"error": f"Erreur sauvegarde: {str(e)}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.wfile.write(json.dumps(response).encode())
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
elif path == '/license/delete':
|
|
|
|
|
# Supprimer la licence
|
|
|
|
|
license_path = "/opt/splunk/etc/apps/pusher_app/local/license.lic"
|
|
|
|
|
license_path = os.path.join(APP_HOME, 'local', 'license.lic')
|
|
|
|
|
if os.path.exists(license_path):
|
|
|
|
|
os.remove(license_path)
|
|
|
|
|
logger.info(f"Licence supprimée: {license_path}")
|
|
|
|
|
response = {"success": True, "message": "Licence supprimée"}
|
|
|
|
|
else:
|
|
|
|
|
response = {"success": False, "error": "Aucune licence à supprimer"}
|
|
|
|
|
@ -346,27 +400,46 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
|
|
|
|
|
# Copier les applications
|
|
|
|
|
logger.info("Copying applications to repository...")
|
|
|
|
|
apps_copied = 0
|
|
|
|
|
for app_data in app_directories:
|
|
|
|
|
app_name = app_data['name']
|
|
|
|
|
app_path = app_data['path']
|
|
|
|
|
dest_path = os.path.join(apps_dir, app_name)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(app_path):
|
|
|
|
|
# Supprimer l'ancienne version si elle existe
|
|
|
|
|
if os.path.exists(dest_path):
|
|
|
|
|
logger.info(f"Removing old version of {app_name}")
|
|
|
|
|
shutil.rmtree(dest_path)
|
|
|
|
|
|
|
|
|
|
# Copier la nouvelle version
|
|
|
|
|
shutil.copytree(app_path, dest_path)
|
|
|
|
|
logger.info(f"Copied app: {app_name}")
|
|
|
|
|
apps_copied += 1
|
|
|
|
|
|
|
|
|
|
# Compter les fichiers copiés
|
|
|
|
|
file_count = sum(len(files) for _, _, files in os.walk(dest_path))
|
|
|
|
|
logger.info(f"Copied app: {app_name} ({file_count} files)")
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(f"App path not found: {app_path}")
|
|
|
|
|
|
|
|
|
|
logger.info(f"Total apps copied: {apps_copied}")
|
|
|
|
|
|
|
|
|
|
# Configurer git
|
|
|
|
|
subprocess.run(['git', 'config', 'user.email', 'splunk@splunk.local'],
|
|
|
|
|
cwd=temp_dir, capture_output=True)
|
|
|
|
|
subprocess.run(['git', 'config', 'user.name', 'Splunk Git Pusher'],
|
|
|
|
|
cwd=temp_dir, capture_output=True)
|
|
|
|
|
|
|
|
|
|
# Commit et push
|
|
|
|
|
subprocess.run(['git', 'add', '-A'], cwd=temp_dir, capture_output=True)
|
|
|
|
|
# Ajouter TOUS les fichiers (y compris les suppressions)
|
|
|
|
|
subprocess.run(['git', 'add', '--all'], cwd=temp_dir, capture_output=True)
|
|
|
|
|
|
|
|
|
|
# Afficher le statut Git pour debug
|
|
|
|
|
status_check = subprocess.run(['git', 'status', '--short'],
|
|
|
|
|
cwd=temp_dir, capture_output=True, text=True)
|
|
|
|
|
if status_check.stdout.strip():
|
|
|
|
|
logger.info(f"Git changes detected:\n{status_check.stdout[:500]}")
|
|
|
|
|
else:
|
|
|
|
|
logger.info("No Git changes detected")
|
|
|
|
|
|
|
|
|
|
# Message de commit avec infos de licence (envoyées par le client)
|
|
|
|
|
full_message = f"{commit_message}\n\n"
|
|
|
|
|
@ -374,21 +447,34 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
full_message += f"License: {license_id or 'N/A'} ({license_type or 'N/A'})\n"
|
|
|
|
|
full_message += f"Timestamp: {datetime.now().isoformat()}"
|
|
|
|
|
|
|
|
|
|
result = subprocess.run(['git', 'commit', '-m', full_message],
|
|
|
|
|
cwd=temp_dir, capture_output=True, text=True)
|
|
|
|
|
# Vérifier s'il y a des changements à committer
|
|
|
|
|
status_result = subprocess.run(['git', 'status', '--porcelain'],
|
|
|
|
|
cwd=temp_dir, capture_output=True, text=True)
|
|
|
|
|
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
logger.warning(f"Commit warning: {result.stderr}")
|
|
|
|
|
if status_result.stdout.strip():
|
|
|
|
|
# Il y a des changements, faire le commit
|
|
|
|
|
result = subprocess.run(['git', 'commit', '-m', full_message],
|
|
|
|
|
cwd=temp_dir, capture_output=True, text=True)
|
|
|
|
|
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
logger.warning(f"Commit warning: {result.stderr}")
|
|
|
|
|
else:
|
|
|
|
|
logger.info("Commit created successfully")
|
|
|
|
|
else:
|
|
|
|
|
logger.info("No changes detected, skipping commit")
|
|
|
|
|
|
|
|
|
|
logger.info("Pushing to Git...")
|
|
|
|
|
result = subprocess.run(['git', 'push', 'origin', git_branch],
|
|
|
|
|
cwd=temp_dir, capture_output=True, text=True, timeout=60)
|
|
|
|
|
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
raise Exception(f"Push failed: {result.stderr}")
|
|
|
|
|
# Vérifier si c'est juste "Everything up-to-date"
|
|
|
|
|
if "Everything up-to-date" in result.stderr or "Everything up-to-date" in result.stdout:
|
|
|
|
|
logger.info("Repository is already up-to-date")
|
|
|
|
|
else:
|
|
|
|
|
raise Exception(f"Push failed: {result.stderr}")
|
|
|
|
|
|
|
|
|
|
# Incrémenter les stats d'utilisation
|
|
|
|
|
increment_usage()
|
|
|
|
|
# NOTE: L'incrémentation des stats est maintenant faite côté client (JavaScript)
|
|
|
|
|
|
|
|
|
|
logger.info("Git push successful!")
|
|
|
|
|
|
|
|
|
|
|