Git_pusher V2.2

Pushed by: admin
License: TA9O64YS7EPT (Professional)
Timestamp: 2026-02-22T14:16:20.164938
masterdev
Splunk Git Pusher 2 months ago
parent 4a579acde2
commit 621b3ac5d8

@ -3,32 +3,74 @@
// Version 2.1 avec déploiement vers SH Cluster // Version 2.1 avec déploiement vers SH Cluster
// ============================================ // ============================================
// Configuration // Configuration par défaut
const GIT_PUSHER_CONFIG = { const DEFAULT_CONFIG = {
// URL du serveur Git Pusher API api: {
serverUrl: (function() { url: '',
const hostname = window.location.hostname; port: 9999,
const protocol = window.location.protocol; useProxy: true
},
// Si déjà sur le domaine API, l'utiliser directement deployer: {
if (hostname === 'myprivspldev-api.jp-engineering.fr') { enabled: false,
return protocol + '//' + hostname; host: '',
} port: 9998,
token: '',
useSSL: true
}
};
// Si accès via le domaine Splunk principal, utiliser le domaine API // Charger la configuration
if (hostname === 'myprivspldev.jp-engineering.fr') { function loadAppConfig() {
return protocol + '//myprivspldev-api.jp-engineering.fr'; try {
const stored = localStorage.getItem('git_pusher_config');
if (stored) {
return JSON.parse(stored);
} }
} catch (e) {
console.warn('Erreur chargement config localStorage:', e);
}
return DEFAULT_CONFIG;
}
// Si c'est une IP ou localhost, ajouter le port 9999 // Déterminer l'URL du serveur API
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') { function getServerUrl() {
return protocol + '//' + hostname + ':9999'; const config = loadAppConfig();
const hostname = window.location.hostname;
const protocol = window.location.protocol;
// Si une URL est configurée, l'utiliser
if (config.api && config.api.url) {
let url = config.api.url;
// Ajouter le port si pas de proxy
if (!config.api.useProxy && config.api.port) {
url = url.replace(/\/$/, '') + ':' + config.api.port;
} }
return url;
}
// Par défaut, ajouter le port 9999 // Auto-détection basée sur le hostname
// Si accès via le domaine Splunk principal, utiliser le domaine API
if (hostname === 'myprivspldev.jp-engineering.fr') {
return protocol + '//myprivspldev-api.jp-engineering.fr';
}
// Si déjà sur le domaine API
if (hostname === 'myprivspldev-api.jp-engineering.fr') {
return protocol + '//' + hostname;
}
// Si c'est une IP ou localhost, ajouter le port 9999
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
return protocol + '//' + hostname + ':9999'; return protocol + '//' + hostname + ':9999';
})(), }
// Par défaut, ajouter le port 9999
return protocol + '//' + hostname + ':9999';
}
// Configuration
const GIT_PUSHER_CONFIG = {
serverUrl: getServerUrl(),
credentialsKey: 'git_pusher_credentials', credentialsKey: 'git_pusher_credentials',
deployerConfigKey: 'git_pusher_deployer_config', deployerConfigKey: 'git_pusher_deployer_config',
version: '2.1.0' version: '2.1.0'

@ -0,0 +1,381 @@
// ============================================
// GIT PUSHER - CONFIGURATION PAGE
// Version 2.1 - Compatible Splunk
// ============================================
require([
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/simplexml/ready!'
], function($, mvc) {
console.log('Git Pusher Config v2.1 initializing...');
// Configuration par défaut
var DEFAULT_CONFIG = {
api: {
url: '',
port: 9999,
useProxy: true
},
deployer: {
enabled: false,
host: '',
port: 9998,
token: '',
useSSL: true
},
license: {
checkInterval: 24
},
advanced: {
logLevel: 'INFO',
timeout: 30,
gitTimeout: 120
}
};
// URL de l'API pour la config
function getConfigApiUrl() {
var hostname = window.location.hostname;
var protocol = window.location.protocol;
// Essayer de charger depuis localStorage
try {
var stored = localStorage.getItem('git_pusher_config');
if (stored) {
var config = JSON.parse(stored);
if (config.api && config.api.url) {
var url = config.api.url;
if (!config.api.useProxy && config.api.port) {
url = url.replace(/\/$/, '') + ':' + config.api.port;
}
return url;
}
}
} catch(e) {}
// Auto-détection
if (hostname === 'myprivspldev.jp-engineering.fr') {
return protocol + '//myprivspldev-api.jp-engineering.fr';
}
if (hostname === 'myprivspldev-api.jp-engineering.fr') {
return protocol + '//' + hostname;
}
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
return protocol + '//' + hostname + ':9999';
}
return protocol + '//' + hostname + ':9999';
}
// ============================================
// CHARGEMENT DE LA CONFIGURATION
// ============================================
function loadConfig() {
console.log('Loading configuration...');
var apiUrl = getConfigApiUrl();
$.ajax({
url: apiUrl + '/config',
method: 'GET',
dataType: 'json',
success: function(config) {
console.log('Config loaded:', config);
applyConfigToForm(config);
showMessage('Configuration chargée', 'success');
},
error: function(xhr, status, error) {
console.log('No server config, using defaults:', error);
applyConfigToForm(DEFAULT_CONFIG);
}
});
loadLicenseStatus();
}
function applyConfigToForm(config) {
// API
$('#api-url').val(config.api ? config.api.url || '' : '');
$('#api-port').val(config.api ? config.api.port || 9999 : 9999);
$('#use-proxy').prop('checked', config.api ? config.api.useProxy !== false : true);
// Deployer
$('#deployer-enabled').prop('checked', config.deployer ? config.deployer.enabled || false : false);
$('#deployer-host').val(config.deployer ? config.deployer.host || '' : '');
$('#deployer-port').val(config.deployer ? config.deployer.port || 9998 : 9998);
$('#deployer-token').val(config.deployer ? config.deployer.token || '' : '');
$('#deployer-use-ssl').prop('checked', config.deployer ? config.deployer.useSSL !== false : true);
// Licence
$('#license-check-interval').val(config.license ? config.license.checkInterval || 24 : 24);
// Avancé
$('#log-level').val(config.advanced ? config.advanced.logLevel || 'INFO' : 'INFO');
$('#timeout').val(config.advanced ? config.advanced.timeout || 30 : 30);
$('#git-timeout').val(config.advanced ? config.advanced.gitTimeout || 120 : 120);
}
function getConfigFromForm() {
return {
api: {
url: $('#api-url').val().trim(),
port: parseInt($('#api-port').val()) || 9999,
useProxy: $('#use-proxy').is(':checked')
},
deployer: {
enabled: $('#deployer-enabled').is(':checked'),
host: $('#deployer-host').val().trim(),
port: parseInt($('#deployer-port').val()) || 9998,
token: $('#deployer-token').val(),
useSSL: $('#deployer-use-ssl').is(':checked')
},
license: {
checkInterval: parseInt($('#license-check-interval').val()) || 24
},
advanced: {
logLevel: $('#log-level').val(),
timeout: parseInt($('#timeout').val()) || 30,
gitTimeout: parseInt($('#git-timeout').val()) || 120
}
};
}
// ============================================
// SAUVEGARDE DE LA CONFIGURATION
// ============================================
function saveConfig() {
console.log('Saving configuration...');
var config = getConfigFromForm();
var apiUrl = getConfigApiUrl();
$.ajax({
url: apiUrl + '/config',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(config),
dataType: 'json',
success: function(result) {
console.log('Save result:', result);
if (result.success) {
showMessage('✅ Configuration sauvegardée avec succès !', 'success');
// Sauvegarder aussi dans localStorage
localStorage.setItem('git_pusher_config', JSON.stringify(config));
} else {
showMessage('❌ Erreur: ' + (result.error || 'Échec de la sauvegarde'), 'error');
}
},
error: function(xhr, status, error) {
console.error('Save error:', error);
showMessage('❌ Erreur de connexion au serveur: ' + error, 'error');
}
});
}
function resetConfig() {
if (confirm('Voulez-vous vraiment réinitialiser la configuration ?')) {
applyConfigToForm(DEFAULT_CONFIG);
showMessage('Configuration réinitialisée (non sauvegardée)', 'success');
}
}
// ============================================
// TESTS DE CONNEXION
// ============================================
function testApiConnection() {
console.log('Testing API connection...');
var $status = $('#api-status');
$status.removeClass('connected disconnected').text('● Test en cours...');
var apiUrl = $('#api-url').val().trim();
if (!apiUrl) {
apiUrl = getConfigApiUrl();
} else if (!$('#use-proxy').is(':checked')) {
var port = $('#api-port').val() || 9999;
if (apiUrl.indexOf(':' + port) === -1) {
apiUrl = apiUrl.replace(/\/$/, '') + ':' + port;
}
}
console.log('Testing URL:', apiUrl);
$.ajax({
url: apiUrl + '/health',
method: 'GET',
dataType: 'json',
timeout: 10000,
success: function(data) {
console.log('API health:', data);
$status.addClass('connected').text('● Connecté');
},
error: function(xhr, status, error) {
console.error('API test failed:', error);
$status.addClass('disconnected').text('● Échec connexion');
}
});
}
function testDeployerConnection() {
console.log('Testing Deployer connection...');
var $status = $('#deployer-status');
$status.removeClass('connected disconnected').text('● Test en cours...');
var host = $('#deployer-host').val().trim();
var port = $('#deployer-port').val() || 9998;
var useSSL = $('#deployer-use-ssl').is(':checked');
var token = $('#deployer-token').val();
if (!host) {
$status.addClass('disconnected').text('● Adresse manquante');
return;
}
var protocol = useSSL ? 'https' : 'http';
var url = protocol + '://' + host + ':' + port + '/health';
console.log('Testing Deployer URL:', url);
$.ajax({
url: url,
method: 'GET',
dataType: 'json',
timeout: 10000,
headers: {
'X-Auth-Token': token
},
success: function(data) {
console.log('Deployer health:', data);
$status.addClass('connected').text('● Connecté');
},
error: function(xhr, status, error) {
console.error('Deployer test failed:', error);
$status.addClass('disconnected').text('● Échec connexion');
}
});
}
// ============================================
// STATUT DE LA LICENCE
// ============================================
function loadLicenseStatus() {
var $status = $('#license-status');
try {
var stored = localStorage.getItem('git_pusher_license');
if (stored) {
var parsed = JSON.parse(stored);
var licenseData = parsed.licenseData;
if (licenseData) {
var expires = new Date(licenseData.expires);
var now = new Date();
var daysRemaining = Math.ceil((expires - now) / (1000 * 60 * 60 * 24));
if (daysRemaining > 0) {
$status.html(
'<span class="config-status connected">● Active</span>' +
'<br><small>Type: ' + licenseData.type_name + ' | Expire: ' + licenseData.expires + ' (' + daysRemaining + 'j)</small>'
);
} else {
$status.html(
'<span class="config-status disconnected">● Expirée</span>' +
'<br><small>Expirée le ' + licenseData.expires + '</small>'
);
}
return;
}
}
$status.html('<span class="config-status disconnected">● Non installée</span>');
} catch (error) {
console.error('Erreur lecture licence:', error);
$status.html('<span class="config-status disconnected">● Erreur</span>');
}
}
// ============================================
// UTILITAIRES
// ============================================
function showMessage(message, type) {
var $msg = $('#config-message');
$msg.text(message).removeClass('success error').addClass(type).show();
setTimeout(function() {
$msg.fadeOut();
}, 5000);
}
// ============================================
// ATTACHER LES ÉVÉNEMENTS
// ============================================
function attachEvents() {
console.log('Attaching events...');
// Bouton Test API
$('#test-api-btn').on('click', function(e) {
e.preventDefault();
console.log('Test API clicked');
testApiConnection();
});
// Bouton Test Deployer
$('#test-deployer-btn').on('click', function(e) {
e.preventDefault();
console.log('Test Deployer clicked');
testDeployerConnection();
});
// Bouton Sauvegarder
$('#save-btn').on('click', function(e) {
e.preventDefault();
console.log('Save clicked');
saveConfig();
});
// Bouton Réinitialiser
$('#reset-btn').on('click', function(e) {
e.preventDefault();
console.log('Reset clicked');
resetConfig();
});
console.log('Events attached to buttons');
}
// ============================================
// INITIALISATION
// ============================================
// Attendre que le DOM soit complètement prêt
function init() {
if ($('#api-url').length > 0) {
console.log('DOM ready, initializing...');
attachEvents();
loadConfig();
} else {
console.log('DOM not ready, retrying...');
setTimeout(init, 300);
}
}
setTimeout(init, 500);
// Exposer globalement pour le debug
window.gitPusherConfig = {
saveConfig: saveConfig,
resetConfig: resetConfig,
testApiConnection: testApiConnection,
testDeployerConnection: testDeployerConnection,
loadConfig: loadConfig
};
console.log('Git Pusher Config module loaded');
});

