From 700d2499866140bc13d4ea4d5eb87223e1758176 Mon Sep 17 00:00:00 2001
From: Sadallah
Date: Thu, 11 Jun 2026 11:55:22 +0200
Subject: [PATCH] [Feature] Add Docker kubectl support and cluster connectivity
+ Apply Prettier formatting to frontend files
---
webapp/backend/Dockerfile | 7 +++++
webapp/docker-compose.yml | 7 +++++
.../src/components/common/HistoryPanel.jsx | 4 +--
.../tabs/ClusterTab/ClusterInput.jsx | 26 ++++++++++++-------
webapp/frontend/src/hooks/useClusterData.js | 5 ++--
webapp/frontend/src/services/diagramApi.js | 1 -
6 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/webapp/backend/Dockerfile b/webapp/backend/Dockerfile
index 82d3e0a..5369ef0 100644
--- a/webapp/backend/Dockerfile
+++ b/webapp/backend/Dockerfile
@@ -23,6 +23,13 @@ RUN apk update && apk add --no-cache \
musl-dev \
&& rm -rf /var/cache/apk/*
+# Install kubectl (statically compiled Go binary — works on Alpine/musl)
+RUN ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && \
+ KUBECTL_VERSION=$(curl -fsSL https://dl.k8s.io/release/stable.txt) && \
+ curl -fsSL -o /usr/local/bin/kubectl \
+ "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl" && \
+ chmod +x /usr/local/bin/kubectl
+
# Copy Helm from first stage
COPY --from=helm /usr/bin/helm /usr/local/bin/helm
diff --git a/webapp/docker-compose.yml b/webapp/docker-compose.yml
index e05429d..8e29b07 100644
--- a/webapp/docker-compose.yml
+++ b/webapp/docker-compose.yml
@@ -43,8 +43,13 @@ services:
volumes:
# Persist logs outside container
- ./backend/logs:/app/logs
+ # Mount host kubeconfig so kubectl can reach the cluster started on the host
+ - ${HOME}/.kube:/root/.kube:ro
+ # Mount minikube certs at the same absolute path as on the host (kubeconfig references them by absolute path)
+ - ${HOME}/.minikube:${HOME}/.minikube:ro
networks:
- kubediagrams-network
+ - minikube
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "--fail", "--silent", "http://localhost:5000/api/health"]
@@ -59,3 +64,5 @@ services:
networks:
kubediagrams-network:
driver: bridge
+ minikube:
+ external: true
diff --git a/webapp/frontend/src/components/common/HistoryPanel.jsx b/webapp/frontend/src/components/common/HistoryPanel.jsx
index 5148ab3..e3810f7 100644
--- a/webapp/frontend/src/components/common/HistoryPanel.jsx
+++ b/webapp/frontend/src/components/common/HistoryPanel.jsx
@@ -121,9 +121,7 @@ const HistoryPanel = ({ history, onRestore, onRemove, onClear, isOpen, onToggle
No diagrams in history
-
- Generated diagrams will appear here
-
+
Generated diagrams will appear here
) : (
history.map((item) => (
diff --git a/webapp/frontend/src/components/tabs/ClusterTab/ClusterInput.jsx b/webapp/frontend/src/components/tabs/ClusterTab/ClusterInput.jsx
index 730c746..399d7ab 100644
--- a/webapp/frontend/src/components/tabs/ClusterTab/ClusterInput.jsx
+++ b/webapp/frontend/src/components/tabs/ClusterTab/ClusterInput.jsx
@@ -80,7 +80,10 @@ function ClusterInput({
@@ -262,7 +268,9 @@ function ClusterInput({
>
)}
-
+
{resourceTypes.length > 0
? `${resourceTypes.length} type${resourceTypes.length > 1 ? 's' : ''} selected`
: 'No types selected — please select at least one resource type.'}
@@ -307,12 +315,10 @@ function ClusterInput({
<>
No cluster detected. Start your cluster, then click{' '}
Refresh:
-
• minikube:{' '}
- minikube start
+
• minikube: minikube start
• kind:{' '}
kind create cluster
-
• k3d:{' '}
- k3d cluster create
+
• k3d: k3d cluster create
Make sure kubectl is installed
and your kubeconfig points to the right context.
@@ -406,4 +412,4 @@ ClusterInput.propTypes = {
handleNamespaceChange: PropTypes.func.isRequired,
};
-export default ClusterInput;
\ No newline at end of file
+export default ClusterInput;
diff --git a/webapp/frontend/src/hooks/useClusterData.js b/webapp/frontend/src/hooks/useClusterData.js
index fe130a2..7a57563 100644
--- a/webapp/frontend/src/hooks/useClusterData.js
+++ b/webapp/frontend/src/hooks/useClusterData.js
@@ -136,8 +136,7 @@ export function useClusterData({
const commons = availableResourceTypes.filter((rt) => rt.isCommon);
// With a specific namespace, default to namespaced commons only — cluster-scoped
// resources (nodes, storageclasses…) can still be added manually.
- const selected =
- namespace && !allNamespaces ? commons.filter((rt) => rt.namespaced) : commons;
+ const selected = namespace && !allNamespaces ? commons.filter((rt) => rt.namespaced) : commons;
setResourceTypes(selected.map((rt) => rt.name));
};
@@ -226,4 +225,4 @@ export function useClusterData({
handleAllNamespacesToggle,
handleNamespaceChange,
};
-}
\ No newline at end of file
+}
diff --git a/webapp/frontend/src/services/diagramApi.js b/webapp/frontend/src/services/diagramApi.js
index bdc6b5b..4d9b7b0 100644
--- a/webapp/frontend/src/services/diagramApi.js
+++ b/webapp/frontend/src/services/diagramApi.js
@@ -306,7 +306,6 @@ export async function getClusterResourceTypes() {
}
}
-
/**
* Submit user feedback
* @param {Object} params - Feedback parameters