| Current Path : /proc/thread-self/root/snap/lxd/current/share/lxd-ui/assets/ |
| Current File : //proc/thread-self/root/snap/lxd/current/share/lxd-ui/assets/NetworkDetail-Df8AN8_A.js |
import{u as Pe,B as le,c as V,d as s,a1 as ge,a5 as M,r as L,t as O,bo as ve,K as _,J as A,bp as Le,bq as Fe,f as te,h as D,a8 as $e,k as W,j as e,R as S,w as j,O as ne,s as z,y as U,I as he,L as je,S as we,a9 as Te,ae as G,M as ae,az as B,br as Ie,aI as Re,bs as fe,T as Ne,bt as Ee,p as se,v as Y,U as Me,bu as Ue,bv as _e,b3 as Ae}from"./index-BFGypnt-.js";import{g as be,a as Z,t as qe,N as De,i as Oe}from"./NetworkForm-VVshF-VF.js";import{b as Be,e as Ke,g as Ve,d as Qe,r as He,h as Ye,u as xe}from"./useNetworks-B1lu5MbM.js";import{y as We,o as ze,d as Ge}from"./YamlSwitch-BQqYYI1i.js";import{C as Je,G as ee,Y as H}from"./NetworkFormMenu-CXUwfE9b.js";import{F as Xe}from"./FormFooterLayout-CMGxv4XX.js";import{F as Ze}from"./FormSubmitBtn-NpEQWJ3F.js";import{s as et}from"./scroll-Dc7Cgzms.js";import{u as tt}from"./useClusterMembers-B29_ixY7.js";import{N as $}from"./NetworkRichChip-D2iomVd3.js";import{R as nt}from"./RenameHeader-yxEpJNaX.js";import{a as re}from"./ClusterMemberRichChip-h3WaiYeI.js";import{T as at}from"./TabLinks-BlmDr2on.js";import{d as st,a as rt}from"./network-forwards-Cv12zUSO.js";import{E as ot}from"./ExpandableList-DK5_MQFC.js";import{u as K,p as de}from"./usePanelParams-CV5ZHNeu.js";import{I as it}from"./InstanceIpEdit-Dpgjq_FU.js";import{P as ye}from"./ProjectRichChip-CtiU36yR.js";import{A as ct}from"./AutoExpandingTextArea-WEdimI5c.js";import{N as lt}from"./NetworkSelector-BaEsMhep.js";import"./FormMenuItem-fhYfVpHc.js";import"./ClusterSpecificSelect-aZ9P5CkH.js";import"./ClusterSpecificInput-BYM6R5do.js";import"./UsedByItem-DETYWHDN.js";import"./useImages-DavKpFTt.js";import"./images-C6WqBeZG.js";import"./image-registries-YAuyq4CZ.js";import"./ProfileRichChip-XiLIeCE5.js";import"./ProfileResourceLimits-DkY60ueM.js";import"./useProfiles-CErbukD2.js";import"./ConfigurationTable-CmO6jSmV.js";import"./ConfigFieldDescription-CY0sdTp6.js";import"./useStoragePools-qBtKr1j9.js";import"./NetworkDefaultACLSelector-C5Ak_9zq.js";import"./useNetworkAcls-DNeSgtR0.js";import"./network-acls-DPo6Eh5Y.js";import"./formChangeCount-Dw7v2KcL.js";import"./cluster-members-CG6XHzn4.js";import"./ClusterMemberMemoryUsage-UO8J-hw2.js";import"./Meter-VGEmUMfL.js";const I=()=>{const{isFineGrained:t}=Pe();return{canDeleteNetwork:r=>le(t,"can_delete",r?.access_entitlements),canEditNetwork:r=>le(t,"can_edit",r?.access_entitlements)}},dt=({network:t,project:n})=>{const a=V(),r=s.useNotify(),o=s.useToastNotification(),{hash:l}=ge(),m=l?l.substring(1):M(Je),[d,g]=L.useState(m),f=O(),c=L.useState(null),[x,p]=L.useState(0),{data:u=[]}=tt(),{canEditNetwork:y}=I(),w=t.managed&&ve.includes(t.type),{data:k=[],error:N}=Be(t.name,n,w),{hasStorageAndNetworkOperations:h}=_(),i=A();L.useEffect(()=>{N&&r.failure("Loading network from cluster members failed",N)},[N]);const b=k.filter(Le);L.useEffect(()=>{Fe(k,r)},[k]);const C=te().shape({name:be(n,c,t.name),network:D().test("required","Uplink network is required",(P,q)=>q.parent.networkType!==$e||!!P)}),v=y(t)?void 0:"You do not have permission to edit this network",F=()=>{f.invalidateQueries({queryKey:[j.projects,n,j.networks,t.name]}),f.invalidateQueries({queryKey:[j.projects,n,j.networks,t.name,j.cluster]})},R=P=>{T.resetForm({values:Z(P,b)}),F(),o.success(e.jsxs(e.Fragment,{children:["Network","",e.jsx($,{networkName:t.name,projectName:n})," ","updated."]}))},Q=P=>{F(),r.failure(`Update of network ${t.name} failed`,P)},T=W({initialValues:Z(t,b,v),validationSchema:C,enableReinitialize:!0,onSubmit:P=>{const q=P.yaml?P.yaml:oe(),X=We(q),ce={...X,etag:t.etag};(async E=>E.parentPerClusterMember&&Object.keys(E.parentPerClusterMember).length>0?Ke(ce,n,u,E.parentPerClusterMember,h,E.bridge_external_interfaces_per_member,t.config):Ve(ce,n))(P).then(E=>{h&&E.metadata.id?(o.info(e.jsxs(e.Fragment,{children:["Update of network"," ",e.jsx($,{networkName:t.name,projectName:n})," ","has started."]})),i.set(E.metadata.id,()=>{R(X)},Se=>{Q(new Error(Se))})):R(X)}).catch(E=>{Q(E)}).finally(()=>{T.setSubmitting(!1)})}}),oe=()=>{const P=qe(T.values);return ze(P)};L.useEffect(()=>{et(m),g(m)},[m]);const J=`${S}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(t.name)}`,ie=(P,q)=>{q==="scroll"&&d===M(H)||(q==="click"&&a(P===ee?J:`${J}/#${M(P)}`),g(M(P)))},Ce=T.values.readOnly;return e.jsxs(e.Fragment,{children:[e.jsx(De,{formik:T,getYaml:oe,project:n,section:d??M(ee),setSection:ie,version:x},t.name),e.jsxs(Xe,{children:[e.jsx(Ge,{formik:T,section:d,setSection:()=>{ie(d===M(H)?ee:H,"click")},disableReason:T.values.name?void 0:"Please enter a network name to enable this section"}),Ce?null:e.jsxs(e.Fragment,{children:[e.jsx(s.Button,{appearance:"base",onClick:()=>{p(P=>P+1),T.setValues(Z(t,b))},children:"Cancel"}),e.jsx(Ze,{formik:T,baseUrl:J,isYaml:d===M(H),disabled:Oe(T,u)})]})]})]})},ut=({network:t,project:n})=>{const a=s.useNotify(),r=s.useToastNotification(),o=O(),[l,m]=L.useState(!1),d=V(),g=ge(),f=ne(),{canDeleteNetwork:c}=I(),{hasStorageAndNetworkOperations:x}=_(),p=A(),u=()=>{o.invalidateQueries({predicate:b=>b.queryKey[0]===j.projects&&b.queryKey[1]===n&&b.queryKey[2]===j.networks})},y=()=>{u();const b=`${S}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(t.name)}`;g.pathname.startsWith(b)&&d(`${S}/ui/project/${encodeURIComponent(n)}/networks`),m(!1),r.success(e.jsxs(e.Fragment,{children:["Network ",e.jsx(U,{bold:!0,type:"network",value:t.name})," ","deleted."]}))},w=b=>{u(),m(!1),a.failure(`Deleting network ${t.name} failed`,b)},k=()=>{m(!0),Qe(t.name,n).then(b=>{x?(r.info(e.jsxs(e.Fragment,{children:["Deletion of network"," ",e.jsx($,{networkName:t.name,projectName:n})," ","has started."]})),p.set(b.metadata.id,()=>{y()},C=>{w(new Error(C))})):y()}).catch(b=>{w(b)})},N=(t.used_by?.length??0)>0,h=t.managed,i=()=>c(t)?h?N?"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 e.jsxs(s.ConfirmationButton,{onHoverText:i(),confirmationModalProps:{title:"Confirm delete",confirmButtonAppearance:"negative",confirmButtonLabel:"Delete",children:e.jsxs("p",{children:["Are you sure you want to delete the network"," ",e.jsx($,{networkName:t.name,projectName:n}),"?",e.jsx("br",{}),"This action cannot be undone, and can result in data loss."]}),onConfirm:k},className:z("u-no-margin--bottom",{"has-icon":!f}),loading:l,disabled:!c(t)||N||!h||l,shiftClickEnabled:!0,showShiftClickHint:!0,children:[!f&&e.jsx(s.Icon,{name:"delete"}),e.jsx("span",{children:"Delete network"})]})},mt=({name:t,network:n,project:a})=>{const{member:r}=he(),o=V(),l=s.useNotify(),m=s.useToastNotification(),d=L.useState(null),{canEditNetwork:g}=I(),{hasStorageAndNetworkOperations:f}=_(),c=A(),x=te().shape({name:be(a,d,n?.name)}),p=h=>{const i=`${S}/ui/project/${encodeURIComponent(a)}/network/${encodeURIComponent(h)}`;o(i),m.success(e.jsxs(e.Fragment,{children:["Network ",e.jsx("strong",{children:t})," renamed to"," ",e.jsx($,{networkName:h,projectName:a})]})),y.setFieldValue("isRenaming",!1)},u=(h,i)=>{l.failure(`Renaming of network ${h} failed`,i)},y=W({initialValues:{name:t,isRenaming:!1},validationSchema:x,onSubmit:h=>{if(t===h.name){y.setFieldValue("isRenaming",!1),y.setSubmitting(!1);return}He(t,h.name,a).then(i=>{f?(m.info(e.jsxs(e.Fragment,{children:["Renaming of network"," ",e.jsx($,{networkName:h.name,projectName:a})," ","has started."]})),c.set(i.metadata.id,()=>{p(h.name)},b=>{u(h.name,new Error(b))})):p(h.name)}).catch(i=>{u(h.name,i)}).finally(()=>{y.setSubmitting(!1)})}}),w=(n?.used_by?.length??0)>0,k=n?.managed,N=()=>{if(!g(n))return"You do not have permission to rename this network";if(!k)return"Can not rename, network is not managed";if(w)return"Can not rename, network is currently in use."};return e.jsx(nt,{name:t,relatedChip:r&&e.jsx(re,{clusterMember:r}),parentItems:[e.jsx(je,{to:`${S}/ui/project/${encodeURIComponent(a)}/networks`,children:"Networks"},1)],renameDisabledReason:N(),controls:n&&e.jsx(ut,{network:n,project:a}),isLoaded:!!n,formik:y})},pt=({network:t,forward:n,project:a})=>{const r=s.useNotify(),o=s.useToastNotification(),l=O(),[m,d]=L.useState(!1),{canEditNetwork:g}=I(),{hasStorageAndNetworkOperations:f}=_(),c=A(),x=()=>{l.invalidateQueries({predicate:w=>w.queryKey[0]===j.projects&&w.queryKey[1]===a&&w.queryKey[2]===j.networks&&w.queryKey[3]===t.name})},p=()=>{x(),o.success(e.jsxs(e.Fragment,{children:["Network forward with listen address"," ",e.jsx(U,{type:"network-forward",value:n.listen_address,bold:!0})," ","deleted."]}))},u=w=>{x(),d(!1),r.failure(`Deletion of network forward with listen address ${n.listen_address} failed`,w)},y=()=>{d(!0),st(t,n,a).then(w=>{f?(o.info(e.jsxs(e.Fragment,{children:["Deletion of network forward with listen address"," ",e.jsx(U,{bold:!0,type:"network-forward",value:n.listen_address})," ","has started."]})),c.set(w.metadata.id,()=>{p()},k=>{u(new Error(k))})):p()}).catch(w=>{u(w)})};return e.jsx(s.ConfirmationButton,{appearance:"base",onHoverText:g(t)?"Delete network forward":"You do not have permission to delete this network forward",confirmationModalProps:{title:"Confirm delete",confirmButtonAppearance:"negative",confirmButtonLabel:"Delete",children:e.jsxs("p",{children:["Are you sure you want to delete the network forward with listen address"," ",e.jsx(U,{type:"network-forward",value:n.listen_address,bold:!0}),"?",e.jsx("br",{})]}),onConfirm:y},className:"u-no-margin--bottom has-icon",loading:m,shiftClickEnabled:!0,showShiftClickHint:!0,disabled:!g(t)||m,children:e.jsx(s.Icon,{name:"delete"})})},gt=({port:t})=>{const n=t.target_port&&t.target_port.length>0?t.target_port:t.listen_port,r=`:${t.listen_port} → ${t.target_address}:${n} (${t.protocol})`;return e.jsx("div",{className:"u-truncate",title:r,children:r})},ue=({network:t,className:n})=>{const a=ne(),{canEditNetwork:r}=I(),o=K(),l=V();return e.jsxs(s.Button,{appearance:"positive",hasIcon:!a,onClick:()=>{l(`${S}/ui/project/${encodeURIComponent(o.project)}/network/${encodeURIComponent(t.name)}/forwards/create`)},className:z("p-button--positive u-no-margin--bottom",n),disabled:!r(t),title:r(t)?"Create forward":"You do not have permission to create network forwards for this network",children:[!a&&e.jsx(s.Icon,{name:"plus",light:!0}),e.jsx("span",{children:"Create forward"})]})},ht=({network:t,project:n})=>{const a=s.useNotify(),{canEditNetwork:r}=I(),l=we()&&t?.type===Te,{data:m=[],error:d,isLoading:g}=G({queryKey:[j.projects,n,j.networks,t.name,j.forwards],queryFn:async()=>rt(t.name,n)});d&&a.failure("Loading network forwards failed",d);const f=m.length>0,c=[{content:"Listen address",sortKey:"listenAddress"},{content:"Description",sortKey:"description"},{content:"Default target address",sortKey:"defaultTarget"},{content:"Ports"},...l?[{content:"Location",sortKey:"location"}]:[],{"aria-label":"Actions",className:"u-align--right actions"}],x=m.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:e.jsx(ot,{items:p.ports.map(u=>e.jsx(gt,{port:u},u.listen_port))}),role:"cell","aria-label":"Forwarded ports"},...l?[{content:e.jsx(re,{clusterMember:p.location??""}),role:"cell"}]:[],{content:e.jsxs(e.Fragment,{children:[r(t)&&e.jsx(je,{className:"p-button--base u-no-margin--bottom has-icon",to:l?`${S}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(t.name)}/member/${encodeURIComponent(p.location??"")}/forwards/${encodeURIComponent(p.listen_address)}/edit`:`${S}/ui/project/${encodeURIComponent(n)}/network/${encodeURIComponent(t.name)}/forwards/${encodeURIComponent(p.listen_address)}/edit`,title:"Edit network forward",children:e.jsx(s.Icon,{name:"edit"})}),!r(t)&&e.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:e.jsx(s.Icon,{name:"edit"})},"edit"),e.jsx(pt,{network:t,forward:p,project:n},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?e.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):e.jsxs(e.Fragment,{children:[f&&e.jsx(ue,{network:t,className:"u-float-right"}),e.jsxs(s.Row,{children:[f&&e.jsx(s.ScrollableTable,{dependencies:m,tableId:"network-forwards-table",belowIds:["status-bar"],children:e.jsx(s.MainTable,{id:"network-forwards-table",headers:c,expanding:!0,rows:x,paginate:30,sortable:!0,defaultSort:"listenAddress",defaultSortDirection:"ascending",className:"u-table-layout--auto network-forwards-table",emptyStateMsg:"No data to display"})}),!g&&!f&&e.jsxs(s.EmptyState,{className:"empty-state",image:e.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No network forwards found",children:[e.jsx("p",{children:"There are no network forwards in this project."}),e.jsx("p",{children:e.jsx(ae,{docPath:"/howto/network_forwards/",hasExternalIcon:!0,children:"Learn more about network forwards"})}),!f&&e.jsx(ue,{network:t,className:"empty-state-button"})]})]})]})},jt=async(t,n)=>{const a=new URLSearchParams;return a.set("project",n),a.set("recursion","1"),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/leases?${a.toString()}`).then(B).then(r=>r.metadata)},wt=({network:t,project:n})=>{const a=s.useNotify(),r=we(),{data:o=[],error:l,isLoading:m}=G({queryKey:[j.projects,n,j.networks,t.name,j.leases],queryFn:async()=>jt(t.name,n)});l&&a.failure("Loading network leases failed",l);const d=o.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"}],f=o.map(c=>({key:c.address+c.hostname+c.type,columns:[{content:c.type,role:"cell","aria-label":"Type",className:"type"},{content:c.hostname,role:"rowheader","aria-label":"Hostname",className:"hostname"},{content:c.project&&e.jsx(ye,{projectName:c.project}),role:"cell","aria-label":"project",className:"project"},...r?[{content:c.location&&e.jsx(re,{clusterMember:c.location}),role:"cell","aria-label":"Cluster member",className:"clusterMember"}]:[],{content:c.hwaddr,role:"cell","aria-label":"MAC address",className:"macAddress"},{content:Ie.includes(t.type)&&["static","dynamic"].includes(c.type)?e.jsx(it,{address:c.address,instanceName:c.hostname,projectName:c.project}):e.jsx(e.Fragment,{children:c.address}),role:"cell","aria-label":"IP address",className:"ipAddress"}],sortData:{hostname:c.hostname.toLowerCase(),macAddress:c.hwaddr,type:c.type,project:c.project?.toLowerCase(),clusterMember:c.location?.toLowerCase(),address:c.address}}));return m?e.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):e.jsxs(s.Row,{children:[d&&e.jsx(s.ScrollableTable,{dependencies:o,tableId:"network-lease-table",belowIds:["status-bar"],children:e.jsx(s.MainTable,{id:"network-lease-table",headers:g,expanding:!0,rows:f,responsive:!0,sortable:!0,defaultSort:"address",defaultSortDirection:"ascending",className:"network-leases-table",emptyStateMsg:"No data to display"})}),!m&&!d&&e.jsxs(s.EmptyState,{className:"empty-state",image:e.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No network leases found",children:[e.jsx("p",{children:"There are no network leases in this project."}),e.jsx("p",{children:e.jsx(ae,{docPath:"/howto/network_ipam/#view-dhcp-leases-for-fully-controlled-networks",hasExternalIcon:!0,children:"Learn more about network leases"})})]})]})},ft=async(t,n)=>{const a=new URLSearchParams;return a.set("project",n),a.set("recursion","1"),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/peers?${a.toString()}`).then(B).then(r=>(r.metadata.sort((o,l)=>o.name.localeCompare(l.name)),r.metadata))},Nt=async(t,n,a)=>{const r=new URLSearchParams;return r.set("project",n),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/peers/${encodeURIComponent(a)}?${r.toString()}`).then(B).then(o=>o.metadata)},me=async(t,n,a)=>{const r=new URLSearchParams;return r.set("project",n),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/peers?${r.toString()}`,{method:"POST",headers:{"Content-Type":"application/json"},body:a}).then(B).then(o=>o)},bt=async(t,n,a)=>{const r=new URLSearchParams;return r.set("project",n),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/peers/${encodeURIComponent(a)}?${r.toString()}`,{method:"DELETE"}).then(B).then(o=>o)},xt=async(t,n,a,r)=>{const o=new URLSearchParams;return o.set("project",a),fetch(`${S}/1.0/networks/${encodeURIComponent(t)}/peers/${encodeURIComponent(n)}?${o.toString()}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}).then(B).then(l=>l)},yt=({value:t,setValue:n,projects:a,hasNoneOption:r=!1,...o})=>{const l=()=>{const d=a.map(g=>({label:e.jsx("div",{className:"label",children:e.jsx("span",{title:g.name,className:"project-option u-truncate",children:g.name})}),value:g.name,text:g.name,disabled:!1}));return d.length===0&&d.unshift({label:e.jsx("span",{children:"No projects available"}),value:"",text:"None",disabled:!0}),r&&d.push({label:e.jsx("div",{className:"label",children:e.jsx("span",{title:"No project",className:"project-option u-truncate",children:"No project"})}),value:"none",text:"No project",disabled:!1}),d},m=()=>e.jsx("div",{className:"header",children:e.jsx("span",{className:"project-option u-no-margin--bottom",children:"Name"})});return e.jsx(s.CustomSelect,{label:"Project",...o,onChange:d=>{n(d)},value:t,options:l(),header:m(),dropdownClassName:"project-select-dropdown","aria-label":"Project"})},ke=({formik:t,network:n,isEditing:a})=>{const r="Manually enter project",o="Manually enter network",{canEditNetwork:l}=I(),{data:m=[]}=Re(),{data:d=[]}=Ye(t.values.targetProject||"default",void 0,t.values.targetProject===r?!1:void 0),g=[...m,{name:r,config:{},description:""}],c=[...d.filter(u=>fe.includes(u.type)).filter(u=>u.name!==n.name),{name:o,type:"ovn",config:{}}],x=u=>({id:u,name:u,onBlur:t.handleBlur,onChange:t.handleChange,value:t.values[u]??"",error:t.touched[u]?t.errors[u]:null,placeholder:`Enter ${u.replaceAll("-"," ")}`}),p=l(n)?"":"You do not have permission to edit this network";return e.jsxs(s.Form,{onSubmit:t.handleSubmit,className:"local-peering-create-form",children:[e.jsx(s.Input,{type:"submit",hidden:!0,value:"Hidden input"}),e.jsx(s.Input,{...x("name"),type:"text",label:"Name",required:!0,autoFocus:!a,disabled:a||!!p,title:"Name cannot be changed"}),e.jsx(ct,{...x("description"),label:"Description",disabled:!!p,title:p,autoFocus:a}),a?e.jsx(s.Input,{id:"targetProject",type:"text",label:"Target project",value:t.values.targetProject,title:"Target project cannot be changed",required:!0,disabled:!0}):e.jsx(yt,{id:"targetProject",name:"targetProject",label:"Target project",value:t.values.targetProject,setValue:u=>{t.setFieldValue("targetProject",u,!1),t.setFieldValue("customTargetProject","",!1),u===r?t.setFieldValue("targetNetwork",o,!1):t.setFieldValue("targetNetwork","",!1),t.setFieldValue("customTargetNetwork","",!1),t.setFieldValue("createMutualPeering",!1,!1),setTimeout(()=>{t.validateForm()},100)},disabled:!!p,projects:g,required:!0}),t.values.targetProject===r&&e.jsx(s.Input,{id:"customTargetProject",name:"customTargetProject",type:"text",placeholder:"Enter target project name",value:t.values.customTargetProject,onChange:t.handleChange,onBlur:t.handleBlur}),a?e.jsx(s.Input,{id:"targetNetwork",type:"text",label:"Target network",value:t.values.targetNetwork,title:"Target network cannot be changed",required:!0,disabled:!0}):t.values.targetProject&&t.values.targetProject!==r&&e.jsx(lt,{id:"targetNetwork",name:"targetNetwork",label:"Target network",value:t.values.targetNetwork,setValue:u=>{t.setFieldValue("targetNetwork",u,!1),u===o?t.setFieldValue("createMutualPeering",!1,!0):(t.setFieldValue("customTargetNetwork","",!1),t.setFieldValue("createMutualPeering",!0,!1)),setTimeout(()=>{t.validateForm()},100)},networkList:c,help:t.values.targetNetwork!==o&&"Peering is limited to intra-cluster OVN networks; non-OVN or cross-cluster network peering is not supported.",required:!0}),(t.values.targetNetwork===o||t.values.targetProject===r)&&e.jsx(s.Input,{id:"customTargetNetwork",name:"customTargetNetwork",type:"text",label:(t.values.targetNetwork!==o||t.values.targetProject===r)&&"Target network",placeholder:"Enter target network name",value:t.values.customTargetNetwork,onChange:t.handleChange,onBlur:t.handleBlur,help:"Peering is limited to intra-cluster OVN networks; non-OVN or cross-cluster network peering is not supported.",required:!0}),!a&&e.jsx(s.Input,{id:"createMutualPeering",name:"createMutualPeering",type:"checkbox",label:"Create mutual peering",checked:t.values.createMutualPeering,onChange:u=>{t.setFieldValue("createMutualPeering",u.target.checked)},disabled:t.values.targetNetwork===o||t.values.targetProject===r,title:t.values.targetNetwork===o||t.values.targetProject===r?"Unavailable when using manual network or project entry":""})]})},kt=({network:t})=>{const n=K(),{project:a}=Ne(),r=s.useNotify(),o=s.useToastNotification(),l=O(),m=L.useState(null),{hasStorageAndNetworkOperations:d}=_(),g=A(),f=()=>{n.clear(),r.clear()},c=`${S}/ui/project/${encodeURIComponent(a?.name??"")}/network/${encodeURIComponent(t.name)}`,x="Manually enter project",p="Manually enter network",u=te().shape({targetProject:D().required("Target project is required"),customTargetProject:D().nullable().when("targetProject",{is:i=>i===x,then:i=>i.required("Please enter a project name"),otherwise:i=>i.notRequired()}),targetNetwork:D().when("targetProject",{is:i=>i!==x,then:i=>i.required("Target network is required"),otherwise:i=>i.notRequired()}),customTargetNetwork:D().nullable().when("targetNetwork",{is:i=>i===p,then:i=>i.required("Please enter a network name"),otherwise:i=>i.notRequired()}),name:D().test(...Ee(n.project,t.name,m)).required("Local peering name is required")}),y=()=>{l.invalidateQueries({queryKey:[j.projects,n.project,j.networks,t.name,j.peers]})},w=i=>{y(),o.success(e.jsxs(e.Fragment,{children:["Local peering"," ",e.jsx(Y,{type:"peering",value:i,to:`${c}/local-peerings`})," ","created for network"," ",e.jsx($,{networkName:t.name,projectName:a?.name||"default"})]})),f()},k=(i,b,C)=>{y(),h.setSubmitting(!1),r.failure(`Creation of ${i?"local":"mutual"} peering ${b} for network ${t.name} failed`,C)},N=(i,b,C,v)=>{me(i,b,JSON.stringify(C)).then(F=>{d?g.set(F.metadata.id,()=>{w(v)},R=>{k(!1,v,new Error(R))}):w(v)}).catch(F=>{k(!1,v,F)})},h=W({initialValues:{name:"",description:"",targetProject:a?.name||"",targetNetwork:"",customTargetNetwork:"",customTargetProject:"",createMutualPeering:!1},validationSchema:u,validateOnMount:!0,validateOnChange:!0,validateOnBlur:!0,onSubmit:i=>{const b=i.targetProject===x?i.customTargetProject||"":i.targetProject,C=i.targetNetwork===p?i.customTargetNetwork||"":i.targetNetwork,v={name:i.name,description:i.description,target_project:b,target_network:C};me(t.name,n.project,JSON.stringify(v)).then(F=>{if(h.values.createMutualPeering){const R={name:i.name,description:i.description,target_project:n.project,target_network:t.name};d?(o.info(e.jsxs(e.Fragment,{children:["Creation of mutual peering"," ",e.jsx(U,{bold:!0,type:"peering",value:i.name})," has started."]})),g.set(F.metadata.id,()=>{N(C,b,R,i.name)},Q=>{k(!0,i.name,new Error(Q))})):N(C,b,R,i.name)}else d?(o.info(e.jsxs(e.Fragment,{children:["Creation of local peering"," ",e.jsx(U,{bold:!0,type:"peering",value:i.name})," has started."]})),g.set(F.metadata.id,()=>{w(i.name)},R=>{k(!0,i.name,new Error(R))})):w(i.name)}).catch(F=>{k(!0,i.name,F)})}});return e.jsx(e.Fragment,{children:e.jsxs(s.SidePanel,{children:[e.jsx(s.SidePanel.Header,{children:e.jsx(s.SidePanel.HeaderTitle,{children:"Create local peering"})}),e.jsx(se,{className:"u-no-padding"}),e.jsx(s.SidePanel.Content,{className:"u-no-padding",children:e.jsx(s.ScrollableContainer,{dependencies:[r.notification],belowIds:["panel-footer"],children:e.jsx(ke,{formik:h,network:t})})}),e.jsxs(s.SidePanel.Footer,{className:"u-align--right",children:[e.jsx(s.Button,{appearance:"base",onClick:f,className:"u-no-margin--bottom",children:"Cancel"}),e.jsx(s.ActionButton,{appearance:"positive",loading:h.isSubmitting,onClick:()=>{h.submitForm()},className:"u-no-margin--bottom",disabled:!h.isValid||h.isSubmitting||!h.values.name,children:"Create local peering"})]})]})})},Ct=(t,n)=>G({queryKey:[j.projects,n,j.networks,t.name,j.peers],queryFn:async()=>ft(t.name,n)}),St=(t,n,a)=>G({queryKey:[j.projects,n,j.networks,t.name,j.peers,a],queryFn:async()=>Nt(t.name,n,a)}),pe=({network:t,className:n})=>{const a=ne(),{canEditNetwork:r}=I(),o=K();return e.jsxs(s.Button,{appearance:"positive",hasIcon:!a,onClick:()=>{o.openCreateLocalPeering()},className:z("p-button--positive",n),disabled:!r(t),title:r(t)?"Create local peering":"You do not have permission to create local peerings for this network",children:[!a&&e.jsx(s.Icon,{name:"plus",light:!0}),e.jsx("span",{children:"Create local peering"})]})},Pt=({network:t,localPeering:n})=>{const a=s.useNotify(),[r,o]=L.useState(!1),l=O(),{canEditNetwork:m}=I(),{project:d}=Ne(),g=d?.name||"",f=s.useToastNotification(),{hasStorageAndNetworkOperations:c}=_(),x=A(),p=`${S}/ui/project/${encodeURIComponent(g)}/network/${encodeURIComponent(t.name)}`,u=()=>{l.invalidateQueries({queryKey:[j.projects,g,j.networks,t.name,j.peers]})},y=()=>{u(),o(!1),f.success(e.jsxs(e.Fragment,{children:["Local peering ",e.jsx(U,{type:"peering",value:n,bold:!0})," ","deleted for network"," ",e.jsx($,{networkName:t.name,projectName:g})]}))},w=N=>{a.failure(`Deletion of local peering ${n} for network ${t.name} failed`,N),o(!1),u()},k=()=>{o(!0),bt(t.name,g,n).then(N=>{c?(f.info(e.jsxs(e.Fragment,{children:["Deletion of local peering"," ",e.jsx(U,{type:"peering",value:n,bold:!0})," for network"," ",e.jsx($,{networkName:t.name,projectName:g})," ","has started."]})),x.set(N.metadata.id,()=>{y()},h=>{w(new Error(h))})):y()}).catch(w)};return e.jsx(s.ConfirmationButton,{loading:r,confirmationModalProps:{title:"Confirm delete",children:e.jsxs("p",{children:["This will permanently delete the local peering"," ",e.jsx(Y,{type:"peering",value:n,to:`${p}/local-peerings`})," ","for network"," ",e.jsx($,{networkName:t.name,projectName:g}),".",e.jsx("br",{})]}),confirmButtonLabel:"Delete",onConfirm:k},appearance:"base",className:"has-icon",shiftClickEnabled:!0,showShiftClickHint:!0,disabled:!m(t),onHoverText:m(t)?"Delete local peering":"You do not have permission to delete this local peering.",children:e.jsx(s.Icon,{name:"delete"})})},vt=({network:t,localPeering:n})=>{const a=K(),{canEditNetwork:r}=I(),o=r(t)?"Edit local peering":"You do not have permission to edit this local peering";return e.jsx(s.Button,{appearance:"base",hasIcon:!0,onClick:()=>{a.openEditLocalPeering(n)},title:o,disabled:!r(t),children:e.jsx(s.Icon,{name:"edit"})},`${n}-edit`)},Lt=({network:t,localPeering:n})=>{const a=[e.jsx(vt,{network:t,localPeering:n},"edit"),e.jsx(Pt,{network:t,localPeering:n},"delete")];return e.jsx(s.List,{inline:!0,className:"u-no-margin--bottom actions-list",items:a})},Ft=({network:t})=>{const n=K(),{project:a,localPeering:r}=n,o=s.useNotify(),l=s.useToastNotification(),m=O(),{hasStorageAndNetworkOperations:d}=_(),g=A(),f=()=>{n.clear(),o.clear()},c=`${S}/ui/project/${encodeURIComponent(a??"")}/network/${encodeURIComponent(t.name)}`,{data:x,error:p,isLoading:u}=St(t,a,r??""),y=()=>{m.invalidateQueries({queryKey:[j.projects,a,j.networks,t.name,j.peers]}),m.invalidateQueries({queryKey:[j.projects,a,j.networks,t.name,j.peers,r]})},w=()=>{y(),l.success(e.jsxs(e.Fragment,{children:["Local peering"," ",e.jsx(Y,{type:"peering",value:r??"",to:`${c}/local-peerings`})," ","updated."]})),f()},k=i=>{y(),N.setSubmitting(!1),o.failure(`Update of local peering ${r} failed`,i)},N=W({initialValues:{name:x?.name??"",description:x?.description,targetProject:x?.target_project??"",targetNetwork:x?.target_network??""},enableReinitialize:!0,onSubmit:i=>{const b={name:i.name,description:i.description,target_project:i.targetProject,target_network:i.targetNetwork};xt(t.name,r??"",a,b).then(C=>{d?(l.info(e.jsxs(e.Fragment,{children:["Update of local peering"," ",e.jsx(Y,{type:"peering",value:r??"",to:`${c}/local-peerings`})," ","has started."]})),g.set(C.metadata.id,()=>{w()},v=>{k(new Error(v))})):w()}).catch(C=>{k(C)})}});if(!x)return e.jsx(e.Fragment,{children:"Missing local peering"});if(p&&o.failure("Loading local peering failed",p),u)return e.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0});const h=N.values.description!==x?.description?1:0;return e.jsx(e.Fragment,{children:e.jsxs(s.SidePanel,{children:[e.jsx(s.SidePanel.Header,{children:e.jsxs(s.SidePanel.HeaderTitle,{className:"u-truncate",children:["Edit local peering ",r]})}),e.jsx(se,{className:"u-no-padding"}),e.jsx(s.SidePanel.Content,{className:"u-no-padding",children:e.jsx(s.ScrollableContainer,{dependencies:[o.notification],belowIds:["panel-footer"],children:e.jsx(ke,{formik:N,network:t,isEditing:!0})})}),e.jsxs(s.SidePanel.Footer,{className:"u-align--right",children:[e.jsx(s.Button,{appearance:"base",onClick:f,className:"u-no-margin--bottom",children:"Cancel"}),e.jsx(s.ActionButton,{appearance:"positive",loading:N.isSubmitting,onClick:()=>{N.submitForm()},className:"u-no-margin--bottom",disabled:!N.isValid||N.isSubmitting||h===0,children:h===0?"Save changes":`Save ${h} ${Me("change",h)}`})]})]})})},$t=({localPeering:t})=>{const n=a=>({Pending:"status-waiting-small",Created:"status-succeeded-small",Errored:"status-failed-small"})[a]??"";return e.jsxs(e.Fragment,{children:[e.jsx(s.Icon,{name:n(t.status),className:"status-icon"}),t.status]})},Tt=({network:t})=>{const n=t.config["security.acls"];return(!n||n?.length==0)&&e.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."})},It=({network:t,project:n})=>{const{data:a}=xe(t,n),r=a?.config["security.acls"];return(!r||r?.length==0)&&e.jsx(s.Tooltip,{message:e.jsxs("div",{children:[e.jsx("div",{children:"Target network has unrestricted ingress and egress."}),e.jsx("div",{children:"To enforce filtering, add ACLs to the target network."})]}),children:e.jsx(s.Icon,{name:"warning"})})},Rt=({network:t,project:n})=>{const a=s.useNotify(),{data:r=[],error:o,isLoading:l}=Ct(t,n),m=K(),d=r.length>0;o&&a.failure("Loading local network peerings failed",o);const g=[{content:"Name",sortKey:"name"},{content:"Description",sortKey:"description"},{content:"Target project",sortKey:"targetProject"},{content:"Target network",sortKey:"targetNetwork"},{content:e.jsx("span",{className:"status-header",children:"Status"}),sortKey:"status"},{"aria-label":"Actions",className:"actions"}],f=r.map(c=>({key:c.name,columns:[{content:c.name,role:"rowheader","aria-label":"Name"},{content:c.description,role:"cell","aria-label":"Description"},{content:c.target_project?e.jsx(ye,{projectName:c.target_project}):"-",role:"cell","aria-label":"Target project"},{content:c.target_network?e.jsxs(e.Fragment,{children:[e.jsx($,{networkName:c.target_network,projectName:c.target_project??""}),e.jsx(It,{network:c.target_network,project:c.target_project})]}):"-",role:"cell","aria-label":"Target network"},{content:e.jsx($t,{localPeering:c}),role:"cell","aria-label":"Status"},{content:e.jsx(Lt,{network:t,localPeering:c.name}),role:"cell","aria-label":"Actions",className:"u-align--right actions"}],sortData:{name:c.name?.toLowerCase(),description:c.description?.toLowerCase(),targetProject:c.target_project?.toLowerCase(),targetNetwork:c.target_network,status:c.status?.toLowerCase()}}));return l?e.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0}):e.jsxs(e.Fragment,{children:[e.jsx(Tt,{network:t}),d&&e.jsx(pe,{network:t,className:" u-float-right"}),e.jsxs(s.Row,{children:[d&&e.jsx(s.ScrollableTable,{dependencies:r,tableId:"network-peer-table",belowIds:["status-bar"],children:e.jsx(s.MainTable,{id:"network-peer-table",headers:g,expanding:!0,rows:f,responsive:!0,sortable:!0,className:"network-peer-list u-table-layout--auto"})}),!d&&e.jsxs(s.EmptyState,{className:"empty-state",image:e.jsx(s.Icon,{className:"empty-state-icon",name:"exposed"}),title:"No local peerings found",children:[e.jsx("p",{children:"There are no local peerings in this network and project."}),e.jsx("p",{children:e.jsx(ae,{docPath:"/howto/network_ovn_peers",children:"Learn more about local peering"})}),e.jsx(pe,{className:"empty-state-button",network:t})]})]}),m.panel===de.createLocalPeering&&e.jsx(kt,{network:t}),m.panel===de.editLocalPeering&&e.jsx(Ft,{network:t})]})},yn=()=>{const t=s.useNotify(),{name:n,project:a,member:r,activeTab:o}=he();if(!n)return e.jsx(e.Fragment,{children:"Missing name"});if(!a)return e.jsx(e.Fragment,{children:"Missing project"});const{data:l,error:m,isLoading:d}=xe(n,a,r),g=V();if(L.useEffect(()=>{m&&t.failure("Loading network failed",m)},[m]),d)return e.jsx(s.Spinner,{className:"u-loader",text:"Loading...",isMainComponent:!0});const f=l?.managed??!1,c=Ue.includes(l?.type??"")&&f,x=_e.includes(l?.type??"")&&f,p=fe.includes(l?.type??""),u=`${S}/ui/project/${encodeURIComponent(a)}/network/${encodeURIComponent(n)}`,y=N=>z("p-tabs__link",{"is-disabled":N}),w=(N,h,i)=>{const b=M(N),C=h?`${u}/${i}`:"#";return{href:C,className:y(!h),title:h?N:`${N} are not supported on this network`,id:b,label:N,onClick:v=>{v.preventDefault(),t.clear(),g(C)},active:b===o}},k=["Configuration",w("Forwards",c,"forwards"),w("Leases",x,"leases"),w("Local peerings",p,"local-peerings")];return e.jsxs(s.CustomLayout,{header:e.jsx(mt,{network:l,project:a,name:n}),contentClassName:"edit-network",children:[!d&&!l&&e.jsx(Ae,{entityType:"network",entityName:n,errorMessage:m?.message}),!d&&l&&e.jsxs(s.Row,{children:[e.jsx(at,{tabs:k,activeTab:o,tabUrl:u}),e.jsx(se,{}),!o&&e.jsx("div",{role:"tabpanel","aria-labelledby":"configuration",children:l&&e.jsx(dt,{network:l,project:a})}),o==="forwards"&&e.jsx("div",{role:"tabpanel","aria-labelledby":"forwards",children:l&&e.jsx(ht,{network:l,project:a})}),o==="leases"&&e.jsx("div",{role:"tabpanel","aria-labelledby":"leases",children:l&&e.jsx(wt,{network:l,project:a})}),o==="local-peerings"&&e.jsx("div",{role:"tabpanel","aria-labelledby":"local-peerings",children:l&&e.jsx(Rt,{network:l,project:a})})]})]})};export{yn as default};