fix(sdn): zone DNS is an SDN DNS entry id, not an IP — use select
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
import {
|
import {
|
||||||
useSDNStatus, useSDNZones, useSDNVNets, useSDNSubnets,
|
useSDNStatus, useSDNZones, useSDNVNets, useSDNSubnets, useSDNDns,
|
||||||
useCreateSDNZone, useUpdateSDNZone, useDeleteSDNZone,
|
useCreateSDNZone, useUpdateSDNZone, useDeleteSDNZone,
|
||||||
useCreateSDNVNet, useUpdateSDNVNet, useDeleteSDNVNet,
|
useCreateSDNVNet, useUpdateSDNVNet, useDeleteSDNVNet,
|
||||||
useCreateSDNSubnet, useDeleteSDNSubnet, useApplySDN,
|
useCreateSDNSubnet, useDeleteSDNSubnet, useApplySDN,
|
||||||
@@ -42,6 +42,9 @@ function ZoneDialog({ serverId, open, onOpenChange, editing }: {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const createZone = useCreateSDNZone(serverId);
|
const createZone = useCreateSDNZone(serverId);
|
||||||
const updateZone = useUpdateSDNZone(serverId);
|
const updateZone = useUpdateSDNZone(serverId);
|
||||||
|
// Zone `dns` is the ID of an SDN DNS entry (Datacenter → SDN → Options), not an IP
|
||||||
|
const { data: dnsData } = useSDNDns(serverId, open);
|
||||||
|
const dnsEntries = dnsData?.dns ?? [];
|
||||||
// Dialog is freshly mounted on each open, so init state lazily from `editing`.
|
// Dialog is freshly mounted on each open, so init state lazily from `editing`.
|
||||||
const [form, setForm] = useState<ZoneForm>(() => editing ? {
|
const [form, setForm] = useState<ZoneForm>(() => editing ? {
|
||||||
zone: editing.zone,
|
zone: editing.zone,
|
||||||
@@ -110,7 +113,22 @@ function ZoneDialog({ serverId, open, onOpenChange, editing }: {
|
|||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-3 gap-3">
|
||||||
<div><Label>MTU</Label><Input type="number" value={form.mtu} onChange={e => set('mtu', e.target.value)} className="mt-1" /></div>
|
<div><Label>MTU</Label><Input type="number" value={form.mtu} onChange={e => set('mtu', e.target.value)} className="mt-1" /></div>
|
||||||
<div><Label>{t('sdn.nodes')}</Label><Input value={form.nodes} onChange={e => set('nodes', e.target.value)} className="mt-1" placeholder="node1,node2" /></div>
|
<div><Label>{t('sdn.nodes')}</Label><Input value={form.nodes} onChange={e => set('nodes', e.target.value)} className="mt-1" placeholder="node1,node2" /></div>
|
||||||
<div><Label>DNS</Label><Input value={form.dns} onChange={e => set('dns', e.target.value)} className="mt-1" /></div>
|
<div>
|
||||||
|
<Label>DNS</Label>
|
||||||
|
<Select
|
||||||
|
value={form.dns}
|
||||||
|
onValueChange={v => set('dns', v === '__none__' ? '' : v)}
|
||||||
|
disabled={dnsEntries.length === 0}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-1">
|
||||||
|
<SelectValue placeholder={dnsEntries.length ? '—' : t('sdn.no_dns_entries')} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="__none__">—</SelectItem>
|
||||||
|
{dnsEntries.map(d => <SelectItem key={d.dns} value={d.dns}>{d.dns}</SelectItem>)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@@ -41,6 +41,20 @@ export function useSDNSubnets(serverId: number, vnet: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SDNDnsEntry {
|
||||||
|
dns: string;
|
||||||
|
type?: string;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSDNDns(serverId: number, enabled = true) {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['sdn-dns', serverId] as const,
|
||||||
|
queryFn: () => apiClient.get<{ dns: SDNDnsEntry[] }>(`/proxmox/api/servers/${serverId}/sdn/dns`),
|
||||||
|
enabled: serverId > 0 && enabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Invalidate the SDN status (pending indicator) alongside the changed entity.
|
// Invalidate the SDN status (pending indicator) alongside the changed entity.
|
||||||
function useSDNInvalidator(serverId: number) {
|
function useSDNInvalidator(serverId: number) {
|
||||||
const qc = useQueryClient();
|
const qc = useQueryClient();
|
||||||
|
|||||||
@@ -493,7 +493,8 @@
|
|||||||
"gateway": "Gateway",
|
"gateway": "Gateway",
|
||||||
"snat": "SNAT",
|
"snat": "SNAT",
|
||||||
"dnszoneprefix": "DNS zone prefix",
|
"dnszoneprefix": "DNS zone prefix",
|
||||||
"create_ipam": "Also create a matching IPAM network"
|
"create_ipam": "Also create a matching IPAM network",
|
||||||
|
"no_dns_entries": "No SDN DNS servers"
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
"title": "OS Templates",
|
"title": "OS Templates",
|
||||||
@@ -637,7 +638,6 @@
|
|||||||
"vmids_hint": "Comma-separated VMIDs (e.g. 100, 101) or 'all' for every VM/CT.",
|
"vmids_hint": "Comma-separated VMIDs (e.g. 100, 101) or 'all' for every VM/CT.",
|
||||||
"all_vms": "All VMs/CTs",
|
"all_vms": "All VMs/CTs",
|
||||||
"all_vms_selected": "All VMs/CTs on the node selected",
|
"all_vms_selected": "All VMs/CTs on the node selected",
|
||||||
"selected_count": "Selected: {{count}}",
|
|
||||||
"select_all_visible": "Select all visible",
|
"select_all_visible": "Select all visible",
|
||||||
"clear_selection": "Clear",
|
"clear_selection": "Clear",
|
||||||
"pick_server_node_first": "Select a server and node first",
|
"pick_server_node_first": "Select a server and node first",
|
||||||
@@ -945,4 +945,4 @@
|
|||||||
"connected": "Connected",
|
"connected": "Connected",
|
||||||
"error": "Error"
|
"error": "Error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -493,7 +493,8 @@
|
|||||||
"gateway": "Шлюз",
|
"gateway": "Шлюз",
|
||||||
"snat": "SNAT",
|
"snat": "SNAT",
|
||||||
"dnszoneprefix": "Префикс DNS-зоны",
|
"dnszoneprefix": "Префикс DNS-зоны",
|
||||||
"create_ipam": "Также создать соответствующую IPAM-сеть"
|
"create_ipam": "Также создать соответствующую IPAM-сеть",
|
||||||
|
"no_dns_entries": "Нет DNS-серверов SDN"
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
"title": "Шаблоны ОС",
|
"title": "Шаблоны ОС",
|
||||||
@@ -637,7 +638,6 @@
|
|||||||
"vmids_hint": "Список VMID через запятую (напр. 100, 101) или слово all для всех VM/CT.",
|
"vmids_hint": "Список VMID через запятую (напр. 100, 101) или слово all для всех VM/CT.",
|
||||||
"all_vms": "Все VM/CT",
|
"all_vms": "Все VM/CT",
|
||||||
"all_vms_selected": "Выбраны все VM/CT на узле",
|
"all_vms_selected": "Выбраны все VM/CT на узле",
|
||||||
"selected_count": "Выбрано: {{count}}",
|
|
||||||
"select_all_visible": "Выбрать все видимые",
|
"select_all_visible": "Выбрать все видимые",
|
||||||
"clear_selection": "Очистить",
|
"clear_selection": "Очистить",
|
||||||
"pick_server_node_first": "Сначала выберите сервер и узел",
|
"pick_server_node_first": "Сначала выберите сервер и узел",
|
||||||
@@ -945,4 +945,4 @@
|
|||||||
"connected": "Подключено",
|
"connected": "Подключено",
|
||||||
"error": "Ошибка"
|
"error": "Ошибка"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user