@ -3,34 +3,66 @@
// Version 2.1 - 100% Client-Side Validation // Version 2.1 - 100% Client-Side Validation
// ============================================ // ============================================
// Configuration // Configuration par défaut
const LICENSE_CONFIG = { const DEFAULT_APP_CONFIG = {
storageKey: 'git_pusher_license', api: {
usageKey: 'git_pusher_usage', url: '',
version: '2.1.0', port: 9999,
// URL du serveur Git Pusher API useProxy: true
serverUrl: (function() { }
const hostname = window.location.hostname; };
const protocol = window.location.protocol;
// Si déjà sur le domaine API, l'utiliser directement
if (hostname === 'myprivspldev-api.jp-engineering.fr') {
return protocol + '//' + hostname;
}
// Si accès via le domaine Splunk principal, utiliser le domaine API // Charger la configuration
if (hostname === 'myprivspldev.jp-engineering.fr') { function loadAppConfigForLicense() {
return protocol + '//myprivspldev-api.jp-engineering.fr'; try {
const stored = localStorage.getItem('git_pusher_config');
if (stored) {
return JSON.parse(stored);
} }
} catch (e) {
console.warn('Erreur chargement config localStorage:', e);
}
return DEFAULT_APP_CONFIG;
}
// Si c'est une IP ou localhost, ajouter le port 9999 // Déterminer l'URL du serveur API
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') { function getLicenseServerUrl() {
return protocol + '//' + hostname + ':9999'; const config = loadAppConfigForLicense();
const hostname = window.location.hostname;
const protocol = window.location.protocol;
// Si une URL est configurée, l'utiliser
if (config.api && config.api.url) {
let url = config.api.url;
// Ajouter le port si pas de proxy
if (!config.api.useProxy && config.api.port) {
url = url.replace(/\/$/, '') + ':' + config.api.port;
} }
return url;
}
// Auto-détection basée sur le hostname
if (hostname === 'myprivspldev.jp-engineering.fr') {
return protocol + '//myprivspldev-api.jp-engineering.fr';
}
// Par défaut, ajouter le port 9999 if (hostname === 'myprivspldev-api.jp-engineering.fr') {
return protocol + '//' + hostname;
}
if (/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') {
return protocol + '//' + hostname + ':9999'; return protocol + '//' + hostname + ':9999';
})() }
return protocol + '//' + hostname + ':9999';
}
// Configuration
const LICENSE_CONFIG = {
storageKey: 'git_pusher_license',
usageKey: 'git_pusher_usage',
version: '2.1.0',
serverUrl: getLicenseServerUrl()
}; };
// ============================================ // ============================================

