Your IP : 216.73.216.52


Current Path : /snap/lxd/38768/share/lxd-ui/assets/
Upload File :
Current File : //snap/lxd/38768/share/lxd-ui/assets/NetworkDetail-DO0qz03w.js

import{bH as j,bI as Ne,u as be,au as ne,c as E,d as s,a1 as ye,a6 as S,r as _,v as F,t as xe,bJ as we,bK as ve,bL as _e,f as W,h as L,aa as Ce,a9 as ce,k as B,x as f,j as t,R as y,H as J,s as K,z as D,C as le,L as de,Q as ue,ab as ke,J as O,b3 as z,O as $,bM as Pe,aY as Se,bN as me,S as pe,bO as Le,p as G,w as X,T as Te,bP as Ie,bQ as Re,bm as Fe}from"./index-BsQN_SZU.js";import{b as $e,e as Me,g as Ee,d as Ue,r as qe,h as Ae,u as ge}from"./useNetworks-1j5RF-bH.js";import{t as De,N as Be,i as Ke}from"./NetworkForm-CUPjrYLG.js";import{y as Oe,o as Ve,Y as He}from"./YamlSwitch-BStSXJFs.js";import{C as Ye,G as Y,Y as A}from"./NetworkFormMenu-jasNljC3.js";import{F as Qe}from"./FormFooterLayout-CcbL_-PB.js";import{F as We}from"./FormSubmitBtn-DEfKgZu7.js";import{s as Je}from"./scroll-Dc7Cgzms.js";import{N as T}from"./NetworkRichChip-Cp8QBNS_.js";import{R as ze}from"./RenameHeader-BdCO5Nid.js";import{a as Z}from"./ClusterMemberRichChip-Di9w-E3M.js";import{T as Ge}from"./TabLinks-N89T_JJh.js";import{d as Xe,a as Ze}from"./network-forwards-CAuMAfcF.js";import{E as et}from"./ExpandableList-DsGr0BpD.js";import{u as M,p as se}from"./usePanelParams-CNAJZsSX.js";import{I as tt}from"./InstanceIpEdit-Dh7Kdppb.js";import{P as he}from"./ProjectRichChip-DZzjTfq6.js";import{A as at}from"./AutoExpandingTextArea-Bd-45rZK.js";import{N as nt}from"./NetworkSelector-DuJmwRYk.js";import"./SshKeyForm-BNz7yPwa.js";import"./limits-yeXZOxhv.js";import"./formFields-DzJouV_d.js";import"./ConfigFieldDescription-CjXKAIpa.js";import"./snapshots-LtzKNDw1.js";import"./ClusterSpecificSelect-B2H3HpuO.js";import"./ClusterSpecificInput-7EvfCd3b.js";import"./UsedByItem-DYTdOZkC.js";import"./NetworkDefaultACLSelector-8KsXe1ya.js";import"./useNetworkAcls-Bl3lzJua.js";import"./network-acls-bpCzo6oH.js";import"./formChangeCount-Kjdextdt.js";import"./ClusterMemberMemoryUsage-DYUQFY0n.js";import"./Meter-cq8smrSm.js";const Q=(e,a,n)=>{const r={};a?.forEach(d=>r[d.memberName]=d.config.parent??"");const i={};a?.forEach(d=>i[d.memberName]=d.config[j("bridge_external_interfaces")]??"");const c=Object.values(i).find(d=>d.length>0);return{readOnly:!0,isCreating:!1,name:e.name,description:e.description,networkType:e.type,bridge_driver:e.config[j("bridge_driver")],bridge_external_interfaces:c?"set":e.config[j("bridge_external_interfaces")],bridge_external_interfaces_per_member:i,bridge_hwaddr:e.config[j("bridge_hwaddr")],bridge_mtu:e.config[j("bridge_mtu")],dns_domain:e.config[j("dns_domain")],dns_mode:e.config[j("dns_mode")],dns_nameservers:e.config[j("dns_nameservers")],dns_search:e.config[j("dns_search")],gvrp:e.config.gvrp,ipv4_address:e.config[j("ipv4_address")],ipv4_dhcp:e.config[j("ipv4_dhcp")],ipv4_dhcp_expiry:e.config[j("ipv4_dhcp_expiry")],ipv4_dhcp_ranges:e.config[j("ipv4_dhcp_ranges")],ipv4_l3only:e.config[j("ipv4_l3only")],ipv4_nat:e.config[j("ipv4_nat")],ipv4_nat_address:e.config[j("ipv4_nat_address")],ipv4_ovn_ranges:e.config[j("ipv4_ovn_ranges")],ipv4_gateway:e.config[j("ipv4_gateway")],ipv4_routes:e.config[j("ipv4_routes")],ipv4_routes_anycast:e.config[j("ipv4_routes_anycast")],ipv6_address:e.config[j("ipv6_address")],ipv6_dhcp:e.config[j("ipv6_dhcp")],ipv6_dhcp_expiry:e.config[j("ipv6_dhcp_expiry")],ipv6_dhcp_ranges:e.config[j("ipv6_dhcp_ranges")],ipv6_dhcp_stateful:e.config[j("ipv6_dhcp_stateful")],ipv6_l3only:e.config[j("ipv6_l3only")],ipv6_nat:e.config[j("ipv6_nat")],ipv6_nat_address:e.config[j("ipv6_nat_address")],ipv6_ovn_ranges:e.config[j("ipv6_ovn_ranges")],ipv6_gateway:e.config[j("ipv6_gateway")],ipv6_routes:e.config[j("ipv6_routes")],ipv6_routes_anycast:e.config[j("ipv6_routes_anycast")],mtu:e.config.mtu,ovn_ingress_mode:e.config[j("ovn_ingress_mode")],network:e.config.network,parent:e.config.parent,security_acls:Ne(e),vlan:e.config.vlan,parentPerClusterMember:r,entityType:"network",bareNetwork:e,editRestriction:n,security_acls_default_egress:e.config[j("security_acls_default_egress")],security_acls_default_ingress:e.config[j("security_acls_default_ingress")]}},C=()=>{const{isFineGrained:e}=be();return{canDeleteNetwork:r=>ne(e,"can_delete",r?.access_entitlements),canEditNetwork:r=>ne(e,"can_edit",r?.access_entitlements)}},st=({network:e,project:a})=>{const n=E(),r=s.useNotify(),i=s.useToastNotification(),{hash:c}=ye(),d=c?c.substring(1):S(Ye),[m,g]=_.useState(d),h=F(),o=_.useState(null),[b,p]=_.useState(0),{data:u=[]}=xe(),{canEditNetwork:N}=C(),l=e.managed&&we.includes(e.type),{data:k=[],error:x}=$e(e.name,a,l);_.useEffect(()=>{x&&r.failure("Loading network from cluster members failed",x)},[x]);const P=k.filter(ve);_.useEffect(()=>{_e(k,r)},[k]);const V=W().shape({name:L().test("deduplicate","A network with this name already exists",async w=>w===e.name||ce(w,a,o,"networks")).required("Network name is required"),network:L().test("required","Uplink network is required",(w,I)=>I.parent.networkType!==Ce||!!w)}),U=N(e)?void 0:"You do not have permission to edit this network",v=B({initialValues:Q(e,P,U),validationSchema:V,enableReinitialize:!0,onSubmit:w=>{const I=w.yaml?w.yaml:q(),te=Oe(I),ae={...te,etag:e.etag};(async R=>R.parentPerClusterMember&&Object.keys(R.parentPerClusterMember).length>0?Me(ae,a,u,R.parentPerClusterMember,R.bridge_external_interfaces_per_member,e.config):Ee(ae,a))(w).then(()=>{v.resetForm({values:Q(te,P)}),h.invalidateQueries({queryKey:[f.projects,a,f.networks,e.name]}),h.invalidateQueries({queryKey:[f.projects,a,f.networks,e.name,f.cluster]}),i.success(t.jsxs(t.Fragment,{children:["Network","",t.jsx(T,{networkName:e.name,projectName:a})," ","updated."]}))}).catch(R=>{r.failure("Network update failed",R)}).finally(()=>{v.setSubmitting(!1)})}}),q=()=>{const w=De(v.values);return Ve(w)};_.useEffect(()=>{Je(d),g(d)},[d]);const H=`${y}/ui/project/${encodeURIComponent(a)}/network/${encodeURIComponent(e.name)}`,ee=(w,I)=>{I==="scroll"&&m===S(A)||(I==="click"&&n(w===Y?H:`${H}/#${S(w)}`),g(S(w)))},fe=v.values.readOnly;return t.jsxs(t.Fragment,{children:[t.jsx(Be,{formik:v,getYaml:q,project:a,section:m??S(Y),setSection:ee,version:b},e.name),t.jsxs(Qe,{children:[t.jsx(He,{formik:v,section:m,setSection:()=>{ee(m===S(A)?Y:A,"click")},disableReason:v.values.name?void 0:"Please enter a network name to enable this section"}),fe?null:t.jsxs(t.Fragment,{children:[t.jsx(s.Button,{appearance:"base",onClick:()=>{p(w=>w+1),v.setValues(Q(e,P))},children:"Cancel"}),t.jsx(We,{formik:v,baseUrl:H,isYaml:m===S(A),disabled:Ke(v,u)})]})]})]})},rt=({network:e,project:a})=>{const n=s.useNotify(),r=s.useToastNotification(),i=F(),[c,d]=_.useState(!1),m=E(),g=J(),{canDeleteNetwork:h}=C(),o=()=>{d(!0),Ue(e.name,a).then(()=>{i.invalidateQueries({predicate:N=>N.queryKey[0]===f.projects&&N.queryKey[1]===a&&N.queryKey[2]===f.networks}),m(`${y}/ui/project/${encodeURIComponent(a)}/networks`),r.success(t.jsxs(t.Fragment,{children:["Network ",t.jsx(D,{bold:!0,type:"network",value:e.name})," ","deleted."]}))}).catch(N=>{d(!1),n.failure("Network deletion failed",N)})},b=(e.used_by?.length??0)>0,p=e.managed,u=()=>h(e)?p?b?"Can not delete, network is currently in use":"":"Can not delete, network is not managed":"You do not have permission to delete this network";return t.jsxs(s.ConfirmationButton,{onHoverText:u(),confirmationModalProps:{title:"Confirm delete",confirmButtonAppearance:"negative",confirmButtonLabel:"Delete",children:t.jsxs("p",{children:["Are you sure you want to delete the network"," ",t.jsx(T,{networkName:e.name,projectName:a}),"?",t.jsx("br",{}),"This action cannot be undone, and can result in data loss."]}),onConfirm:o},className:K("u-no-margin--bottom",{"has-icon":!g}),loading:c,disabled:!h(e)||b||!p||c,shiftClickEnabled:!0,showShiftClickHint:!0,children:[!g&&t.jsx(s.Icon,{name:"delete"}),t.jsx("span",{children:"Delete network"})]})},ot=({name:e,network:a,project:n})=>{const{member:r}=le(),i=E(),c=s.useNotify(),d=s.useToastNotification(),m=_.useState(null),{canEditNetwork:g}=C(),h=W().shape({name:L().test("deduplicate","A network with this name already exists",async N=>a?.name===N||ce(N,n,m,"networks")).required("Network name is required")}),o=B({initialValues:{name:e,isRenaming:!1},validationSchema:h,onSubmit:N=>{if(e===N.name){o.setFieldValue("isRenaming",!1),o.setSubmitting(!1);return}qe(e,N.name,n).then(()=>{const l=`${y}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(N.name)}`;i(l),d.success(t.jsxs(t.Fragment,{children:["Network ",t.jsx("strong",{children:e})," renamed to"," ",t.jsx(T,{networkName:N.name,projectName:n})]})),o.setFieldValue("isRenaming",!1)}).catch(l=>{c.failure("Renaming failed",l)}).finally(()=>{o.setSubmitting(!1)})}}),b=(a?.used_by?.length??0)>0,p=a?.managed,u=()=>{if(!g(a))return"You do not have permission to rename this network";if(!p)return"Can not rename, network is not managed";if(b)return"Can not rename, network is currently in use."};return t.jsx(ze,{name:e,relatedChip:r&&t.jsx(Z,{clusterMember:r}),parentItems:[t.jsx(de,{to:`${y}/ui/project/${encodeURIComponent(n)}/networks`,children:"Networks"},1)],renameDisabledReason:u(),controls:a&&t.jsx(rt,{network:a,project:n}),isLoaded:!!a,formik:o})},it=({network:e,forward:a,project:n})=>{const r=s.useNotify(),i=s.useToastNotification(),c=F(),[d,m]=_.useState(!1),{canEditNetwork:g}=C(),h=()=>{m(!0),Xe(e,a,n).then(()=>{i.success(t.jsxs(t.Fragment,{children:["Network forward with listen address"," ",t.jsx(D,{type:"network-forward",value:a.listen_address,bold:!0})," ","deleted."]})),c.invalidateQueries({predicate:o=>o.queryKey[0]===f.projects&&o.queryKey[1]===n&&o.queryKey[2]===f.networks&&o.queryKey[3]===e.name})}).catch(o=>{m(!1),r.failure("Network forward deletion failed",o)})};return t.jsx(s.ConfirmationButton,{appearance:"base",onHoverText:g(e)?"Delete network forward":"You do not have permission to delete this network forward",confirmationModalProps:{title:"Confirm delete",confirmButtonAppearance:"negative",confirmButtonLabel:"Delete",children:t.jsxs("p",{children:["Are you sure you want to delete the network forward with listen address"," ",t.jsx(D,{type:"network-forward",value:a.listen_address,bold:!0}),"?",t.jsx("br",{})]}),onConfirm:h},className:"u-no-margin--bottom has-icon",loading:d,shiftClickEnabled:!0,showShiftClickHint:!0,disabled:!g(e)||d,children:t.jsx(s.Icon,{name:"delete"})})},ct=({port:e})=>{const a=e.target_port&&e.target_port.length>0?e.target_port:e.listen_port,r=`:${e.listen_port} → ${e.target_address}:${a} (${e.protocol})`;return t.jsx("div",{className:"u-truncate",title:r,children:r})},re=({network:e,className:a})=>{const n=J(),{canEditNetwork:r}=C(),i=M(),c=E();return t.jsxs(s.Button,{appearance:"positive",hasIcon:!n,onClick:()=>{c(`${y}/ui/project/${encodeURIComponent(i.project)}/network/${encodeURIComponent(e.name)}/forwards/create`)},className:K("p-button--positive u-no-margin--bottom",a),disabled:!r(e),title:r(e)?"Create forward":"You do not have permission to create network forwards for this network",children:[!n&&t.jsx(s.Icon,{name:"plus",light:!0}),t.jsx("span",{children:"Create forward"})]})},lt=({network:e,project:a})=>{const n=s.useNotify(),{canEditNetwork:r}=C(),c=ue()&&e?.type===ke,{data:d=[],error:m,isLoading:g}=O({queryKey:[f.projects,a,f.networks,e.name,f.forwards],queryFn:async()=>Ze(e.name,a)});m&&n.failure("Loading network forwards failed",m);const h=d.length>0,o=[{content:"Listen address",sortKey:"listenAddress"},{content:"Description",sortKey:"description"},{content:"Default target address",sortKey:"defaultTarget"},{content:"Ports"},...c?[{content:"Location",sortKey:"location"}]:[],{"aria-label":"Actions",className:"u-align--right actions"}],b=d.map(p=>({key:p.listen_address,columns:[{content:p.listen_address,role:"rowheader","aria-label":"Listen address"},{content:p.description,role:"cell","aria-label":"Description"},{content:p.config.target_address,role:"cell","aria-label":"Default target address"},{content:t.jsx(et,{items:p.ports.map(u=>t.jsx(ct,{port:u},u.listen_port))}),role:"cell","aria-label":"Forwarded ports"},...c?[{content:t.jsx(Z,{clusterMember:p.location??""}),role:"cell"}]:[],{content:t.jsxs(t.Fragment,{children:[r(e)&&t.jsx(de,{className:"p-button--base u-no-margin--bottom has-icon",to:c?`${y}/ui/project/${encodeURIComponent(a)}/network/${encodeURIComponent(e.name)}/member/${encodeURIComponent(p.location??"")}/forwards/${encodeURIComponent(p.listen_address)}/edit`:`${y}/ui/project/${encodeURIComponent(a)}/network/${encodeURIComponent(e.name)}/forwards/${encodeURIComponent(p.listen_address)}/edit`,title:"Edit network forward",children:t.jsx(s.Icon,{name:"edit"})}),!r(e)&&t.jsx(s.Button,{appearance:"base",className:"u-no-margin--bottom",dense:!0,hasIcon:!0,type:"button",title:"You do not have permission to edit forwards for this network",disabled:!0,children:t.jsx(s.Icon,{name:"edit"})},"edit"),t.jsx(it,{network:e,forward:p,project:a},p.listen_address+p.location)]}),role:"cell",className:"u-align--right actions","aria-label":"Actions"}],sortData:{listenAddress:p.listen_address,description:p.description,defaultTarget:p.config.target_address??"",location:p.location}}));return g?t.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):t.jsxs(t.Fragment,{children:[h&&t.jsx(re,{network:e,className:"u-float-right"}),t.jsxs(s.Row,{children:[h&&t.jsx(s.ScrollableTable,{dependencies:d,tableId:"network-forwards-table",belowIds:["status-bar"],children:t.jsx(s.MainTable,{id:"network-forwards-table",headers:o,expanding:!0,rows:b,paginate:30,sortable:!0,defaultSort:"listenAddress",defaultSortDirection:"ascending",className:"u-table-layout--auto network-forwards-table",emptyStateMsg:"No data to display"})}),!g&&!h&&t.jsxs(s.EmptyState,{className:"empty-state",image:t.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No network forwards found",children:[t.jsx("p",{children:"There are no network forwards in this project."}),t.jsx("p",{children:t.jsx(z,{docPath:"/howto/network_forwards/",hasExternalIcon:!0,children:"Learn more about network forwards"})}),!h&&t.jsx(re,{network:e,className:"empty-state-button"})]})]})]})},dt=async(e,a)=>{const n=new URLSearchParams;return n.set("project",a),n.set("recursion","1"),fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/leases?${n.toString()}`).then($).then(r=>r.metadata)},ut=({network:e,project:a})=>{const n=s.useNotify(),r=ue(),{data:i=[],error:c,isLoading:d}=O({queryKey:[f.projects,a,f.networks,e.name,f.leases],queryFn:async()=>dt(e.name,a)});c&&n.failure("Loading network leases failed",c);const m=i.length>0,g=[{content:"Type",sortKey:"type",className:"type"},{content:"Hostname",sortKey:"hostname",className:"hostname"},{content:"Project",sortKey:"project",className:"project"},...r?[{content:"Cluster member",sortKey:"clusterMember",className:"clusterMember"}]:[],{content:"MAC address",sortKey:"macAddress",className:"macAddress"},{content:"IP Address",sortKey:"address",className:"ipAddress"}],h=i.map(o=>({key:o.address+o.hostname+o.type,columns:[{content:o.type,role:"cell","aria-label":"Type",className:"type"},{content:o.hostname,role:"rowheader","aria-label":"Hostname",className:"hostname"},{content:o.project&&t.jsx(he,{projectName:o.project}),role:"cell","aria-label":"project",className:"project"},...r?[{content:o.location&&t.jsx(Z,{clusterMember:o.location}),role:"cell","aria-label":"Cluster member",className:"clusterMember"}]:[],{content:o.hwaddr,role:"cell","aria-label":"MAC address",className:"macAddress"},{content:Pe.includes(e.type)&&["static","dynamic"].includes(o.type)?t.jsx(tt,{address:o.address,instanceName:o.hostname,projectName:o.project}):t.jsx(t.Fragment,{children:o.address}),role:"cell","aria-label":"IP address",className:"ipAddress"}],sortData:{hostname:o.hostname.toLowerCase(),macAddress:o.hwaddr,type:o.type,project:o.project?.toLowerCase(),clusterMember:o.location?.toLowerCase(),address:o.address}}));return d?t.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):t.jsxs(s.Row,{children:[m&&t.jsx(s.ScrollableTable,{dependencies:i,tableId:"network-lease-table",belowIds:["status-bar"],children:t.jsx(s.MainTable,{id:"network-lease-table",headers:g,expanding:!0,rows:h,responsive:!0,sortable:!0,defaultSort:"address",defaultSortDirection:"ascending",className:"network-leases-table",emptyStateMsg:"No data to display"})}),!d&&!m&&t.jsxs(s.EmptyState,{className:"empty-state",image:t.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No network leases found",children:[t.jsx("p",{children:"There are no network leases in this project."}),t.jsx("p",{children:t.jsx(z,{docPath:"/howto/network_ipam/#view-dhcp-leases-for-fully-controlled-networks",hasExternalIcon:!0,children:"Learn more about network leases"})})]})]})},mt=async(e,a)=>{const n=new URLSearchParams;return n.set("project",a),n.set("recursion","1"),fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/peers?${n.toString()}`).then($).then(r=>(r.metadata.sort((i,c)=>i.name.localeCompare(c.name)),r.metadata))},pt=async(e,a,n)=>{const r=new URLSearchParams;return r.set("project",a),fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/peers/${encodeURIComponent(n)}?${r.toString()}`).then($).then(i=>i.metadata)},oe=async(e,a,n)=>{const r=new URLSearchParams;r.set("project",a),await fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/peers?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"},body:n}).then($)},gt=async(e,a,n)=>{const r=new URLSearchParams;r.set("project",a),await fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/peers/${encodeURIComponent(n)}?${r.toString()}`,{method:"DELETE"}).then($)},ht=async(e,a,n,r)=>{const i=new URLSearchParams;i.set("project",n),await fetch(`${y}/1.0/networks/${encodeURIComponent(e)}/peers/${encodeURIComponent(a)}?${i.toString()}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}).then($)},jt=({value:e,setValue:a,projects:n,hasNoneOption:r=!1,...i})=>{const c=()=>{const m=n.map(g=>({label:t.jsx("div",{className:"label",children:t.jsx("span",{title:g.name,className:"project-option u-truncate",children:g.name})}),value:g.name,text:g.name,disabled:!1}));return m.length===0&&m.unshift({label:t.jsx("span",{children:"No projects available"}),value:"",text:"None",disabled:!0}),r&&m.push({label:t.jsx("div",{className:"label",children:t.jsx("span",{title:"No project",className:"project-option u-truncate",children:"No project"})}),value:"none",text:"No project",disabled:!1}),m},d=()=>t.jsx("div",{className:"header",children:t.jsx("span",{className:"project-option u-no-margin--bottom",children:"Name"})});return t.jsx(s.CustomSelect,{label:"Project",...i,onChange:m=>{a(m)},value:e,options:c(),header:d(),dropdownClassName:"project-select-dropdown","aria-label":"Project"})},je=({formik:e,network:a,isEditing:n})=>{const r="Manually enter project",i="Manually enter network",{canEditNetwork:c}=C(),{data:d=[]}=Se(),{data:m=[]}=Ae(e.values.targetProject||"default",void 0,e.values.targetProject===r?!1:void 0),g=[...d,{name:r,config:{},description:""}],o=[...m.filter(u=>me.includes(u.type)).filter(u=>u.name!==a.name),{name:i,type:"ovn",config:{}}],b=u=>({id:u,name:u,onBlur:e.handleBlur,onChange:e.handleChange,value:e.values[u]??"",error:e.touched[u]?e.errors[u]:null,placeholder:`Enter ${u.replaceAll("-"," ")}`}),p=c(a)?"":"You do not have permission to edit this network";return t.jsxs(s.Form,{onSubmit:e.handleSubmit,className:"local-peering-create-form",children:[t.jsx(s.Input,{type:"submit",hidden:!0,value:"Hidden input"}),t.jsx(s.Input,{...b("name"),type:"text",label:"Name",required:!0,autoFocus:!n,disabled:n||!!p,title:"Name cannot be changed"}),t.jsx(at,{...b("description"),label:"Description",disabled:!!p,title:p,autoFocus:n}),n?t.jsx(s.Input,{id:"targetProject",type:"text",label:"Target project",value:e.values.targetProject,title:"Target project cannot be changed",required:!0,disabled:!0}):t.jsx(jt,{id:"targetProject",name:"targetProject",label:"Target project",value:e.values.targetProject,setValue:u=>{e.setFieldValue("targetProject",u,!1),e.setFieldValue("customTargetProject","",!1),u===r?e.setFieldValue("targetNetwork",i,!1):e.setFieldValue("targetNetwork","",!1),e.setFieldValue("customTargetNetwork","",!1),e.setFieldValue("createMutualPeering",!1,!1),setTimeout(()=>{e.validateForm()},100)},disabled:!!p,projects:g,required:!0}),e.values.targetProject===r&&t.jsx(s.Input,{id:"customTargetProject",name:"customTargetProject",type:"text",placeholder:"Enter target project name",value:e.values.customTargetProject,onChange:e.handleChange,onBlur:e.handleBlur}),n?t.jsx(s.Input,{id:"targetNetwork",type:"text",label:"Target network",value:e.values.targetNetwork,title:"Target network cannot be changed",required:!0,disabled:!0}):e.values.targetProject&&e.values.targetProject!==r&&t.jsx(nt,{id:"targetNetwork",name:"targetNetwork",label:"Target network",value:e.values.targetNetwork,setValue:u=>{e.setFieldValue("targetNetwork",u,!1),u===i?e.setFieldValue("createMutualPeering",!1,!0):(e.setFieldValue("customTargetNetwork","",!1),e.setFieldValue("createMutualPeering",!0,!1)),setTimeout(()=>{e.validateForm()},100)},networkList:o,help:e.values.targetNetwork!==i&&"Peering is limited to intra-cluster OVN networks; non-OVN or cross-cluster network peering is not supported.",required:!0}),(e.values.targetNetwork===i||e.values.targetProject===r)&&t.jsx(s.Input,{id:"customTargetNetwork",name:"customTargetNetwork",type:"text",label:(e.values.targetNetwork!==i||e.values.targetProject===r)&&"Target network",placeholder:"Enter target network name",value:e.values.customTargetNetwork,onChange:e.handleChange,onBlur:e.handleBlur,help:"Peering is limited to intra-cluster OVN networks; non-OVN or cross-cluster network peering is not supported.",required:!0}),!n&&t.jsx(s.Input,{id:"createMutualPeering",name:"createMutualPeering",type:"checkbox",label:"Create mutual peering",checked:e.values.createMutualPeering,onChange:u=>{e.setFieldValue("createMutualPeering",u.target.checked)},disabled:e.values.targetNetwork===i||e.values.targetProject===r,title:e.values.targetNetwork===i||e.values.targetProject===r?"Unavailable when using manual network or project entry":""})]})},ft=({network:e})=>{const a=M(),{project:n}=pe(),r=s.useNotify(),i=s.useToastNotification(),c=F(),d=_.useState(null),m=()=>{a.clear(),r.clear()},g=`${y}/ui/project/${encodeURIComponent(n?.name??"")}/network/${encodeURIComponent(e.name)}`,h="Manually enter project",o="Manually enter network",b=W().shape({targetProject:L().required("Target project is required"),customTargetProject:L().nullable().when("targetProject",{is:l=>l===h,then:l=>l.required("Please enter a project name"),otherwise:l=>l.notRequired()}),targetNetwork:L().when("targetProject",{is:l=>l!==h,then:l=>l.required("Target network is required"),otherwise:l=>l.notRequired()}),customTargetNetwork:L().nullable().when("targetNetwork",{is:l=>l===o,then:l=>l.required("Please enter a network name"),otherwise:l=>l.notRequired()}),name:L().test(...Le(a.project,e.name,d)).required("Local peering name is required")}),p=l=>{i.success(t.jsxs(t.Fragment,{children:["Local peering"," ",t.jsx(X,{type:"peering",value:l,to:`${g}/local-peerings`})," ","created for network"," ",t.jsx(T,{networkName:e.name,projectName:n?.name||"default"})]})),m()},u=()=>{c.invalidateQueries({queryKey:[f.projects,a.project,f.networks,e.name,f.peers]})},N=B({initialValues:{name:"",description:"",targetProject:n?.name||"",targetNetwork:"",customTargetNetwork:"",customTargetProject:"",createMutualPeering:!1},validationSchema:b,validateOnMount:!0,validateOnChange:!0,validateOnBlur:!0,onSubmit:l=>{const k={name:l.name,description:l.description,target_project:l.targetProject===h?l.customTargetProject:l.targetProject,target_network:l.targetNetwork===o?l.customTargetNetwork:l.targetNetwork};oe(e.name,a.project,JSON.stringify(k)).then(()=>{if(N.values.createMutualPeering){const x={name:l.name,description:l.description,target_project:a.project,target_network:e.name};oe(l.targetNetwork,l.targetProject,JSON.stringify(x)).then(()=>{u(),p(l.name)}).catch(P=>{N.setSubmitting(!1),u(),r.failure("Mutual local peering creation failed",P)})}else u(),p(l.name)}).catch(x=>{N.setSubmitting(!1),r.failure("Local peering creation failed",x)})}});return t.jsx(t.Fragment,{children:t.jsxs(s.SidePanel,{children:[t.jsx(s.SidePanel.Header,{children:t.jsx(s.SidePanel.HeaderTitle,{children:"Create local peering"})}),t.jsx(G,{className:"u-no-padding"}),t.jsx(s.SidePanel.Content,{className:"u-no-padding",children:t.jsx(s.ScrollableContainer,{dependencies:[r.notification],belowIds:["panel-footer"],children:t.jsx(je,{formik:N,network:e})})}),t.jsxs(s.SidePanel.Footer,{className:"u-align--right",children:[t.jsx(s.Button,{appearance:"base",onClick:m,className:"u-no-margin--bottom",children:"Cancel"}),t.jsx(s.ActionButton,{appearance:"positive",loading:N.isSubmitting,onClick:()=>{N.submitForm()},className:"u-no-margin--bottom",disabled:!N.isValid||N.isSubmitting||!N.values.name,children:"Create local peering"})]})]})})},Nt=(e,a)=>O({queryKey:[f.projects,a,f.networks,e.name,f.peers],queryFn:async()=>mt(e.name,a)}),bt=(e,a,n)=>O({queryKey:[f.projects,a,f.networks,e.name,f.peers,n],queryFn:async()=>pt(e.name,a,n)}),ie=({network:e,className:a})=>{const n=J(),{canEditNetwork:r}=C(),i=M();return t.jsxs(s.Button,{appearance:"positive",hasIcon:!n,onClick:()=>{i.openCreateLocalPeering()},className:K("p-button--positive",a),disabled:!r(e),title:r(e)?"Create local peering":"You do not have permission to create local peerings for this network",children:[!n&&t.jsx(s.Icon,{name:"plus",light:!0}),t.jsx("span",{children:"Create local peering"})]})},yt=({network:e,localPeering:a})=>{const n=s.useNotify(),[r,i]=_.useState(!1),c=F(),{canEditNetwork:d}=C(),{project:m}=pe(),g=m?.name||"",h=s.useToastNotification(),o=`${y}/ui/project/${encodeURIComponent(g)}/network/${encodeURIComponent(e.name)}`,b=()=>{h.success(t.jsxs(t.Fragment,{children:["Local peering ",t.jsx(D,{type:"peering",value:a,bold:!0})," ","deleted for network"," ",t.jsx(T,{networkName:e.name,projectName:g})]}))},p=()=>{i(!0),gt(e.name,g,a).then(b).catch(u=>{n.failure("Local peering deletion failed",u)}).finally(()=>{i(!1),c.invalidateQueries({queryKey:[f.projects,g,f.networks,e.name,f.peers]})})};return t.jsx(s.ConfirmationButton,{loading:r,confirmationModalProps:{title:"Confirm delete",children:t.jsxs("p",{children:["This will permanently delete the local peering"," ",t.jsx(X,{type:"peering",value:a,to:`${o}/local-peerings`})," ","for network"," ",t.jsx(T,{networkName:e.name,projectName:g}),".",t.jsx("br",{})]}),confirmButtonLabel:"Delete",onConfirm:p},appearance:"base",className:"has-icon",shiftClickEnabled:!0,showShiftClickHint:!0,disabled:!d(e),onHoverText:d(e)?"Delete local peering":"You do not have permission to delete this local peering.",children:t.jsx(s.Icon,{name:"delete"})})},xt=({network:e,localPeering:a})=>{const n=M(),{canEditNetwork:r}=C(),i=r(e)?"Edit local peering":"You do not have permission to edit this local peering";return t.jsx(s.Button,{appearance:"base",hasIcon:!0,onClick:()=>{n.openEditLocalPeering(a)},title:i,disabled:!r(e),children:t.jsx(s.Icon,{name:"edit"})},`${a}-edit`)},wt=({network:e,localPeering:a})=>{const n=[t.jsx(xt,{network:e,localPeering:a},"edit"),t.jsx(yt,{network:e,localPeering:a},"delete")];return t.jsx(s.List,{inline:!0,className:"u-no-margin--bottom actions-list",items:n})},vt=({network:e})=>{const a=M(),{project:n,localPeering:r}=a,i=s.useNotify(),c=s.useToastNotification(),d=F(),m=()=>{a.clear(),i.clear()},g=`${y}/ui/project/${encodeURIComponent(n??"")}/network/${encodeURIComponent(e.name)}`,{data:h,error:o,isLoading:b}=bt(e,n,r??""),p=()=>{c.success(t.jsxs(t.Fragment,{children:["Local peering"," ",t.jsx(X,{type:"peering",value:r??"",to:`${g}/local-peerings`})," ","updated."]})),m()},u=B({initialValues:{name:h?.name??"",description:h?.description,targetProject:h?.target_project??"",targetNetwork:h?.target_network??""},enableReinitialize:!0,onSubmit:l=>{const k={name:l.name,description:l.description,target_project:l.targetProject,target_network:l.targetNetwork};ht(e.name,r??"",n,k).then(()=>{d.invalidateQueries({queryKey:[f.projects,n,f.networks,e.name,f.peers]}),d.invalidateQueries({queryKey:[f.projects,n,f.networks,e.name,f.peers,r]}),p()}).catch(x=>{u.setSubmitting(!1),i.failure("Local peering update failed",x)})}});if(!h)return t.jsx(t.Fragment,{children:"Missing local peering"});if(o&&i.failure("Loading local peering failed",o),b)return t.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0});const N=u.values.description!==h?.description?1:0;return t.jsx(t.Fragment,{children:t.jsxs(s.SidePanel,{children:[t.jsx(s.SidePanel.Header,{children:t.jsxs(s.SidePanel.HeaderTitle,{className:"u-truncate",children:["Edit local peering ",r]})}),t.jsx(G,{className:"u-no-padding"}),t.jsx(s.SidePanel.Content,{className:"u-no-padding",children:t.jsx(s.ScrollableContainer,{dependencies:[i.notification],belowIds:["panel-footer"],children:t.jsx(je,{formik:u,network:e,isEditing:!0})})}),t.jsxs(s.SidePanel.Footer,{className:"u-align--right",children:[t.jsx(s.Button,{appearance:"base",onClick:m,className:"u-no-margin--bottom",children:"Cancel"}),t.jsx(s.ActionButton,{appearance:"positive",loading:u.isSubmitting,onClick:()=>{u.submitForm()},className:"u-no-margin--bottom",disabled:!u.isValid||u.isSubmitting||N===0,children:N===0?"Save changes":`Save ${N} ${Te("change",N)}`})]})]})})},_t=({localPeering:e})=>{const a=n=>({Pending:"status-waiting-small",Created:"status-succeeded-small",Errored:"status-failed-small"})[n]??"";return t.jsxs(t.Fragment,{children:[t.jsx(s.Icon,{name:a(e.status),className:"status-icon"}),e.status]})},Ct=({network:e})=>{const a=e.config["security.acls"];return(!a||a?.length==0)&&t.jsx(s.Notification,{severity:"caution",title:"No ACLs configured for this network.",children:"Local peerings have unrestricted ingress and egress on this network. To enforce filtering, add ACLs to the network configuration."})},kt=({network:e,project:a})=>{const{data:n}=ge(e,a),r=n?.config["security.acls"];return(!r||r?.length==0)&&t.jsx(s.Tooltip,{message:t.jsxs("div",{children:[t.jsx("div",{children:"Target network has unrestricted ingress and egress."}),t.jsx("div",{children:"To enforce filtering, add ACLs to the target network."})]}),children:t.jsx(s.Icon,{name:"warning"})})},Pt=({network:e,project:a})=>{const n=s.useNotify(),{data:r=[],error:i,isLoading:c}=Nt(e,a),d=M(),m=r.length>0;i&&n.failure("Loading local network peerings failed",i);const g=[{content:"Name",sortKey:"name"},{content:"Description",sortKey:"description"},{content:"Target project",sortKey:"targetProject"},{content:"Target network",sortKey:"targetNetwork"},{content:t.jsx("span",{className:"status-header",children:"Status"}),sortKey:"status"},{"aria-label":"Actions",className:"actions"}],h=r.map(o=>({key:o.name,columns:[{content:o.name,role:"rowheader","aria-label":"Name"},{content:o.description,role:"cell","aria-label":"Description"},{content:o.target_project?t.jsx(he,{projectName:o.target_project}):"-",role:"cell","aria-label":"Target project"},{content:o.target_network?t.jsxs(t.Fragment,{children:[t.jsx(T,{networkName:o.target_network,projectName:o.target_project??""}),t.jsx(kt,{network:o.target_network,project:o.target_project})]}):"-",role:"cell","aria-label":"Target network"},{content:t.jsx(_t,{localPeering:o}),role:"cell","aria-label":"Status"},{content:t.jsx(wt,{network:e,localPeering:o.name}),role:"cell","aria-label":"Actions",className:"u-align--right actions"}],sortData:{name:o.name?.toLowerCase(),description:o.description?.toLowerCase(),targetProject:o.target_project?.toLowerCase(),targetNetwork:o.target_network,status:o.status?.toLowerCase()}}));return c?t.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):t.jsxs(t.Fragment,{children:[t.jsx(Ct,{network:e}),m&&t.jsx(ie,{network:e,className:" u-float-right"}),t.jsxs(s.Row,{children:[m&&t.jsx(s.ScrollableTable,{dependencies:r,tableId:"network-peer-table",belowIds:["status-bar"],children:t.jsx(s.MainTable,{id:"network-peer-table",headers:g,expanding:!0,rows:h,responsive:!0,sortable:!0,className:"network-peer-list u-table-layout--auto"})}),!m&&t.jsxs(s.EmptyState,{className:"empty-state",image:t.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No local peerings found",children:[t.jsx("p",{children:"There are no local peerings in this network and project."}),t.jsx("p",{children:t.jsx(z,{docPath:"/howto/network_ovn_peers",children:"Learn more about local peering"})}),t.jsx(ie,{className:"empty-state-button",network:e})]})]}),d.panel===se.createLocalPeering&&t.jsx(ft,{network:e}),d.panel===se.editLocalPeering&&t.jsx(vt,{network:e})]})},ca=()=>{const e=s.useNotify(),{name:a,project:n,member:r,activeTab:i}=le();if(!a)return t.jsx(t.Fragment,{children:"Missing name"});if(!n)return t.jsx(t.Fragment,{children:"Missing project"});const{data:c,error:d,isLoading:m}=ge(a,n,r),g=E();if(_.useEffect(()=>{d&&e.failure("Loading network failed",d)},[d]),m)return t.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0});const h=c?.managed??!1,o=Ie.includes(c?.type??"")&&h,b=Re.includes(c?.type??"")&&h,p=me.includes(c?.type??""),u=`${y}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(a)}`,N=x=>K("p-tabs__link",{"is-disabled":x}),l=(x,P,V)=>{const U=S(x),v=P?`${u}/${V}`:"#";return{href:v,className:N(!P),title:P?x:`${x} are not supported on this network`,id:U,label:x,onClick:q=>{q.preventDefault(),e.clear(),g(v)},active:U===i}},k=["Configuration",l("Forwards",o,"forwards"),l("Leases",b,"leases"),l("Local peerings",p,"local-peerings")];return t.jsxs(s.CustomLayout,{header:t.jsx(ot,{network:c,project:n,name:a}),contentClassName:"edit-network",children:[!m&&!c&&t.jsx(Fe,{entityType:"network",entityName:a,errorMessage:d?.message}),!m&&c&&t.jsxs(s.Row,{children:[t.jsx(Ge,{tabs:k,activeTab:i,tabUrl:u}),t.jsx(G,{}),!i&&t.jsx("div",{role:"tabpanel","aria-labelledby":"configuration",children:c&&t.jsx(st,{network:c,project:n})}),i==="forwards"&&t.jsx("div",{role:"tabpanel","aria-labelledby":"forwards",children:c&&t.jsx(lt,{network:c,project:n})}),i==="leases"&&t.jsx("div",{role:"tabpanel","aria-labelledby":"leases",children:c&&t.jsx(ut,{network:c,project:n})}),i==="local-peerings"&&t.jsx("div",{role:"tabpanel","aria-labelledby":"local-peerings",children:c&&t.jsx(Pt,{network:c,project:n})})]})]})};export{ca as default};