'use client' import { useState } from 'react' import { useRouter } from 'next/navigation' import { Header } from '@/components/header' import { Footer } from '@/components/footer' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Alert, AlertDescription } from '@/components/ui/alert' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Container, Server, HardDrive, Shield, AlertCircle, Check, Plus, Minus, Cpu, GitBranch, Download, ExternalLink, } from 'lucide-react' import { useAuth } from '@/contexts/AuthContext' interface NodePool { id: string name: string size: string count: number autoscale: boolean minNodes?: number maxNodes?: number } interface ClusterSize { id: string name: string price: { daily: number monthly: number } } interface DeploymentResult { status: string clusterId?: string message?: string id?: string error?: string [key: string]: any } export default function KubernetesPage() { const router = useRouter() const { user } = useAuth() const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [success, setSuccess] = useState('') const [deploymentResult, setDeploymentResult] = useState(null) const [billingCycle, setBillingCycle] = useState<'daily' | 'monthly'>('monthly') // Form state const [clusterName, setClusterName] = useState('') const [k8sVersion, setK8sVersion] = useState('1.30.0-utho') const [nodePools, setNodePools] = useState([ { id: '1', name: 'default-pool', size: '10215', count: 2, autoscale: false, minNodes: 2, maxNodes: 4, }, ]) // Available cluster sizes const clusterSizes: ClusterSize[] = [ { id: '10215', name: '2 vCPU, 4GB RAM', price: { daily: 200, monthly: 4000 } }, { id: '10216', name: '4 vCPU, 8GB RAM', price: { daily: 300, monthly: 7000 } }, { id: '10217', name: '8 vCPU, 16GB RAM', price: { daily: 500, monthly: 12000 } }, { id: '10218', name: '16 vCPU, 32GB RAM', price: { daily: 800, monthly: 20000 } }, ] // Kubernetes versions const k8sVersions = ['1.30.0-utho', '1.29.0-utho', '1.28.0-utho'] // Mock user balance const userBalance = 15000 // Calculate total price const calculatePrice = () => { let total = 0 nodePools.forEach((pool) => { const size = clusterSizes.find((s) => s.id === pool.size) if (size) { total += size.price[billingCycle] * pool.count } }) return total } // Add node pool const addNodePool = () => { const newPool: NodePool = { id: Date.now().toString(), name: `pool-${nodePools.length + 1}`, size: '10215', count: 1, autoscale: false, minNodes: 1, maxNodes: 3, } setNodePools([...nodePools, newPool]) } // Remove node pool const removeNodePool = (id: string) => { if (nodePools.length > 1) { setNodePools(nodePools.filter((pool) => pool.id !== id)) } } // Update node pool const updateNodePool = (id: string, field: keyof NodePool, value: any) => { setNodePools(nodePools.map((pool) => (pool.id === id ? { ...pool, [field]: value } : pool))) } // Format node pools for API const formatNodePools = () => { return nodePools.map((pool) => ({ name: pool.name, size: pool.size, count: pool.count, autoscale: pool.autoscale, min_nodes: pool.minNodes || pool.count, max_nodes: pool.maxNodes || pool.count + 2, })) } const handleDeploy = async (e: React.FormEvent) => { e.preventDefault() setError('') setSuccess('') setDeploymentResult(null) if (!user) { router.push('/auth?redirect=/services/kubernetes') return } // Validate form if (!clusterName) { setError('Cluster name is required') return } // Validate cluster name if (!/^[a-z0-9-]+$/.test(clusterName)) { setError('Cluster name can only contain lowercase letters, numbers, and hyphens') return } // Check balance const totalPrice = calculatePrice() if (userBalance < totalPrice) { setError( `Insufficient balance. You need ₹${totalPrice.toFixed(2)} but only have ₹${userBalance.toFixed(2)}` ) return } setLoading(true) try { const response = await fetch('/api/services/deploy-kubernetes', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ cluster_label: clusterName, cluster_version: k8sVersion, nodepools: formatNodePools(), cycle: billingCycle, amount: totalPrice, }), }) const result: DeploymentResult = await response.json() if (!response.ok) { throw new Error(result.message || `Deployment failed with status ${response.status}`) } if (result.status === 'success') { setDeploymentResult(result) setSuccess( `Kubernetes cluster "${clusterName}" deployed successfully! Cluster ID: ${result.clusterId || result.id}` ) // Reset form after successful deployment setClusterName('') setNodePools([ { id: '1', name: 'default-pool', size: '10215', count: 2, autoscale: false, minNodes: 2, maxNodes: 4, }, ]) } else { throw new Error(result.message || 'Deployment failed') } } catch (err) { console.error('Deployment error:', err) setError(err instanceof Error ? err.message : 'Failed to deploy Kubernetes cluster') } finally { setLoading(false) } } const downloadKubeconfig = async (clusterId: string) => { try { const response = await fetch(`/api/services/deploy-kubernetes?clusterId=${clusterId}`) if (response.ok) { const blob = await response.blob() const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.style.display = 'none' a.href = url a.download = `kubeconfig-${clusterId}.yaml` document.body.appendChild(a) a.click() window.URL.revokeObjectURL(url) document.body.removeChild(a) } else { const errorData = await response.json() setError(errorData.message || 'Failed to download kubeconfig') } } catch (err) { console.error('Kubeconfig download error:', err) setError('Failed to download kubeconfig') } } const resetForm = () => { setDeploymentResult(null) setSuccess('') setError('') } return (
{/* Page Header */}

Kubernetes Edge

Managed Kubernetes clusters with auto-scaling and enterprise-grade security

{!user && ( You need to be logged in to deploy a Kubernetes cluster.{' '} Click here to login )} {deploymentResult ? ( Deployment Successful! Your Kubernetes cluster has been deployed successfully.

{deploymentResult.clusterId || deploymentResult.id}

{deploymentResult.status}

{deploymentResult.clusterId && ( )}
) : (
{/* Billing Cycle */} Billing Cycle Choose your preferred billing period setBillingCycle(v as 'daily' | 'monthly')} > Daily Monthly (Save 25%) {/* Cluster Configuration */} Cluster Configuration Configure your Kubernetes cluster settings
setClusterName(e.target.value.toLowerCase())} pattern="^[a-z0-9-]+$" required />

Only lowercase letters, numbers, and hyphens allowed

Location: Mumbai, India (Fixed)

All Kubernetes clusters are deployed in our Mumbai datacenter for optimal performance.

{/* Node Pools */} Node Pools Configure worker node pools for your cluster {nodePools.map((pool, index) => (
updateNodePool(pool.id, 'name', e.target.value)} className="max-w-xs" placeholder="Pool name" required /> {nodePools.length > 1 && ( )}
updateNodePool(pool.id, 'count', parseInt(e.target.value) || 1) } className="w-20 text-center" min="1" max="10" />
Pool cost: ₹ {(clusterSizes.find((s) => s.id === pool.size)?.price[billingCycle] || 0) * pool.count} /{billingCycle === 'daily' ? 'day' : 'month'}
))}
{/* Pricing Summary */} Order Summary
{nodePools.map((pool) => { const size = clusterSizes.find((s) => s.id === pool.size) const cost = (size?.price[billingCycle] || 0) * pool.count return (
{pool.name} ({pool.count} nodes × {size?.name}) ₹{cost}
) })}
Total ₹{calculatePrice()}/{billingCycle === 'daily' ? 'day' : 'month'}
Your Balance = calculatePrice() ? 'text-green-600' : 'text-red-600' } > ₹{userBalance.toFixed(2)}
{error && ( {error} )} {/* Deploy Button */}
)} {/* Features */} {!deploymentResult && (

Auto-scaling

Automatically scale nodes based on workload

Secure by Default

RBAC, network policies, and encryption

Load Balancing

Built-in load balancers for your services

Persistent Storage

SSD-backed persistent volumes

)}
) }