@ -46,29 +46,87 @@ except ImportError:
def parse_license_content(c): return {} def parse_license_content(c): return {}
# ============================================ # ============================================
# CONFIGURATION SH DEPLOYER # CONFIGURATION
# ============================================ # ============================================
# Chemins Splunk # Chemins Splunk
SPLUNK_HOME = os.environ.get('SPLUNK_HOME', '/opt/splunk') SPLUNK_HOME = os.environ.get('SPLUNK_HOME', '/opt/splunk')
APP_HOME = os.path.join(SPLUNK_HOME, 'etc', 'apps', 'pusher_app_prem') APP_HOME = os.path.join(SPLUNK_HOME, 'etc', 'apps', 'pusher_app_prem')
CONFIG_FILE = os.path.join(APP_HOME, 'local', 'config.json')
# Configuration par défaut
DEFAULT_CONFIG = {
"api": {
"url": "",
"port": 9999,
"useProxy": True
},
"deployer": {
"enabled": False,
"host": "",
"port": 9998,
"token": "",
"useSSL": True
},
"license": {
"checkInterval": 24
},
"advanced": {
"logLevel": "INFO",
"timeout": 30,
"gitTimeout": 120
}
}
def load_config():
"""Charger la configuration depuis le fichier"""
try:
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, 'r') as f:
config = json.load(f)
# Fusionner avec la config par défaut pour les clés manquantes
return {**DEFAULT_CONFIG, **config}
except Exception as e:
logger.error(f"Erreur chargement config: {e}")
return DEFAULT_CONFIG.copy()
def save_config(config):
"""Sauvegarder la configuration dans le fichier"""
try:
local_dir = os.path.join(APP_HOME, 'local')
os.makedirs(local_dir, exist_ok=True)
with open(CONFIG_FILE, 'w') as f:
json.dump(config, f, indent=2)
# Configuration du SH Deployer (peut être surchargée par les paramètres) os.chmod(CONFIG_FILE, 0o600)
logger.info(f"Configuration sauvegardée: {CONFIG_FILE}")
return True
except Exception as e:
logger.error(f"Erreur sauvegarde config: {e}")
return False
# Charger la configuration au démarrage
APP_CONFIG = load_config()
# Configuration du SH Deployer (depuis la config ou valeurs par défaut)
SH_DEPLOYER_CONFIG = { SH_DEPLOYER_CONFIG = {
"enabled": True, "enabled": APP_CONFIG.get("deployer", {}).get("enabled", False),
"host": "10.10.40.14", "host": APP_CONFIG.get("deployer", {}).get("host", ""),
"port": 9998, "port": APP_CONFIG.get("deployer", {}).get("port", 9998),
"use_ssl": True, "use_ssl": APP_CONFIG.get("deployer", {}).get("useSSL", True),
"token": "deployer_agent_secret_token_change_me_in_production", "token": APP_CONFIG.get("deployer", {}).get("token", ""),
"timeout": 30 "timeout": APP_CONFIG.get("advanced", {}).get("timeout", 30)
} }
# Configuration du logging # Configuration du logging
log_dir = '/opt/splunk/var/log/splunk' log_dir = '/opt/splunk/var/log/splunk'
os.makedirs(log_dir, exist_ok=True) os.makedirs(log_dir, exist_ok=True)
log_level = getattr(logging, APP_CONFIG.get("advanced", {}).get("logLevel", "INFO"), logging.INFO)
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=log_level,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[ handlers=[
logging.FileHandler(os.path.join(log_dir, 'git_pusher.log')), logging.FileHandler(os.path.join(log_dir, 'git_pusher.log')),
@ -87,7 +145,7 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
origin = self.headers.get('Origin', '*') origin = self.headers.get('Origin', '*')
self.send_header('Access-Control-Allow-Origin', origin) self.send_header('Access-Control-Allow-Origin', origin)
self.send_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE') self.send_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin') self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin, X-Splunk-Form-Key, X-Auth-Token')
self.send_header('Access-Control-Allow-Credentials', 'true') self.send_header('Access-Control-Allow-Credentials', 'true')
self.send_header('Access-Control-Max-Age', '86400') # Cache preflight 24h self.send_header('Access-Control-Max-Age', '86400') # Cache preflight 24h
@ -161,6 +219,18 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
self.wfile.write(json.dumps(response).encode()) self.wfile.write(json.dumps(response).encode())
# ============================================
# ENDPOINT CONFIGURATION
# ============================================
elif path == '/config':
# Retourner la configuration actuelle
config = load_config()
# Masquer le token pour la sécurité
if 'deployer' in config and 'token' in config['deployer']:
config['deployer']['token'] = '***' if config['deployer']['token'] else ''
self.wfile.write(json.dumps(config).encode())
elif path == '/health': elif path == '/health':
# Health check # Health check
response = { response = {
@ -239,11 +309,57 @@ class GitPusherRequestHandler(BaseHTTPRequestHandler):
logger.info(f"POST request to {path}") logger.info(f"POST request to {path}")
# ============================================
# ENDPOINT CONFIGURATION
# ============================================
if path == '/config':
# Sauvegarder la configuration
content_length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_length).decode('utf-8')
try:
new_config = json.loads(body)
# Charger la config existante pour préserver le token si masqué
existing_config = load_config()
# Si le token est masqué (***), garder l'ancien
if new_config.get('deployer', {}).get('token') == '***':
new_config['deployer']['token'] = existing_config.get('deployer', {}).get('token', '')
# Sauvegarder
if save_config(new_config):
# Recharger la config globale
global APP_CONFIG, SH_DEPLOYER_CONFIG
APP_CONFIG = load_config()
SH_DEPLOYER_CONFIG = {
"enabled": APP_CONFIG.get("deployer", {}).get("enabled", False),
"host": APP_CONFIG.get("deployer", {}).get("host", ""),
"port": APP_CONFIG.get("deployer", {}).get("port", 9998),
"use_ssl": APP_CONFIG.get("deployer", {}).get("useSSL", True),
"token": APP_CONFIG.get("deployer", {}).get("token", ""),
"timeout": APP_CONFIG.get("advanced", {}).get("timeout", 30)
}
response = {"success": True, "message": "Configuration sauvegardée"}
else:
response = {"success": False, "error": "Erreur lors de la sauvegarde"}
except json.JSONDecodeError as e:
response = {"success": False, "error": f"JSON invalide: {str(e)}"}
except Exception as e:
logger.error(f"Erreur sauvegarde config: {e}")
response = {"success": False, "error": str(e)}
self.wfile.write(json.dumps(response).encode())
return
# ============================================ # ============================================
# ENDPOINTS LICENCE # ENDPOINTS LICENCE
# ============================================ # ============================================
if path == '/license/upload' or path == '/license/save': elif path == '/license/upload' or path == '/license/save':
# Sauvegarder la licence sur le serveur (fichier) # Sauvegarder la licence sur le serveur (fichier)
# La validation RSA est faite côté client # La validation RSA est faite côté client
content_length = int(self.headers.get('Content-Length', 0)) content_length = int(self.headers.get('Content-Length', 0))

@ -1,3 +1,4 @@
<nav search_view="git_pusher_-_deploy_applications"> <nav search_view="git_pusher_-_deploy_applications">
<view name="git_pusher_-_deploy_applications" default='true' /> <view name="git_pusher_-_deploy_applications" default='true' />
<view name="git_pusher_config" />
</nav> </nav>

@ -0,0 +1,22 @@
{
"api": {
"url": "https://myprivspldev-api.jp-engineering.fr",
"port": 9999,
"useProxy": true
},
"deployer": {
"enabled": false,
"host": "10.10.40.14",
"port": 9998,
"token": "bc2564e5a885d49ac3811dc946ca5620da24da19b8a8f5c5fdfcd7c07a241688",
"useSSL": true
},
"license": {
"checkInterval": 24
},
"advanced": {
"logLevel": "INFO",
"timeout": 30,
"gitTimeout": 120
}
}

@ -0,0 +1,311 @@
<dashboard version="1.1" script="git_pusher_config.js" hideEdit="true">
<label>Git Pusher - Configuration</label>
<description>Configuration de l'application Git Pusher</description>
<row>
<panel>
<html>
<style>
.config-container {
max-width: 900px;
margin: 0 auto;
padding: 30px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.config-header {
text-align: center;
margin-bottom: 40px;
}
.config-header h1 {
font-size: 28px;
color: #333;
margin-bottom: 10px;
}
.config-header p {
color: #666;
font-size: 14px;
}
.config-section {
background: white;
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.config-section h2 {
font-size: 18px;
color: #333;
margin: 0 0 20px 0;
padding-bottom: 10px;
border-bottom: 2px solid #667eea;
display: flex;
align-items: center;
gap: 10px;
}
.config-section h2 .icon {
font-size: 24px;
}
.config-grid {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 15px;
align-items: center;
}
.config-grid label {
font-weight: 600;
color: #555;
}
.config-grid input, .config-grid select {
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
.config-grid input:focus, .config-grid select:focus {
outline: none;
border-color: #667eea;
}
.config-grid input[type="checkbox"] {
width: 20px;
height: 20px;
}
.config-hint {
grid-column: 2;
font-size: 12px;
color: #888;
margin-top: -10px;
}
.config-actions {
display: flex;
justify-content: flex-end;
gap: 15px;
margin-top: 30px;
}
.btn {
padding: 12px 30px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: #f5f5f5;
color: #333;
}
.btn-secondary:hover {
background: #e0e0e0;
}
.btn-danger {
background: #f44336;
color: white;
}
.btn-danger:hover {
background: #d32f2f;
}
.config-message {
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
display: none;
}
.config-message.success {
background: #e8f5e9;
color: #2e7d32;
border-left: 4px solid #4caf50;
display: block;
}
.config-message.error {
background: #ffebee;
color: #c62828;
border-left: 4px solid #f44336;
display: block;
}
.config-status {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 5px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.config-status.connected {
background: #e8f5e9;
color: #2e7d32;
}
.config-status.disconnected {
background: #ffebee;
color: #c62828;
}
.test-btn {
padding: 8px 15px;
font-size: 12px;
background: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.test-btn:hover {
background: #1976D2;
}
.version-badge {
position: fixed;
bottom: 20px;
right: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
</style>
<div class="config-container">
<div class="config-header">
<h1>⚙️ Configuration Git Pusher</h1>
<p>Configurez les paramètres de l'application</p>
</div>
<div id="config-message" class="config-message"></div>
<!-- Section API -->
<div class="config-section">
<h2><span class="icon">🌐</span> Configuration API</h2>
<div class="config-grid">
<label for="api-url">URL de l'API Git Pusher</label>
<input type="text" id="api-url" placeholder="https://myprivspldev-api.example.com" />
<span class="config-hint">L'URL du serveur Git Pusher (sans le port si proxy)</span>
<label for="api-port">Port (si accès direct)</label>
<input type="number" id="api-port" placeholder="9999" value="9999" />
<span class="config-hint">Port utilisé si accès direct par IP (ignoré si URL de domaine)</span>
<label for="use-proxy">Utiliser un proxy</label>
<input type="checkbox" id="use-proxy" checked="checked" />
<span class="config-hint">Coché si vous utilisez un reverse proxy (Nginx, etc.)</span>
<label>Test de connexion</label>
<div>
<button class="test-btn" id="test-api-btn">Tester la connexion</button>
<span id="api-status" class="config-status disconnected">● Non testé</span>
</div>
</div>
</div>
<!-- Section SH Deployer -->
<div class="config-section">
<h2><span class="icon">🚀</span> Configuration SH Deployer</h2>
<div class="config-grid">
<label for="deployer-enabled">Activer SH Deployer</label>
<input type="checkbox" id="deployer-enabled" />
<span class="config-hint">Activer le déploiement automatique vers le Search Head Cluster</span>
<label for="deployer-host">Adresse du SH Deployer</label>
<input type="text" id="deployer-host" placeholder="10.10.40.14" />
<span class="config-hint">Adresse IP ou hostname du serveur SH Deployer</span>
<label for="deployer-port">Port</label>
<input type="number" id="deployer-port" placeholder="9998" value="9998" />
<label for="deployer-token">Token d'authentification</label>
<input type="password" id="deployer-token" placeholder="Token secret" />
<span class="config-hint">Token configuré dans deployer_agent.py</span>
<label for="deployer-use-ssl">Utiliser SSL</label>
<input type="checkbox" id="deployer-use-ssl" checked="checked" />
<label>Test de connexion</label>
<div>
<button class="test-btn" id="test-deployer-btn">Tester la connexion</button>
<span id="deployer-status" class="config-status disconnected">● Non testé</span>
</div>
</div>
</div>
<!-- Section Licence -->
<div class="config-section">
<h2><span class="icon">🔐</span> Configuration Licence</h2>
<div class="config-grid">
<label>Statut de la licence</label>
<div id="license-status">Chargement...</div>
<label for="license-check-interval">Intervalle de vérification (heures)</label>
<input type="number" id="license-check-interval" value="24" min="1" max="168" />
<span class="config-hint">Fréquence de revalidation de la licence</span>
</div>
</div>
<!-- Section Avancée -->
<div class="config-section">
<h2><span class="icon">🔧</span> Paramètres avancés</h2>
<div class="config-grid">
<label for="log-level">Niveau de log</label>
<select id="log-level">
<option value="INFO">INFO</option>
<option value="DEBUG">DEBUG</option>
<option value="WARNING">WARNING</option>
<option value="ERROR">ERROR</option>
</select>
<label for="timeout">Timeout des requêtes (secondes)</label>
<input type="number" id="timeout" value="30" min="5" max="300" />
<label for="git-timeout">Timeout Git (secondes)</label>
<input type="number" id="git-timeout" value="120" min="30" max="600" />
</div>
</div>
<!-- Actions -->
<div class="config-actions">
<button class="btn btn-secondary" id="reset-btn">Réinitialiser</button>
<button class="btn btn-primary" id="save-btn">💾 Sauvegarder</button>
</div>
</div>
<div class="version-badge">Git Pusher v2.1</div>
</html>
</panel>
</row>
</dashboard>
Loading…
Cancel
Save