import React, { useState, useEffect } from "react"; import { Button } from '../ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "../ui/select"; import { Input } from "../ui/input"; import { Label } from "../ui/label"; import Loader from "../ui/loader"; import { useToast } from "../ui/toast"; import { Switch } from "../ui/switch"; export default function NewKubernetesService() { const { showToast } = useToast(); const [isLoading, setIsLoading] = useState(false); const [isFetchingData, setIsFetchingData] = useState(true); const [plans, setPlans] = useState([]); const [vpcs, setVpcs] = useState([]); const [subnets, setSubnets] = useState([]); const PUBLIC_UTHO_API_KEY = import.meta.env.PUBLIC_UTHO_API_KEY; const [formData, setFormData] = useState({ dcslug: "innoida", cluster_version: "1.24", cluster_label: "", nodepools: [{ label: "default-pool", size: "", count: 1, maxCount: 1 }], firewall: "", vpc: "", subnet: "", network_type: "public", cpumodel: "intel" }); useEffect(() => { const fetchInitialData = async () => { setIsFetchingData(true); try { const [plansResponse, vpcsResponse] = await Promise.all([ fetch("https://api.utho.com/v2/plans", { headers: { "Authorization": `Bearer ${PUBLIC_UTHO_API_KEY}`, "Content-Type": "application/json" } }), fetch("https://api.utho.com/v2/vpc", { headers: { "Authorization": `Bearer ${PUBLIC_UTHO_API_KEY}`, "Content-Type": "application/json" } }) ]); const plansData = await plansResponse.json(); const vpcsData = await vpcsResponse.json(); setPlans(plansData.plans || []); setVpcs(vpcsData.vpc || []); // Set default VPC if available if (vpcsData.vpc?.length > 0) { const firstVpc = vpcsData.vpc[0]; setFormData(prev => ({ ...prev, vpc: firstVpc.id })); // Fetch subnets for the default VPC await fetchSubnets(firstVpc.id); } } catch (error) { console.error("Initial data fetch error:", error); showToast({ title: "Error", description: "Failed to load initial configuration data", variant: "destructive" }); } finally { setIsFetchingData(false); } }; fetchInitialData(); }, []); const fetchSubnets = async (vpcId) => { try { // First try to get subnets from the VPC data const selectedVpc = vpcs.find(vpc => vpc.id === vpcId); if (selectedVpc?.subnet?.length > 0) { setSubnets(selectedVpc.subnet); setFormData(prev => ({ ...prev, subnet: selectedVpc.subnet[0].id })); return; } // If no subnets in VPC data, try the subnets endpoint const response = await fetch(`https://api.utho.com/v2/vpc/${vpcId}/subnets`, { headers: { "Authorization": `Bearer ${PUBLIC_UTHO_API_KEY}`, "Content-Type": "application/json" } }); if (response.ok) { const data = await response.json(); setSubnets(data.subnets || []); if (data.subnets?.length > 0) { setFormData(prev => ({ ...prev, subnet: data.subnets[0].id })); } } } catch (error) { console.error("Error fetching subnets:", error); } }; const handleVpcChange = async (vpcId) => { setFormData(prev => ({ ...prev, vpc: vpcId, subnet: "" })); await fetchSubnets(vpcId); }; const handleSubmit = async (e) => { e.preventDefault(); setIsLoading(true); try { // Validate required fields including subnet if (!formData.cluster_label || !formData.nodepools[0].size || !formData.vpc || !formData.subnet) { throw new Error("Please fill all required fields including VPC and Subnet"); } const payload = { dcslug: formData.dcslug, cluster_version: formData.cluster_version, cluster_label: formData.cluster_label, nodepools: formData.nodepools.map(pool => ({ label: pool.label, size: pool.size, count: pool.count.toString(), maxCount: pool.maxCount.toString() })), firewall: formData.firewall || undefined, vpc: formData.vpc, subnet: formData.subnet, // Now required based on API behavior network_type: formData.network_type, cpumodel: formData.cpumodel }; console.log("Deployment payload:", payload); const response = await fetch("https://api.utho.com/v2/kubernetes/deploy", { method: "POST", headers: { "Authorization": `Bearer ${PUBLIC_UTHO_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify(payload) }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "Failed to deploy Kubernetes cluster"); } if (data.status === "success") { showToast({ title: "Success", description: `Cluster ${data.cluster_id || data.id} is being deployed`, variant: "success" }); // Reset form setFormData(prev => ({ ...prev, cluster_label: "", nodepools: [{ label: "default-pool", size: "", count: 1, maxCount: 1 }], vpc: vpcs[0]?.id || "", subnet: subnets[0]?.id || "" })); } else { throw new Error(data.message || "Failed to deploy Kubernetes cluster"); } } catch (error) { showToast({ title: "Deployment Failed", description: error.message, variant: "destructive" }); console.error("Deployment error:", error); } finally { setIsLoading(false); } }; const handleChange = (e) => { const { name, value, type, checked } = e.target; setFormData(prev => ({ ...prev, [name]: type === "checkbox" ? checked : value })); }; const handleNodePoolChange = (index, field, value) => { const updatedNodePools = [...formData.nodepools]; updatedNodePools[index][field] = value; setFormData(prev => ({ ...prev, nodepools: updatedNodePools })); }; if (isFetchingData) { return (