From cb205f09d20485c54e042a2095431fde809dcd01 Mon Sep 17 00:00:00 2001 From: Mboehmlaender <41646409+Mboehmlaender@users.noreply.github.com> Date: Thu, 25 Sep 2025 11:26:06 +0200 Subject: [PATCH] Update index.js --- backend/index.js | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/backend/index.js b/backend/index.js index 1a26dfc..398d5a3 100644 --- a/backend/index.js +++ b/backend/index.js @@ -15,61 +15,49 @@ const __dirname = path.dirname(__filename); const app = express(); app.use(express.json()); -// Statische Frontend-Dateien ausliefern app.use(express.static(path.join(__dirname, 'public'))); -// SPA-Fallback für React-Router app.get('*', (req, res, next) => { if (req.path.startsWith('/api')) return next(); res.sendFile(path.join(__dirname, 'public', 'index.html')); }); -// Backend-Port fix const PORT = 4001; - -// Endpoint-ID aus der env const ENDPOINT_ID = Number(process.env.PORTAINER_ENDPOINT_ID); -// HTTPS Agent für Self-Signed-Zertifikate const agent = new https.Agent({ rejectUnauthorized: false }); - -// Axios-Instance für Portainer const axiosInstance = axios.create({ httpsAgent: agent, headers: { "X-API-Key": process.env.PORTAINER_API_KEY }, baseURL: process.env.PORTAINER_URL, }); -// In-Memory Redeploy-Status const redeployingStacks = {}; -// HTTP Server + Socket.IO const server = http.createServer(app); const io = new Server(server, { cors: { origin: "*" } }); io.on("connection", (socket) => { - console.log("Client verbunden:", socket.id); + console.log(`🔌 [Socket] Client verbunden: ${socket.id}`); }); const broadcastRedeployStatus = (stackId, status) => { redeployingStacks[stackId] = status; io.emit("redeployStatus", { stackId, status }); + console.log(`🔄 [RedeployStatus] Stack ${stackId} ist jetzt ${status ? "im Redeploy" : "fertig"}`); }; // --- API Endpoints --- + app.get('/api/stacks', async (req, res) => { + console.log("ℹ️ [API] GET /api/stacks: Abruf gestartet"); try { const stacksRes = await axiosInstance.get('/api/stacks'); - - // Filter nach Endpoint-ID const filteredStacks = stacksRes.data.filter(stack => stack.EndpointId === ENDPOINT_ID); - // Deduplication nach Name: nur einmal pro Name const uniqueStacksMap = {}; filteredStacks.forEach(stack => { - if (!uniqueStacksMap[stack.Name]) { - uniqueStacksMap[stack.Name] = stack; - } + if (!uniqueStacksMap[stack.Name]) uniqueStacksMap[stack.Name] = stack; }); const uniqueStacks = Object.values(uniqueStacksMap); @@ -80,36 +68,46 @@ app.get('/api/stacks', async (req, res) => { `/api/stacks/${stack.Id}/images_status?refresh=true` ); const statusEmoji = statusRes.data.Status === 'outdated' ? '⚠️' : '✅'; - return { ...stack, updateStatus: statusEmoji, redeploying: redeployingStacks[stack.Id] || false }; - } catch { + return { + ...stack, + updateStatus: statusEmoji, + redeploying: redeployingStacks[stack.Id] || false + }; + } catch (err) { + console.error(`❌ Fehler beim Abrufen des Status für Stack ${stack.Id}:`, err.message); return { ...stack, updateStatus: '❌', redeploying: redeployingStacks[stack.Id] || false }; } }) ); stacksWithStatus.sort((a, b) => a.Name.localeCompare(b.Name)); + console.log(`✅ GET /api/stacks: Abruf erfolgreich, ${stacksWithStatus.length} Stacks geladen`); res.json(stacksWithStatus); } catch (err) { + console.error(`❌ Fehler beim Abrufen der Stacks:`, err.message); res.status(500).json({ error: err.message }); } }); app.put('/api/stacks/:id/redeploy', async (req, res) => { const { id } = req.params; + console.log(`🔄 PUT /api/stacks/${id}/redeploy: Redeploy gestartet`); + try { broadcastRedeployStatus(id, true); const stackRes = await axiosInstance.get(`/api/stacks/${id}`); const stack = stackRes.data; - // Prüfen, ob Stack zum konfigurierten Endpoint gehört if (stack.EndpointId !== ENDPOINT_ID) { throw new Error(`Stack gehört nicht zum Endpoint ${ENDPOINT_ID}`); } if (stack.Type === 1) { + console.log(`🔄 [Redeploy] Git Stack "${stack.Name}" (${id}) wird redeployed`); await axiosInstance.put(`/api/stacks/${id}/git/redeploy?endpointId=${stack.EndpointId}`); } else if (stack.Type === 2) { + console.log(`🔄 [Redeploy] Compose Stack "${stack.Name}" (${id}) wird redeployed`); const fileRes = await axiosInstance.get(`/api/stacks/${id}/file`); const stackFileContent = fileRes.data?.StackFileContent; if (!stackFileContent) throw new Error("Stack file konnte nicht geladen werden"); @@ -119,10 +117,13 @@ app.put('/api/stacks/:id/redeploy', async (req, res) => { const imageName = services[serviceName].image; if (!imageName) continue; try { + console.log(`🖼️ Pulling image "${imageName}" für Service "${serviceName}"`); await axiosInstance.post( `/api/endpoints/${stack.EndpointId}/docker/images/create?fromImage=${encodeURIComponent(imageName)}` ); - } catch {} + } catch (err) { + console.error(`❌ Fehler beim Pulling von Image "${imageName}":`, err.message); + } } await axiosInstance.put(`/api/stacks/${id}`, @@ -132,14 +133,15 @@ app.put('/api/stacks/:id/redeploy', async (req, res) => { } broadcastRedeployStatus(id, false); + console.log(`✅ PUT /api/stacks/${id}/redeploy: Redeploy erfolgreich abgeschlossen`); res.json({ success: true, message: 'Stack redeployed' }); } catch (err) { broadcastRedeployStatus(id, false); + console.error(`❌ Fehler beim Redeploy von Stack ${id}:`, err.message); res.status(500).json({ error: err.message }); } }); -// Server starten server.listen(PORT, '0.0.0.0', () => { - console.log(`Backend läuft auf Port ${PORT}`); + console.log(`🚀 Backend läuft auf Port ${PORT}`); });