diff --git a/src/pages/HelmApps.tsx b/src/pages/HelmApps.tsx index 33097bf..9c4d0a1 100644 --- a/src/pages/HelmApps.tsx +++ b/src/pages/HelmApps.tsx @@ -17,50 +17,11 @@ type Preset = { } const PRESETS: Preset[] = [ - // Databases & Caches - { id: 'mysql', name: 'MySQL (Bitnami)', chart: 'bitnami/mysql', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'mariadb', name: 'MariaDB (Bitnami)', chart: 'bitnami/mariadb', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'postgresql', name: 'PostgreSQL (Bitnami)', chart: 'bitnami/postgresql', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'mongodb', name: 'MongoDB (Bitnami)', chart: 'bitnami/mongodb', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'redis', name: 'Redis (Bitnami)', chart: 'bitnami/redis', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'minio', name: 'MinIO (MinIO)', chart: 'minio/minio', repo: 'https://charts.min.io/' }, - - // Messaging & Streaming - { id: 'rabbitmq', name: 'RabbitMQ (Bitnami)', chart: 'bitnami/rabbitmq', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'kafka', name: 'Kafka (Bitnami)', chart: 'bitnami/kafka', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'zookeeper', name: 'Zookeeper (Bitnami)', chart: 'bitnami/zookeeper', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'nats', name: 'NATS (Bitnami)', chart: 'bitnami/nats', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'emqx', name: 'EMQX (EMQ)', chart: 'emqx/emqx', repo: 'https://repos.emqx.io/charts' }, - - // Observability - { id: 'kube-prometheus-stack', name: 'Kube Prometheus Stack', chart: 'prometheus-community/kube-prometheus-stack', repo: 'https://prometheus-community.github.io/helm-charts' }, + { id: 'mysql', name: 'MySQL (Bitnami)', chart: 'mysql', repo: 'https://charts.bitnami.com/bitnami' }, + { id: 'postgresql', name: 'PostgreSQL (Bitnami)', chart: 'postgresql', repo: 'https://charts.bitnami.com/bitnami' }, + { id: 'redis', name: 'Redis (Bitnami)', chart: 'redis', repo: 'https://charts.bitnami.com/bitnami' }, + { id: 'grafana', name: 'Grafana (grafana)', chart: 'grafana', repo: 'https://grafana.github.io/helm-charts' }, { id: 'prometheus', name: 'Prometheus (prometheus-community)', chart: 'prometheus-community/prometheus', repo: 'https://prometheus-community.github.io/helm-charts' }, - { id: 'grafana', name: 'Grafana (grafana)', chart: 'grafana/grafana', repo: 'https://grafana.github.io/helm-charts' }, - { id: 'loki', name: 'Loki (grafana)', chart: 'grafana/loki', repo: 'https://grafana.github.io/helm-charts' }, - { id: 'tempo', name: 'Tempo (grafana)', chart: 'grafana/tempo', repo: 'https://grafana.github.io/helm-charts' }, - { id: 'jaeger', name: 'Jaeger (jaegertracing)', chart: 'jaegertracing/jaeger', repo: 'https://jaegertracing.github.io/helm-charts' }, - - // Ingress & Certs - { id: 'ingress-nginx', name: 'NGINX Ingress (ingress-nginx)', chart: 'ingress-nginx/ingress-nginx', repo: 'https://kubernetes.github.io/ingress-nginx' }, - { id: 'cert-manager', name: 'cert-manager (jetstack)', chart: 'jetstack/cert-manager', repo: 'https://charts.jetstack.io' }, - - // Search & Analytics - { id: 'elasticsearch', name: 'Elasticsearch (Bitnami)', chart: 'bitnami/elasticsearch', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'kibana', name: 'Kibana (Bitnami)', chart: 'bitnami/kibana', repo: 'https://charts.bitnami.com/bitnami' }, - - // Identity & Security - { id: 'keycloak', name: 'Keycloak (Bitnami)', chart: 'bitnami/keycloak', repo: 'https://charts.bitnami.com/bitnami' }, - { id: 'vault', name: 'HashiCorp Vault', chart: 'hashicorp/vault', repo: 'https://helm.releases.hashicorp.com' }, - - // CI/CD & GitOps - { id: 'argo-cd', name: 'Argo CD', chart: 'argo/argo-cd', repo: 'https://argoproj.github.io/argo-helm' }, - { id: 'jenkins', name: 'Jenkins (JenkinsCI)', chart: 'jenkinsci/jenkins', repo: 'https://charts.jenkins.io' }, - - // Registries & Platforms - { id: 'harbor', name: 'Harbor (goharbor)', chart: 'goharbor/harbor', repo: 'https://helm.goharbor.io' }, - - // CMS & Apps - { id: 'wordpress', name: 'WordPress (Bitnami)', chart: 'bitnami/wordpress', repo: 'https://charts.bitnami.com/bitnami' }, ] export default function HelmApps() { @@ -70,26 +31,12 @@ export default function HelmApps() { const [selectedNamespace, setSelectedNamespace] = useState('') const [search, setSearch] = useState('') - const [presetId, setPresetId] = useState('') const [releaseName, setReleaseName] = useState('') - const [chart, setChart] = useState('') - const [repo, setRepo] = useState('') const [version, setVersion] = useState('') - const [valuesYaml, setValuesYaml] = useState('') + const [selectedPreset, setSelectedPreset] = useState(null) const [isInstalling, setIsInstalling] = useState(false) const isInstallingRef = useRef(false) - - const applyPreset = (id: string) => { - setPresetId(id) - const p = PRESETS.find(x => x.id === id) - if (p) { - setChart(p.chart) - setRepo(p.repo) - setVersion(p.version || '') - if (!releaseName) setReleaseName(p.id) - if (p.defaults) setValuesYaml(p.defaults) - } - } + const [showDialog, setShowDialog] = useState(false) const fetchNamespaces = async () => { if (!clusterName) return @@ -105,25 +52,11 @@ export default function HelmApps() { } else if (response.status === 401) { navigate('/login') } - } catch (_err) { - } - } - - const encodeBase64Utf8 = (input: string): string => { - try { return btoa(unescape(encodeURIComponent(input))) } catch (_err) { - const bytes = new TextEncoder().encode(input) - let binary = '' - const chunkSize = 0x8000 - for (let i = 0; i < bytes.length; i += chunkSize) { - const chunk = bytes.subarray(i, i + chunkSize) - binary += String.fromCharCode.apply(null, Array.from(chunk)) - } - return btoa(binary) - } + } catch {} } const submitInstall = async () => { - if (!clusterName || !selectedNamespace || !releaseName.trim() || !chart.trim()) { + if (!clusterName || !selectedNamespace || !releaseName.trim() || !selectedPreset) { alert('Please fill in cluster, namespace, release, and chart') return } @@ -135,11 +68,10 @@ export default function HelmApps() { Clustername: clusterName, Namespace: selectedNamespace, Release: releaseName.trim(), - Chart: chart.trim(), - Repo: repo.trim(), + Chart: selectedPreset.chart, + Repo: selectedPreset.repo, } if (version.trim()) body.Version = version.trim() - if (valuesYaml.trim()) body.Values = encodeBase64Utf8(valuesYaml) const res = await fetch('http://localhost:8082/helm_install', { method: 'POST', @@ -147,46 +79,12 @@ export default function HelmApps() { body: JSON.stringify(body) }) if (res.ok) { - alert('Helm install request submitted successfully') + alert(`Helm install request submitted for ${selectedPreset.name}`) + setShowDialog(false) } else if (res.status === 401) { navigate('/login') } else { - const data = await res.json().catch(() => ({} as any)) - alert('Failed to install: ' + (data.message || 'Unknown error')) - } - } catch (err) { - alert('Failed to install: ' + err) - } finally { - isInstallingRef.current = false - setIsInstalling(false) - } - } - - const quickInstall = async (preset: Preset) => { - if (!clusterName || !selectedNamespace) { alert('Select a cluster and namespace first'); return } - if (isInstallingRef.current) return - isInstallingRef.current = true - setIsInstalling(true) - try { - const body: any = { - Clustername: clusterName, - Namespace: selectedNamespace, - Release: `${preset.id}-${Math.random().toString(36).slice(2,7)}`, - Chart: preset.chart, - Repo: preset.repo, - } - if (preset.version) body.Version = preset.version - if (preset.defaults) body.Values = encodeBase64Utf8(preset.defaults) - const res = await fetch('http://localhost:8082/helm_install', { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'Authorization': `${localStorage.getItem('auth:token') || ''}` }, - body: JSON.stringify(body) - }) - if (res.ok) { - alert(`Installing ${preset.name}...`) - } else if (res.status === 401) { navigate('/login') } - else { - const data = await res.json().catch(() => ({} as any)) + const data = await res.json().catch(() => ({})) alert('Failed to install: ' + (data.message || 'Unknown error')) } } catch (err) { @@ -234,68 +132,51 @@ export default function HelmApps() { -
- {/* One-click marketplace grid */} -
- {PRESETS.filter(p => !search || p.name.toLowerCase().includes(search.toLowerCase()) || p.id.includes(search.toLowerCase())).map(preset => ( -
-
{preset.name}
-
{preset.chart}
-
{preset.repo}
-
- - -
+ +
+ {PRESETS.filter(p => !search || p.name.toLowerCase().includes(search.toLowerCase()) || p.id.includes(search.toLowerCase())).map(preset => ( +
+
{preset.name}
+
{preset.chart}
+
{preset.repo}
+
+
- ))} -
- - {/* Advanced manual configuration */} -
-
Advanced Configuration
-
-
- -
-
- - setReleaseName(e.target.value)} placeholder="e.g., my-mysql" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" /> -
-
- - setChart(e.target.value)} placeholder="e.g., bitnami/mysql" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" /> -
-
- - setRepo(e.target.value)} placeholder="e.g., https://charts.bitnami.com/bitnami" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" /> -
-
- - setVersion(e.target.value)} placeholder="e.g., 13.1.2" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" /> -
-
- -
- -