All checks were successful
		
		
	
	HAProxy Manager Build and Push / Build-and-Push (push) Successful in 48s
				
			
		
			
				
	
	
		
			378 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			378 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html lang="en">
 | 
						|
<head>
 | 
						|
    <meta charset="UTF-8">
 | 
						|
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
						|
    <title>HAProxy Manager</title>
 | 
						|
    <style>
 | 
						|
        body {
 | 
						|
            font-family: Arial, sans-serif;
 | 
						|
            max-width: 1200px;
 | 
						|
            margin: 0 auto;
 | 
						|
            padding: 20px;
 | 
						|
            background-color: #f5f5f5;
 | 
						|
        }
 | 
						|
        .container {
 | 
						|
            background-color: white;
 | 
						|
            padding: 20px;
 | 
						|
            border-radius: 8px;
 | 
						|
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
 | 
						|
        }
 | 
						|
        .form-group {
 | 
						|
            margin-bottom: 15px;
 | 
						|
        }
 | 
						|
        label {
 | 
						|
            display: block;
 | 
						|
            margin-bottom: 5px;
 | 
						|
            font-weight: bold;
 | 
						|
        }
 | 
						|
        input[type="text"], input[type="number"] {
 | 
						|
            width: 100%;
 | 
						|
            padding: 8px;
 | 
						|
            border: 1px solid #ddd;
 | 
						|
            border-radius: 4px;
 | 
						|
            box-sizing: border-box;
 | 
						|
        }
 | 
						|
        button {
 | 
						|
            background-color: #4CAF50;
 | 
						|
            color: white;
 | 
						|
            padding: 10px 15px;
 | 
						|
            border: none;
 | 
						|
            border-radius: 4px;
 | 
						|
            cursor: pointer;
 | 
						|
        }
 | 
						|
        button:hover {
 | 
						|
            background-color: #45a049;
 | 
						|
        }
 | 
						|
        .server-list {
 | 
						|
            margin-top: 10px;
 | 
						|
        }
 | 
						|
        .server-item, .domain-list-item {
 | 
						|
            border: 1px solid #ddd;
 | 
						|
            padding: 15px;
 | 
						|
            margin-bottom: 10px;
 | 
						|
            border-radius: 5px;
 | 
						|
        }
 | 
						|
        .domain-list-item {
 | 
						|
            background-color: #f9f9f9;
 | 
						|
        }
 | 
						|
        .server-item {
 | 
						|
            background-color: #fff;
 | 
						|
        }
 | 
						|
        .delete-btn {
 | 
						|
            background-color: #f44336;
 | 
						|
        }
 | 
						|
        .delete-btn:hover {
 | 
						|
            background-color: #da190b;
 | 
						|
        }
 | 
						|
        .domain-list {
 | 
						|
            margin-top: 20px;
 | 
						|
        }
 | 
						|
        .ssl-btn {
 | 
						|
            background-color: #2196F3;
 | 
						|
        }
 | 
						|
        .ssl-btn:hover {
 | 
						|
            background-color: #0b7dda;
 | 
						|
        }
 | 
						|
        .status {
 | 
						|
            padding: 10px;
 | 
						|
            margin: 10px 0;
 | 
						|
            border-radius: 4px;
 | 
						|
        }
 | 
						|
        .status.success {
 | 
						|
            background-color: #dff0d8;
 | 
						|
            color: #3c763d;
 | 
						|
        }
 | 
						|
        .status.error {
 | 
						|
            background-color: #f2dede;
 | 
						|
            color: #a94442;
 | 
						|
        }
 | 
						|
        .regenerate-btn {
 | 
						|
            background-color: #ff9800;
 | 
						|
            color: white;
 | 
						|
            padding: 10px 15px;
 | 
						|
            border: none;
 | 
						|
            border-radius: 4px;
 | 
						|
            cursor: pointer;
 | 
						|
            margin-bottom: 20px;
 | 
						|
        }
 | 
						|
        .regenerate-btn:hover {
 | 
						|
            background-color: #f57c00;
 | 
						|
        }
 | 
						|
    </style>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
    <div class="container">
 | 
						|
        <h1>HAProxy Domain Manager</h1>
 | 
						|
        <button onclick="regenerateConfig()" class="regenerate-btn">Regenerate HAProxy Config</button>
 | 
						|
        <button onclick="reloadHAProxy()" class="regenerate-btn" style="background-color: #2196F3;">Reload HAProxy</button>
 | 
						|
        <form id="domainForm">
 | 
						|
            <div class="form-group">
 | 
						|
                <label for="domain">Domain:</label>
 | 
						|
                <input type="text" id="domain" required placeholder="example.com">
 | 
						|
            </div>
 | 
						|
            <div class="form-group">
 | 
						|
                <label for="backendName">Backend Name:</label>
 | 
						|
                <input type="text" id="backendName" required placeholder="example_backend">
 | 
						|
            </div>
 | 
						|
            <div class="form-group">
 | 
						|
                <label for="templateOverride">Template Override (optional):</label>
 | 
						|
                <input type="text" id="templateOverride" placeholder="custom_template">
 | 
						|
            </div>
 | 
						|
            <h3>Backend Servers</h3>
 | 
						|
            <div id="serverList" class="server-list"></div>
 | 
						|
            <button type="button" onclick="addServerField()">Add Server</button>
 | 
						|
            <button type="submit">Add Domain</button>
 | 
						|
        </form>
 | 
						|
        <h2>Existing Domains</h2>
 | 
						|
        <div id="domainList" class="domain-list"></div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <script>
 | 
						|
        window.onerror = function(msg, url, lineNo, columnNo, error) {
 | 
						|
            console.log('Error: ' + msg + '\nURL: ' + url + '\nLine: ' + lineNo + '\nColumn: ' + columnNo + '\nError object: ' + JSON.stringify(error));
 | 
						|
            return false;
 | 
						|
        };
 | 
						|
 | 
						|
        function addServerField() {
 | 
						|
            const serverList = document.getElementById('serverList');
 | 
						|
            const serverDiv = document.createElement('div');
 | 
						|
            serverDiv.className = 'server-item';
 | 
						|
            const serverHTML = `
 | 
						|
                <div class="form-group">
 | 
						|
                    <label>Server Name:</label>
 | 
						|
                    <input type="text" class="server-name" required placeholder="server1">
 | 
						|
                </div>
 | 
						|
                <div class="form-group">
 | 
						|
                    <label>Server Address:</label>
 | 
						|
                    <input type="text" class="server-address" required placeholder="192.168.1.100">
 | 
						|
                </div>
 | 
						|
                <div class="form-group">
 | 
						|
                    <label>Server Port:</label>
 | 
						|
                    <input type="number" class="server-port" required placeholder="8080">
 | 
						|
                </div>
 | 
						|
                <div class="form-group">
 | 
						|
                    <label>Server Options:</label>
 | 
						|
                    <input type="text" class="server-options" placeholder="check">
 | 
						|
                </div>
 | 
						|
                <button type="button" class="delete-btn" onclick="this.parentElement.remove()">Remove Server</button>
 | 
						|
            `;
 | 
						|
 | 
						|
            serverDiv.innerHTML = serverHTML;
 | 
						|
            serverList.appendChild(serverDiv);
 | 
						|
        }
 | 
						|
 | 
						|
        document.getElementById('domainForm').addEventListener('submit', async (e) => {
 | 
						|
            e.preventDefault();
 | 
						|
            const serverItems = document.getElementById('serverList').getElementsByClassName('server-item');
 | 
						|
 | 
						|
            const domainInput = document.getElementById('domain');
 | 
						|
            const backendNameInput = document.getElementById('backendName');
 | 
						|
            const templateOverrideInput = document.getElementById('templateOverride');
 | 
						|
 | 
						|
            if (!domainInput || !backendNameInput) {
 | 
						|
                showStatus('Required form fields are missing', 'error');
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            if (serverItems.length === 0) {
 | 
						|
                showStatus('At least one server is required', 'error');
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            const servers = [];
 | 
						|
            for (const item of serverItems) {
 | 
						|
                const nameInput = item.querySelector('.server-name');
 | 
						|
                const addressInput = item.querySelector('.server-address');
 | 
						|
                const portInput = item.querySelector('.server-port');
 | 
						|
                const optionsInput = item.querySelector('.server-options');
 | 
						|
 | 
						|
                if (!nameInput || !addressInput || !portInput) {
 | 
						|
                    showStatus('Server configuration is incomplete', 'error');
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                if (!nameInput.value || !addressInput.value || !portInput.value) {
 | 
						|
                    showStatus('Please fill in all required server fields', 'error');
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                servers.push({
 | 
						|
                    name: nameInput.value,
 | 
						|
                    address: addressInput.value,
 | 
						|
                    port: parseInt(portInput.value),
 | 
						|
                    options: optionsInput.value || "check"
 | 
						|
                });
 | 
						|
            }
 | 
						|
 | 
						|
            const data = {
 | 
						|
                domain: domainInput.value,
 | 
						|
                backend_name: backendNameInput.value,
 | 
						|
                template_override: templateOverrideInput.value || null,
 | 
						|
                servers: servers
 | 
						|
            };
 | 
						|
 | 
						|
            try {
 | 
						|
                const response = await fetch('/api/domain', {
 | 
						|
                    method: 'POST',
 | 
						|
                    headers: {
 | 
						|
                        'Content-Type': 'application/json',
 | 
						|
                    },
 | 
						|
                    body: JSON.stringify(data)
 | 
						|
                });
 | 
						|
 | 
						|
                const responseData = await response.json();
 | 
						|
 | 
						|
                if (response.ok) {
 | 
						|
                    showStatus(`Domain added successfully! Domain ID: ${responseData.domain_id}`, 'success');
 | 
						|
                    document.getElementById('domainForm').reset();
 | 
						|
                    document.getElementById('serverList').innerHTML = '';
 | 
						|
        addServerField();
 | 
						|
        loadDomains();
 | 
						|
                } else {
 | 
						|
                    showStatus('Failed to add domain: ' + (responseData.message || 'Unknown error'), 'error');
 | 
						|
                }
 | 
						|
            } catch (error) {
 | 
						|
                showStatus('Error: ' + error.message, 'error');
 | 
						|
                console.error('Error details:', error);
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        async function reloadHAProxy() {
 | 
						|
            try {
 | 
						|
                const response = await fetch('/api/reload', {
 | 
						|
                    method: 'GET',
 | 
						|
                    headers: {
 | 
						|
                        'Content-Type': 'application/json',
 | 
						|
                    }
 | 
						|
                });
 | 
						|
 | 
						|
                if (response.ok) {
 | 
						|
                    showStatus('HAProxy reloaded successfully', 'success');
 | 
						|
                } else {
 | 
						|
                    const data = await response.json();
 | 
						|
                    showStatus('Failed to reload HAProxy: ' + (data.message || 'Unknown error'), 'error');
 | 
						|
                }
 | 
						|
            } catch (error) {
 | 
						|
                showStatus('Error: ' + error.message, 'error');
 | 
						|
                console.error('Error reloading HAProxy:', error);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        async function requestSSL(domain) {
 | 
						|
            try {
 | 
						|
                const response = await fetch('/api/ssl', {
 | 
						|
                    method: 'POST',
 | 
						|
                    headers: {
 | 
						|
                        'Content-Type': 'application/json',
 | 
						|
                    },
 | 
						|
                    body: JSON.stringify({ domain })
 | 
						|
                });
 | 
						|
 | 
						|
                if (response.ok) {
 | 
						|
                    showStatus(`SSL certificate requested for ${domain}`, 'success');
 | 
						|
                    loadDomains();
 | 
						|
                } else {
 | 
						|
                    showStatus('Failed to request SSL certificate', 'error');
 | 
						|
                }
 | 
						|
            } catch (error) {
 | 
						|
                showStatus('Error: ' + error.message, 'error');
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        async function deleteDomain(domain) {
 | 
						|
            if (!confirm(`Are you sure you want to delete ${domain}?`)) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            try {
 | 
						|
                const response = await fetch('/api/domain', {
 | 
						|
                    method: 'DELETE',
 | 
						|
                    headers: {
 | 
						|
                        'Content-Type': 'application/json',
 | 
						|
                    },
 | 
						|
                    body: JSON.stringify({ domain })
 | 
						|
                });
 | 
						|
 | 
						|
                if (response.ok) {
 | 
						|
                    showStatus(`Domain ${domain} deleted successfully`, 'success');
 | 
						|
                    loadDomains();
 | 
						|
                } else {
 | 
						|
                    showStatus('Failed to delete domain', 'error');
 | 
						|
                }
 | 
						|
            } catch (error) {
 | 
						|
                showStatus('Error: ' + error.message, 'error');
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        async function regenerateConfig() {
 | 
						|
            try {
 | 
						|
                const response = await fetch('/api/regenerate', {
 | 
						|
                    method: 'GET',
 | 
						|
                    headers: {
 | 
						|
                        'Content-Type': 'application/json',
 | 
						|
                    }
 | 
						|
                });
 | 
						|
 | 
						|
                if (response.ok) {
 | 
						|
                    showStatus('HAProxy configuration regenerated successfully', 'success');
 | 
						|
            } else {
 | 
						|
                    const data = await response.json();
 | 
						|
                    showStatus('Failed to regenerate configuration: ' + (data.message || 'Unknown error'), 'error');
 | 
						|
            }
 | 
						|
            } catch (error) {
 | 
						|
                showStatus('Error: ' + error.message, 'error');
 | 
						|
                console.error('Error regenerating config:', error);
 | 
						|
                }
 | 
						|
        }
 | 
						|
 | 
						|
        function showStatus(message, type) {
 | 
						|
            const statusDiv = document.createElement('div');
 | 
						|
            statusDiv.className = `status ${type}`;
 | 
						|
            statusDiv.textContent = message;
 | 
						|
            const container = document.querySelector('.container');
 | 
						|
            const domainList = document.querySelector('.domain-list');
 | 
						|
            if (container && domainList) {
 | 
						|
                container.insertBefore(statusDiv, domainList);
 | 
						|
            } else {
 | 
						|
                document.body.appendChild(statusDiv);
 | 
						|
            }
 | 
						|
            setTimeout(() => {
 | 
						|
                if (statusDiv.parentNode) {
 | 
						|
                    statusDiv.remove();
 | 
						|
                }
 | 
						|
            }, 5000);
 | 
						|
        }
 | 
						|
 | 
						|
        function loadDomains() {
 | 
						|
            fetch('/api/domains')
 | 
						|
                .then(response => response.json())
 | 
						|
                .then(domains => {
 | 
						|
                    const domainList = document.getElementById('domainList');
 | 
						|
                    domainList.innerHTML = '';
 | 
						|
                    domains.forEach(domain => {
 | 
						|
                        const domainDiv = document.createElement('div');
 | 
						|
                        domainDiv.className = 'domain-list-item';
 | 
						|
                        domainDiv.innerHTML = `
 | 
						|
                            <h3>${domain.domain}</h3>
 | 
						|
                            <p>Backend: ${domain.backend_name}</p>
 | 
						|
                        <p>SSL: ${domain.ssl_enabled ? 'Enabled' : 'Disabled'}</p>
 | 
						|
                        <button onclick="requestSSL('${domain.domain}')" class="ssl-btn">
 | 
						|
                                ${domain.ssl_enabled ? 'Renew SSL' : 'Enable SSL'}
 | 
						|
                        </button>
 | 
						|
                            <button onclick="deleteDomain('${domain.domain}')" class="delete-btn">Delete Domain</button>
 | 
						|
                        `;
 | 
						|
                        domainList.appendChild(domainDiv);
 | 
						|
                    });
 | 
						|
                })
 | 
						|
                .catch(error => {
 | 
						|
                    console.error('Error loading domains:', error);
 | 
						|
                    showStatus('Error loading domains: ' + error.message, 'error');
 | 
						|
                });
 | 
						|
            }
 | 
						|
 | 
						|
        addServerField();
 | 
						|
        loadDomains();
 | 
						|
    </script>
 | 
						|
</body>
 | 
						|
</html> |