Your IP : 216.73.216.189


Current Path : /proc/thread-self/root/snap/lxd/current/share/lxd-ui/assets/
Upload File :
Current File : //proc/thread-self/root/snap/lxd/current/share/lxd-ui/assets/ClusterLinkList-BGDh-9cv.js

import{x as D,j as e,d as t,u as B,B as L,r as g,t as f,y,v as S,R as N,w as b,k as w,C as R,D as q,f as H,h as P,E as _,F as O,G as K,e as V,H as $,p as U}from"./index-BFGypnt-.js";import{B as M}from"./BaseLayout-ft99KK4_.js";import{H as Q}from"./HelpLink-l4aaXUp-.js";import{u as Y}from"./useSortTableData-DMPSUVcX.js";import{u as k,p as E}from"./usePanelParams-CV5ZHNeu.js";import{d as z,u as J,a as W,b as X,c as Z,e as ee}from"./useClusterLinks-CpODgtKY.js";import{G as te}from"./GroupSelection-sYtH6Ve5.js";import{u as se}from"./useAuthGroups-3GAYR02a.js";import{E as ne}from"./ExpandableList-DK5_MQFC.js";import{C as F}from"./CodeSnippetWithCopyButton-DAE09ff3.js";import"./PermissionGroupsFilter-BWepc9mD.js";import"./SelectableMainTable-BZaSR8Vv.js";const T=()=>{const s=k(),{canCreateClusterLinks:a}=D(),n=a()?void 0:"You do not have permission to create cluster links";return e.jsxs(t.Button,{appearance:"positive",className:"u-no-margin--bottom",hasIcon:!0,onClick:s.openCreateClusterLink,title:n,disabled:n!==void 0,children:[e.jsx(t.Icon,{name:"plus",light:!0}),e.jsx("span",{children:"Create link"})]})},I=()=>{const{isFineGrained:s}=B();return{canDeleteClusterLink:i=>L(s,"can_delete",i?.access_entitlements),canEditClusterLink:i=>L(s,"can_edit",i?.access_entitlements)}},ae=({clusterLink:s})=>{const{canDeleteClusterLink:a}=I(),n=t.useNotify(),i=t.useToastNotification(),[m,c]=g.useState(!1),o=f(),u=a(s),l=()=>{c(!0),z(s.name).then(()=>{i.success(e.jsxs(e.Fragment,{children:["Cluster link"," ",e.jsx(S,{type:"cluster-link",value:s.name,to:`${N}/ui/cluster/links`})," ","deleted."]}))}).catch(r=>{n.failure("Cluster link deletion failed",r)}).finally(()=>{c(!1),o.invalidateQueries({queryKey:[b.cluster,b.links]})})};return e.jsx(t.ConfirmationButton,{appearance:"base",className:"has-icon",title:"Delete cluster link",disabled:!u,loading:m,confirmationModalProps:{title:"Confirm delete",children:e.jsxs("p",{children:["This will permanently delete cluster link"," ",e.jsx(y,{type:"cluster-link",value:s.name,bold:!0}),"."]}),confirmButtonLabel:u?"Delete cluster link":"You do not have permission to delete this cluster link",onConfirm:l},shiftClickEnabled:!0,showShiftClickHint:!0,children:e.jsx(t.Icon,{name:"delete"})})},ie=(s,a)=>s?.type.toLowerCase().includes("(pending)")?"Pending":a?.cluster_link_members.some(n=>n.status==="Active")?"Reachable":"Unreachable",le={Reachable:"status-succeeded-small",Unreachable:"status-failed-small",Pending:"status-queued-small"},re=({link:s,identity:a})=>{const{data:n,isLoading:i}=J(s.name);if(i)return e.jsx(t.Spinner,{className:"status-spinner"});const m=ie(a,n);return e.jsxs(e.Fragment,{children:[e.jsx(t.Icon,{name:le[m],className:"status-icon"}),m]})},oe=({clusterLink:s})=>{const{canEditClusterLink:a}=I(),n=k(),i=a(s);return e.jsx(t.Button,{appearance:"base",className:"u-no-margin--bottom",onClick:()=>{n.openEditClusterLink(s.name)},title:i?"Edit cluster link":"You do not have permission to edit this cluster link",hasIcon:!0,disabled:!i,children:e.jsx(t.Icon,{name:"edit"})})},G=({formik:s})=>{const{data:a=[]}=se(),n=new Set(s.values.authGroups),i=new Set(s.values.initialAuthGroups),m=[...i].filter(l=>!n.has(l)),c=[...n].filter(l=>!i.has(l)),o=new Set([...m,...c]),u=s.values.name!=="";return e.jsxs(t.Form,{onSubmit:s.handleSubmit,children:[e.jsx(t.Input,{type:"submit",hidden:!0,value:"Hidden input"}),s.values.isCreating&&e.jsx(t.Input,{...s.getFieldProps("name"),type:"text",label:"Name",placeholder:"Enter name",required:!0,autoFocus:!0,error:s.touched.name?s.errors.name:null}),e.jsx(t.Input,{...s.getFieldProps("description"),type:"text",label:"Description",placeholder:"Enter description",disabled:!u,title:u?void 0:"Please enter a name before adding a description"}),s.values.isCreating&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"u-sv1",title:u?void 0:"Please enter a name before selecting token options",children:[e.jsx(t.RadioInput,{inline:!0,labelClassName:"margin-right--large",label:"Generate token",checked:s.values.tokenType==="generate",onChange:()=>{s.setFieldValue("tokenType","generate")},disabled:!u}),e.jsx(t.RadioInput,{inline:!0,label:"Consume token",checked:s.values.tokenType==="consume",onChange:()=>{s.setFieldValue("tokenType","consume")},disabled:!u})]}),s.values.tokenType==="consume"&&e.jsx(t.Input,{...s.getFieldProps("token"),type:"text",label:"Token",placeholder:"Enter token"})]}),e.jsx(t.Label,{className:"u-sv-2",children:"Auth groups"}),e.jsx("p",{className:"u-text--muted u-sv-1 p-text--small",children:"Control access for incoming requests through this cluster link."}),e.jsx(te,{groups:a,modifiedGroups:o,parentItemName:"cluster link",selectedGroups:n,setSelectedGroups:(l,r)=>{r?s.setFieldValue("authGroups",[]):s.setFieldValue("authGroups",l)},toggleGroup:l=>{const r=s.values.authGroups;r.includes(l)?s.setFieldValue("authGroups",r.filter(d=>d!==l)):s.setFieldValue("authGroups",[...r,l])},scrollDependencies:[s],disabled:!u})]})},ce=({identity:s})=>{const a=k(),[n,i]=g.useState(null),m=t.useToastNotification(),c=f(),{data:o}=W(a.identity??""),u=()=>{a.clear(),i(null)},l=w({initialValues:{name:o?.name??"",description:o?.description??"",authGroups:s?.groups??[],isCreating:!1,initialAuthGroups:s?.groups??[]},enableReinitialize:!0,onSubmit:r=>{const d={...o,description:r.description};X(o?.name??"",JSON.stringify(d)).then(async()=>{const h={...s,groups:r.authGroups};await R(h),u(),m.success(e.jsxs(e.Fragment,{children:["Cluster link"," ",e.jsx(S,{type:"cluster-link",value:o?.name??"",to:`${N}/ui/cluster/links`})," ","saved."]}))}).catch(h=>{i(t.failure("Cluster link update failed",h))}).finally(()=>{l.setSubmitting(!1),c.invalidateQueries({queryKey:[b.cluster,b.links]}),c.invalidateQueries({queryKey:[b.identities]})})}});return e.jsxs(t.SidePanel,{children:[e.jsx(t.SidePanel.Header,{children:e.jsx(t.SidePanel.HeaderTitle,{className:"u-truncate",children:e.jsxs("span",{title:`Edit cluster link ${o?.name}`,children:["Edit cluster link ",o?.name]})})}),e.jsx(t.Row,{className:"u-no-padding",children:n&&e.jsx(t.Notification,{title:n.title,severity:"negative",onDismiss:()=>{i(null)},children:n.message})}),e.jsx(t.SidePanel.Content,{className:"u-no-padding",children:e.jsx(t.ScrollableContainer,{dependencies:[n],belowIds:["panel-footer"],children:e.jsx(G,{formik:l})})}),e.jsxs(t.SidePanel.Footer,{className:"u-align--right",children:[e.jsx(t.Button,{appearance:"base",onClick:u,className:"u-no-margin--bottom",children:"Cancel"}),e.jsx(t.ActionButton,{appearance:"positive",loading:l.isSubmitting,onClick:()=>{l.submitForm()},className:"u-no-margin--bottom",disabled:!l.isValid||l.isSubmitting,children:"Save changes"})]})]})},ue=({clusterLink:s})=>{const a=s.config["volatile.addresses"];return!a||a===""?null:e.jsx(ne,{items:a.split(",").map(n=>e.jsx("div",{children:e.jsxs("a",{href:`https://${n}`,target:"_blank",rel:"noopener noreferrer",children:[n,e.jsx(t.Icon,{className:"external-link-icon",name:"external-link"})]})},n))??[]})},de=({onClose:s,token:a,linkName:n})=>{const[i,m]=g.useState(!1),[c,o]=g.useState("ui-tab");return e.jsx(t.Modal,{className:"create-cluster-link",title:e.jsxs(e.Fragment,{children:["Cluster link"," ",e.jsx(y,{type:"cluster-link",value:n,bold:!0,truncate:!0})," ","created"]}),buttonRow:[e.jsx("span",{className:"u-float-left confirm-input",children:e.jsx(q,{label:"I have copied the token",confirmed:[i,m]})},"confirm-input"),e.jsx(t.ActionButton,{appearance:"positive",className:"u-no-margin--bottom",onClick:s,disabled:!i,children:"Done"},"confirm-action-button")],closeOnOutsideClick:!1,children:a&&e.jsxs(e.Fragment,{children:[e.jsx(F,{code:a,title:"Your trust token",tooltipMessage:"Copy token",onCopyButtonClick:()=>{m(!0)}}),e.jsxs(t.Notification,{severity:"caution",title:"Copy the trust token",children:["The trust token can be used to establish the cluster link"," ",e.jsx(y,{type:"cluster-link",value:n,bold:!0})," on the target cluster. ",e.jsx("br",{}),"Make sure to copy it now as you will not be able to see this again."]}),e.jsx(t.Accordion,{sections:[{title:"How to use it?",content:e.jsxs(e.Fragment,{children:[e.jsx(t.Tabs,{links:[{label:"CLI",active:c==="cli-tab",onClick:()=>{o("cli-tab")}},{label:"UI",active:c==="ui-tab",onClick:()=>{o("ui-tab")}}]}),c==="cli-tab"&&e.jsxs(e.Fragment,{children:["For use with the LXC command-line tool, run on the target cluster:",e.jsx(F,{code:`lxc cluster link create ${location.hostname} --auth-group admins --token ${a}`,tooltipMessage:"Copy command",className:"u-no-margin--bottom"}),e.jsxs("span",{className:"u-text--muted p-text--small u-sv3",children:["You can replace ",e.jsx("code",{children:location.hostname})," with a nickname for this server."]})]}),c==="ui-tab"&&e.jsx(t.List,{className:"u-no-margin--bottom",items:[e.jsx(e.Fragment,{children:"Open the target cluster UI."}),e.jsxs(e.Fragment,{children:["Select ",e.jsx("b",{children:"Clustering"}),", ",e.jsx("b",{children:"Links"}),","," ",e.jsx("b",{children:"Create link"})," and ",e.jsx("b",{children:"Consume token"}),"."]}),e.jsx(e.Fragment,{children:"Use this trust token to establish the cluster link."})]})]})}]})]})})},me=({onSuccess:s})=>{const a=k(),[n,i]=g.useState(null),m=t.useToastNotification(),c=f(),o=g.useState(null),u=()=>{a.clear(),i(null)},l=H().shape({name:P().test("deduplicate","A cluster link with this name already exists",async d=>_(d,"",o,"cluster/links")).required("Link name is required"),token:P().when("tokenType",{is:"consume",then:d=>d.required("Token is required when consuming a token"),otherwise:d=>d.notRequired()})}),r=w({initialValues:{name:"",description:"",token:"",tokenType:"generate",authGroups:[],isCreating:!0},validationSchema:l,onSubmit:d=>{const h={name:d.name,description:d.description,trust_token:d.token,auth_groups:d.authGroups,type:"bidirectional"};Z(JSON.stringify(h)).then(x=>{if(r.values.tokenType==="generate"&&x){const C=O(x);s(d.name,C)}else m.success(e.jsxs(e.Fragment,{children:["Cluster link"," ",e.jsx(S,{type:"cluster-link",value:d.name,to:`${N}/ui/cluster/links`})," ","created."]}));u()}).catch(x=>{i(t.failure("Cluster link creation failed",x))}).finally(()=>{r.setSubmitting(!1),c.invalidateQueries({queryKey:[b.cluster,b.links]}),c.invalidateQueries({queryKey:[b.identities]})})}});return e.jsxs(t.SidePanel,{className:"cluster-link-panel",children:[e.jsx(t.SidePanel.Header,{children:e.jsx(t.SidePanel.HeaderTitle,{children:"Create cluster link"})}),e.jsx(t.Row,{className:"u-no-padding",children:n&&e.jsx(t.Notification,{title:n.title,severity:"negative",onDismiss:()=>{i(null)},children:n.message})}),e.jsx(t.SidePanel.Content,{className:"u-no-padding",children:e.jsx(t.ScrollableContainer,{dependencies:[n],belowIds:["panel-footer"],children:e.jsx(G,{formik:r})})}),e.jsxs(t.SidePanel.Footer,{className:"u-align--right",children:[e.jsx(t.Button,{appearance:"base",onClick:u,className:"u-no-margin--bottom",disabled:r.isSubmitting,children:"Cancel"}),e.jsx(t.ActionButton,{appearance:"positive",loading:r.isSubmitting,onClick:()=>{r.submitForm()},className:"u-no-margin--bottom",disabled:!r.isValid||r.isSubmitting||!r.values.name,title:r.values.name?void 0:"Please enter a name before submitting the form",children:"Create link"})]})]})},pe=()=>{const s=k(),{openPortal:a,closePortal:n,isOpen:i,Portal:m}=t.usePortal({programmaticallyOpen:!0}),[c,o]=g.useState(""),[u,l]=g.useState(""),r=()=>{o(""),l(""),n()};return e.jsxs(e.Fragment,{children:[i&&e.jsx(m,{children:e.jsx(de,{onClose:r,token:c,linkName:u})}),s.panel===E.createClusterLink&&e.jsx(me,{onSuccess:(d,h)=>{l(d),o(h),a()}})]})},Le=()=>{const s=K(),a=t.useNotify(),n=k(),{data:i=[]}=V(),{data:m=[],error:c,isLoading:o}=ee();c&&a.failure("Loading cluster links failed",c);const u=p=>i.find(j=>j.name===p&&j.type.startsWith("Cluster link certificate")),l=[{content:"Name",sortKey:"name"},{content:"Status",className:"status-header"},{content:"Type",sortKey:"type"},{content:"Description",sortKey:"description"},{content:"Addresses"},{content:"Auth groups",sortKey:"groups"},{"aria-label":"Actions",className:"actions"}],r=m.map(p=>{const j=u(p.name),v=j?.groups?.length??0,A=()=>{n.openEditClusterLink(p.name)};return{key:p.name,columns:[{content:p.name,title:p.name,className:"u-truncate",role:"rowheader","aria-label":"Name"},{content:e.jsx(re,{identity:j,link:p}),role:"cell","aria-label":"Status"},{content:$(p.type.toLowerCase()),role:"cell","aria-label":"Type"},{content:p.description,role:"cell","aria-label":"Description"},{content:e.jsx(ue,{clusterLink:p}),role:"cell","aria-label":"Addresses"},{content:e.jsx(t.Button,{appearance:"link",dense:!0,onClick:A,children:v}),role:"cell","aria-label":"Auth groups"},{content:e.jsx(t.List,{inline:!0,className:"actions-list u-no-margin--bottom",items:[e.jsx(oe,{clusterLink:p},"edit"),e.jsx(ae,{clusterLink:p},"delete")]}),role:"cell","aria-label":"Actions",className:"u-align--right actions"}],sortData:{name:p.name,description:p.description,type:p.type,groups:v}}}),{rows:d,updateSort:h}=Y({rows:r}),x=m.length===0&&!o,C=u(n.identity);return e.jsxs(e.Fragment,{children:[e.jsxs(M,{title:e.jsx(Q,{docPath:"/explanation/clustering/",title:"Learn more about clustering",children:"Cluster links"}),controls:!x&&e.jsx(T,{}),children:[e.jsx(U,{}),e.jsxs(t.Row,{children:[!x&&e.jsx(e.Fragment,{children:e.jsx(t.ScrollableTable,{dependencies:[m,a.notification],tableId:"cluster-link-table-id",belowIds:["status-bar"],children:e.jsx(t.TablePagination,{data:d,id:"pagination",itemName:"cluster link",className:"u-no-margin--top","aria-label":"Table pagination control",children:e.jsx(t.MainTable,{id:"cluster-link-table-id",className:"cluster-link-table",headers:l,sortable:!0,onUpdateSort:h,emptyStateMsg:o&&e.jsx(t.Spinner,{className:"u-loader",text:"Loading cluster links..."})})})})}),x&&e.jsxs(t.EmptyState,{className:"empty-state",image:e.jsx(t.Icon,{name:"applications",className:"empty-state-icon"}),title:"No cluster links found",children:[e.jsx("p",{children:"There are no cluster links on this server."}),e.jsx("p",{children:e.jsxs("a",{href:`${s}/explanation/clustering/`,target:"_blank",rel:"noopener noreferrer",children:["Learn more about clustering",e.jsx(t.Icon,{className:"external-link-icon",name:"external-link"})]})}),e.jsx(T,{})]})]})]}),e.jsx(pe,{}),n.panel===E.editClusterLink&&C&&e.jsx(ce,{identity:C})]})};export{Le as default};