diff --git a/spinifex/services/spinifexui/frontend/dist/assets/create-cluster.js b/spinifex/services/spinifexui/frontend/dist/assets/create-cluster.js index 3a43d5628..81c15227f 100644 --- a/spinifex/services/spinifexui/frontend/dist/assets/create-cluster.js +++ b/spinifex/services/spinifexui/frontend/dist/assets/create-cluster.js @@ -1 +1 @@ -import{n as e,o as t,r as n,t as r}from"./compiler-runtime.js";import{t as i}from"./error-banner.js";import{t as a}from"./useSuspenseQuery.js";import{Ut as o}from"./auth.js";import{t as s}from"./back-link.js";import{t as c}from"./check.js";import{c as l,i as u,n as d,s as f,t as p}from"./select.js";import{t as m}from"./copy.js";import{t as h}from"./rotate-cw.js";import{t as g}from"./triangle-alert.js";import{t as _}from"./button.js";import{i as v,l as y,m as b}from"./eks.js";import{Ir as x,Lr as S,Lt as C,Nt as w,Rn as T,pt as E,rt as D}from"./index.js";import{i as O,n as k,t as ee}from"./zod.js";import{t as A}from"./use-copy-to-clipboard.js";import{t as te}from"./form-actions.js";import{t as j}from"./page-heading.js";import{a as M,r as N,t as P}from"./field.js";import{t as F}from"./system-managed.js";var I=t(n(),1),L=r(),R=e(),z=`make import-eks-node-image`;function B(e){let t=(0,L.c)(21),{isRechecking:n,onRecheck:r}=e,{copied:i,copy:a}=A(),o;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,R.jsx)(g,{className:`mt-0.5 size-5 shrink-0 text-tactical-amber`}),t[0]=o):o=t[0];let s;t[1]===Symbol.for(`react.memo_cache_sentinel`)?(s=(0,R.jsxs)(`div`,{className:`space-y-1`,children:[(0,R.jsx)(`h2`,{className:`text-sm font-semibold text-foreground`,children:`EKS system image not found`}),(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`EKS clusters boot a Spinifex-managed node image (K3s) that is not shipped with the platform. Install it on the host before creating a cluster.`})]}),t[1]=s):s=t[1];let l,u;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,R.jsx)(`span`,{className:`text-muted-foreground select-none`,children:`$`}),u=(0,R.jsx)(`span`,{className:`flex-1 text-foreground`,children:z}),t[2]=l,t[3]=u):(l=t[2],u=t[3]);let d;t[4]===a?d=t[5]:(d=()=>void a(z),t[4]=a,t[5]=d);let f;t[6]===i?f=t[7]:(f=i?(0,R.jsx)(c,{className:`size-3.5 text-tactical-green`}):(0,R.jsx)(m,{className:`size-3.5`}),t[6]=i,t[7]=f);let p;t[8]!==d||t[9]!==f?(p=(0,R.jsxs)(`div`,{className:`flex items-center gap-2 rounded border border-border bg-background px-3 py-2 font-mono text-xs`,children:[l,u,(0,R.jsx)(`button`,{"aria-label":`Copy command`,className:`text-muted-foreground transition-colors hover:text-foreground`,onClick:d,type:`button`,children:f})]}),t[8]=d,t[9]=f,t[10]=p):p=t[10];let v;t[11]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Run from the Spinifex repo root. The command builds and registers the node image, then click Recheck.`}),t[11]=v):v=t[11];let y=n?`size-4 animate-spin`:`size-4`,b;t[12]===y?b=t[13]:(b=(0,R.jsx)(h,{className:y}),t[12]=y,t[13]=b);let x;t[14]!==n||t[15]!==r||t[16]!==b?(x=(0,R.jsxs)(_,{disabled:n,onClick:r,size:`sm`,variant:`outline`,children:[b,`Recheck`]}),t[14]=n,t[15]=r,t[16]=b,t[17]=x):x=t[17];let S;return t[18]!==x||t[19]!==p?(S=(0,R.jsx)(`div`,{className:`max-w-2xl rounded-md border border-tactical-amber/40 bg-tactical-amber/5 p-6`,children:(0,R.jsxs)(`div`,{className:`flex items-start gap-3`,children:[o,(0,R.jsxs)(`div`,{className:`space-y-4`,children:[s,p,v,x]})]})}),t[18]=x,t[19]=p,t[20]=S):S=t[20],S}function V(e){let t=o(e.Tags);return t?`${e.VpcId} (${t})`:`${e.VpcId} (${e.CidrBlock})`}function H(e){let t=o(e.Tags);return`${t?`${e.SubnetId} (${t})`:e.SubnetId} · ${e.CidrBlock}`}function U(){let e=x(),t=S(),[n,r]=(0,I.useState)(!1),{data:o}=a(C),{data:c}=a(w),{data:m}=a(D),{data:h}=a(E),g=b(),A=(h.Images??[]).some(F),L=async()=>{r(!0);try{await t.invalidateQueries({queryKey:E.queryKey})}finally{r(!1)}},z=o.Vpcs??[],U=c.Subnets??[],W=m.Roles??[],{control:G,formState:{errors:K,isSubmitting:q},handleSubmit:J,register:ne,setValue:Y,watch:X}=O({resolver:ee(y),defaultValues:{name:``,version:v[0],roleArn:``,vpcId:``,subnetIds:[],bootstrapClusterCreatorAdminPermissions:!0,endpointPublicAccess:!0,endpointPrivateAccess:!1,publicAccessCidrs:[`0.0.0.0/0`]}}),re=X(`vpcId`),Z=X(`subnetIds`),ie=X(`endpointPublicAccess`),Q=X(`publicAccessCidrs`),$=U.filter(e=>e.VpcId===re),ae=(e=``)=>{Y(`vpcId`,e??``,{shouldValidate:!0}),Y(`subnetIds`,[])},oe=e=>{Y(`subnetIds`,Z.includes(e)?Z.filter(t=>t!==e):[...Z,e],{shouldValidate:!0})},se=(e,t)=>{let n=[...Q];n[e]=t,Y(`publicAccessCidrs`,n,{shouldValidate:!0})},ce=()=>Y(`publicAccessCidrs`,[...Q,``],{shouldValidate:!0}),le=e=>Y(`publicAccessCidrs`,Q.filter((t,n)=>n!==e),{shouldValidate:!0});return A?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(s,{to:`/eks/list-clusters`,children:`Clusters`}),(0,R.jsx)(j,{subtitle:`EKS`,title:`Create Cluster`}),g.error&&(0,R.jsx)(i,{error:g.error,msg:`Failed to create cluster`}),(0,R.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:J(async t=>{await g.mutateAsync(t),await e({to:`/eks/list-clusters/$clusterName`,params:{clusterName:t.name}})}),children:[(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-name`,children:`Name`})}),(0,R.jsx)(T,{"aria-invalid":!!K.name,id:`cluster-name`,placeholder:`my-cluster`,...ne(`name`)}),(0,R.jsx)(N,{errors:[K.name]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-version`,children:`Kubernetes version`})}),(0,R.jsx)(k,{control:G,name:`version`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e.onChange,value:e.value,children:[(0,R.jsx)(f,{className:`w-full`,id:`cluster-version`,children:(0,R.jsx)(l,{placeholder:`Select version`})}),(0,R.jsx)(d,{children:v.map(e=>(0,R.jsx)(u,{value:e,children:e},e))})]})}),(0,R.jsx)(N,{errors:[K.version]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-role`,children:`Cluster IAM role`})}),(0,R.jsx)(k,{control:G,name:`roleArn`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e.onChange,value:e.value,children:[(0,R.jsx)(f,{"aria-invalid":!!K.roleArn,className:`w-full`,id:`cluster-role`,children:(0,R.jsx)(l,{placeholder:`Select role`})}),(0,R.jsx)(d,{children:W.map(e=>(0,R.jsx)(u,{value:e.Arn??``,children:e.RoleName},e.Arn))})]})}),(0,R.jsx)(N,{errors:[K.roleArn]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-vpc`,children:`VPC`})}),(0,R.jsx)(k,{control:G,name:`vpcId`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e=>ae(e),value:e.value,children:[(0,R.jsx)(f,{"aria-invalid":!!K.vpcId,className:`w-full`,id:`cluster-vpc`,children:(0,R.jsx)(l,{placeholder:`Select VPC`})}),(0,R.jsx)(d,{children:z.map(e=>(0,R.jsx)(u,{value:e.VpcId??``,children:V(e)},e.VpcId))})]})}),(0,R.jsx)(N,{errors:[K.vpcId]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Subnets (select at least 1)`}),$.length===0?(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No subnets in the selected VPC.`}):(0,R.jsx)(`div`,{className:`space-y-1`,children:$.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Subnet ${H(e)}`,checked:Z.includes(e.SubnetId??``),onChange:()=>oe(e.SubnetId??``),type:`checkbox`}),(0,R.jsx)(`span`,{className:`font-mono`,children:H(e)})]},e.SubnetId))}),(0,R.jsx)(N,{errors:[K.subnetIds]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Endpoint access`}),(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Public access exposes the API server on an internet-facing endpoint; private access keeps it reachable only from within the VPC. At least one must be enabled.`}),(0,R.jsx)(k,{control:G,name:`endpointPublicAccess`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`mt-2 flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Enable public access`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Public`]})}),(0,R.jsx)(k,{control:G,name:`endpointPrivateAccess`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Enable private access`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Private`]})}),(0,R.jsx)(N,{errors:[K.endpointPublicAccess]}),ie&&(0,R.jsxs)(`div`,{className:`mt-2 space-y-2`,children:[(0,R.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Public access source ranges (CIDR). Defaults to`,` `,(0,R.jsx)(`span`,{className:`font-mono`,children:`0.0.0.0/0`}),`.`]}),Q.map((e,t)=>(0,R.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,R.jsx)(T,{"aria-label":`Public access CIDR ${t+1}`,className:`font-mono`,onChange:e=>se(t,e.target.value),placeholder:`203.0.113.0/24`,value:e}),(0,R.jsx)(_,{onClick:()=>le(t),size:`sm`,type:`button`,variant:`ghost`,children:`Remove`})]},t)),(0,R.jsx)(_,{onClick:ce,size:`sm`,type:`button`,variant:`outline`,children:`Add CIDR`}),(0,R.jsx)(N,{errors:[K.publicAccessCidrs]})]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Access`}),(0,R.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Authentication mode is `,(0,R.jsx)(`span`,{className:`font-mono`,children:`API`}),` (IAM access entries). The legacy aws-auth ConfigMap is not supported.`]}),(0,R.jsx)(k,{control:G,name:`bootstrapClusterCreatorAdminPermissions`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`mt-2 flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Grant the cluster creator admin permissions`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Grant the cluster creator admin permissions`]})})]}),(0,R.jsx)(te,{isPending:g.isPending,isSubmitting:q,onCancel:async()=>await e({to:`/eks/list-clusters`}),pendingLabel:`Creating…`,submitLabel:`Create Cluster`})]})]}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(s,{to:`/eks/list-clusters`,children:`Clusters`}),(0,R.jsx)(j,{subtitle:`EKS`,title:`Create Cluster`}),(0,R.jsx)(B,{isRechecking:n,onRecheck:L})]})}var W=U;export{W as component}; \ No newline at end of file +import{n as e,o as t,r as n,t as r}from"./compiler-runtime.js";import{t as i}from"./error-banner.js";import{t as a}from"./useSuspenseQuery.js";import{Ut as o}from"./auth.js";import{t as s}from"./back-link.js";import{t as c}from"./check.js";import{c as l,i as u,n as d,s as f,t as p}from"./select.js";import{t as m}from"./copy.js";import{t as h}from"./rotate-cw.js";import{t as g}from"./triangle-alert.js";import{t as _}from"./button.js";import{i as v,l as y,m as b}from"./eks.js";import{Ir as x,Lr as S,Lt as C,Nt as w,Rn as T,pt as E,rt as D}from"./index.js";import{i as O,n as k,t as ee}from"./zod.js";import{t as A}from"./use-copy-to-clipboard.js";import{t as te}from"./form-actions.js";import{t as j}from"./page-heading.js";import{a as M,r as N,t as P}from"./field.js";import{t as F}from"./system-managed.js";var I=t(n(),1),L=r(),R=e(),z=`spx admin images import --name spinifex-eks-node`;function B(e){let t=(0,L.c)(21),{isRechecking:n,onRecheck:r}=e,{copied:i,copy:a}=A(),o;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,R.jsx)(g,{className:`mt-0.5 size-5 shrink-0 text-tactical-amber`}),t[0]=o):o=t[0];let s;t[1]===Symbol.for(`react.memo_cache_sentinel`)?(s=(0,R.jsxs)(`div`,{className:`space-y-1`,children:[(0,R.jsx)(`h2`,{className:`text-sm font-semibold text-foreground`,children:`EKS system image not found`}),(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`EKS clusters boot a Spinifex-managed node image (K3s) that is not shipped with the platform. Import it before creating a cluster.`})]}),t[1]=s):s=t[1];let l,u;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,R.jsx)(`span`,{className:`text-muted-foreground select-none`,children:`$`}),u=(0,R.jsx)(`span`,{className:`flex-1 text-foreground`,children:z}),t[2]=l,t[3]=u):(l=t[2],u=t[3]);let d;t[4]===a?d=t[5]:(d=()=>void a(z),t[4]=a,t[5]=d);let f;t[6]===i?f=t[7]:(f=i?(0,R.jsx)(c,{className:`size-3.5 text-tactical-green`}):(0,R.jsx)(m,{className:`size-3.5`}),t[6]=i,t[7]=f);let p;t[8]!==d||t[9]!==f?(p=(0,R.jsxs)(`div`,{className:`flex items-center gap-2 rounded border border-border bg-background px-3 py-2 font-mono text-xs`,children:[l,u,(0,R.jsx)(`button`,{"aria-label":`Copy command`,className:`text-muted-foreground transition-colors hover:text-foreground`,onClick:d,type:`button`,children:f})]}),t[8]=d,t[9]=f,t[10]=p):p=t[10];let v;t[11]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Run from any authenticated spx CLI host. The command downloads and registers the published node image, then click Recheck.`}),t[11]=v):v=t[11];let y=n?`size-4 animate-spin`:`size-4`,b;t[12]===y?b=t[13]:(b=(0,R.jsx)(h,{className:y}),t[12]=y,t[13]=b);let x;t[14]!==n||t[15]!==r||t[16]!==b?(x=(0,R.jsxs)(_,{disabled:n,onClick:r,size:`sm`,variant:`outline`,children:[b,`Recheck`]}),t[14]=n,t[15]=r,t[16]=b,t[17]=x):x=t[17];let S;return t[18]!==x||t[19]!==p?(S=(0,R.jsx)(`div`,{className:`max-w-2xl rounded-md border border-tactical-amber/40 bg-tactical-amber/5 p-6`,children:(0,R.jsxs)(`div`,{className:`flex items-start gap-3`,children:[o,(0,R.jsxs)(`div`,{className:`space-y-4`,children:[s,p,v,x]})]})}),t[18]=x,t[19]=p,t[20]=S):S=t[20],S}function V(e){let t=o(e.Tags);return t?`${e.VpcId} (${t})`:`${e.VpcId} (${e.CidrBlock})`}function H(e){let t=o(e.Tags);return`${t?`${e.SubnetId} (${t})`:e.SubnetId} · ${e.CidrBlock}`}function U(){let e=x(),t=S(),[n,r]=(0,I.useState)(!1),{data:o}=a(C),{data:c}=a(w),{data:m}=a(D),{data:h}=a(E),g=b(),A=(h.Images??[]).some(F),L=async()=>{r(!0);try{await t.invalidateQueries({queryKey:E.queryKey})}finally{r(!1)}},z=o.Vpcs??[],U=c.Subnets??[],W=m.Roles??[],{control:G,formState:{errors:K,isSubmitting:q},handleSubmit:J,register:ne,setValue:Y,watch:X}=O({resolver:ee(y),defaultValues:{name:``,version:v[0],roleArn:``,vpcId:``,subnetIds:[],bootstrapClusterCreatorAdminPermissions:!0,endpointPublicAccess:!0,endpointPrivateAccess:!1,publicAccessCidrs:[`0.0.0.0/0`]}}),re=X(`vpcId`),Z=X(`subnetIds`),ie=X(`endpointPublicAccess`),Q=X(`publicAccessCidrs`),$=U.filter(e=>e.VpcId===re),ae=(e=``)=>{Y(`vpcId`,e??``,{shouldValidate:!0}),Y(`subnetIds`,[])},oe=e=>{Y(`subnetIds`,Z.includes(e)?Z.filter(t=>t!==e):[...Z,e],{shouldValidate:!0})},se=(e,t)=>{let n=[...Q];n[e]=t,Y(`publicAccessCidrs`,n,{shouldValidate:!0})},ce=()=>Y(`publicAccessCidrs`,[...Q,``],{shouldValidate:!0}),le=e=>Y(`publicAccessCidrs`,Q.filter((t,n)=>n!==e),{shouldValidate:!0});return A?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(s,{to:`/eks/list-clusters`,children:`Clusters`}),(0,R.jsx)(j,{subtitle:`EKS`,title:`Create Cluster`}),g.error&&(0,R.jsx)(i,{error:g.error,msg:`Failed to create cluster`}),(0,R.jsxs)(`form`,{className:`max-w-4xl space-y-6`,onSubmit:J(async t=>{await g.mutateAsync(t),await e({to:`/eks/list-clusters/$clusterName`,params:{clusterName:t.name}})}),children:[(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-name`,children:`Name`})}),(0,R.jsx)(T,{"aria-invalid":!!K.name,id:`cluster-name`,placeholder:`my-cluster`,...ne(`name`)}),(0,R.jsx)(N,{errors:[K.name]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-version`,children:`Kubernetes version`})}),(0,R.jsx)(k,{control:G,name:`version`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e.onChange,value:e.value,children:[(0,R.jsx)(f,{className:`w-full`,id:`cluster-version`,children:(0,R.jsx)(l,{placeholder:`Select version`})}),(0,R.jsx)(d,{children:v.map(e=>(0,R.jsx)(u,{value:e,children:e},e))})]})}),(0,R.jsx)(N,{errors:[K.version]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-role`,children:`Cluster IAM role`})}),(0,R.jsx)(k,{control:G,name:`roleArn`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e.onChange,value:e.value,children:[(0,R.jsx)(f,{"aria-invalid":!!K.roleArn,className:`w-full`,id:`cluster-role`,children:(0,R.jsx)(l,{placeholder:`Select role`})}),(0,R.jsx)(d,{children:W.map(e=>(0,R.jsx)(u,{value:e.Arn??``,children:e.RoleName},e.Arn))})]})}),(0,R.jsx)(N,{errors:[K.roleArn]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:(0,R.jsx)(`label`,{htmlFor:`cluster-vpc`,children:`VPC`})}),(0,R.jsx)(k,{control:G,name:`vpcId`,render:({field:e})=>(0,R.jsxs)(p,{onValueChange:e=>ae(e),value:e.value,children:[(0,R.jsx)(f,{"aria-invalid":!!K.vpcId,className:`w-full`,id:`cluster-vpc`,children:(0,R.jsx)(l,{placeholder:`Select VPC`})}),(0,R.jsx)(d,{children:z.map(e=>(0,R.jsx)(u,{value:e.VpcId??``,children:V(e)},e.VpcId))})]})}),(0,R.jsx)(N,{errors:[K.vpcId]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Subnets (select at least 1)`}),$.length===0?(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No subnets in the selected VPC.`}):(0,R.jsx)(`div`,{className:`space-y-1`,children:$.map(e=>(0,R.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Subnet ${H(e)}`,checked:Z.includes(e.SubnetId??``),onChange:()=>oe(e.SubnetId??``),type:`checkbox`}),(0,R.jsx)(`span`,{className:`font-mono`,children:H(e)})]},e.SubnetId))}),(0,R.jsx)(N,{errors:[K.subnetIds]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Endpoint access`}),(0,R.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Public access exposes the API server on an internet-facing endpoint; private access keeps it reachable only from within the VPC. At least one must be enabled.`}),(0,R.jsx)(k,{control:G,name:`endpointPublicAccess`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`mt-2 flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Enable public access`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Public`]})}),(0,R.jsx)(k,{control:G,name:`endpointPrivateAccess`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Enable private access`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Private`]})}),(0,R.jsx)(N,{errors:[K.endpointPublicAccess]}),ie&&(0,R.jsxs)(`div`,{className:`mt-2 space-y-2`,children:[(0,R.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Public access source ranges (CIDR). Defaults to`,` `,(0,R.jsx)(`span`,{className:`font-mono`,children:`0.0.0.0/0`}),`.`]}),Q.map((e,t)=>(0,R.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,R.jsx)(T,{"aria-label":`Public access CIDR ${t+1}`,className:`font-mono`,onChange:e=>se(t,e.target.value),placeholder:`203.0.113.0/24`,value:e}),(0,R.jsx)(_,{onClick:()=>le(t),size:`sm`,type:`button`,variant:`ghost`,children:`Remove`})]},t)),(0,R.jsx)(_,{onClick:ce,size:`sm`,type:`button`,variant:`outline`,children:`Add CIDR`}),(0,R.jsx)(N,{errors:[K.publicAccessCidrs]})]})]}),(0,R.jsxs)(P,{children:[(0,R.jsx)(M,{children:`Access`}),(0,R.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Authentication mode is `,(0,R.jsx)(`span`,{className:`font-mono`,children:`API`}),` (IAM access entries). The legacy aws-auth ConfigMap is not supported.`]}),(0,R.jsx)(k,{control:G,name:`bootstrapClusterCreatorAdminPermissions`,render:({field:e})=>(0,R.jsxs)(`label`,{className:`mt-2 flex items-center gap-2 text-xs`,children:[(0,R.jsx)(`input`,{"aria-label":`Grant the cluster creator admin permissions`,checked:e.value,onChange:t=>e.onChange(t.target.checked),type:`checkbox`}),`Grant the cluster creator admin permissions`]})})]}),(0,R.jsx)(te,{isPending:g.isPending,isSubmitting:q,onCancel:async()=>await e({to:`/eks/list-clusters`}),pendingLabel:`Creating…`,submitLabel:`Create Cluster`})]})]}):(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(s,{to:`/eks/list-clusters`,children:`Clusters`}),(0,R.jsx)(j,{subtitle:`EKS`,title:`Create Cluster`}),(0,R.jsx)(B,{isRechecking:n,onRecheck:L})]})}var W=U;export{W as component}; \ No newline at end of file diff --git a/spinifex/services/spinifexui/frontend/src/routes/_auth/eks/(clusters)/-components/eks-system-image-required.tsx b/spinifex/services/spinifexui/frontend/src/routes/_auth/eks/(clusters)/-components/eks-system-image-required.tsx index 71e96cfbf..47dbd2c6a 100644 --- a/spinifex/services/spinifexui/frontend/src/routes/_auth/eks/(clusters)/-components/eks-system-image-required.tsx +++ b/spinifex/services/spinifexui/frontend/src/routes/_auth/eks/(clusters)/-components/eks-system-image-required.tsx @@ -3,7 +3,7 @@ import { Check, Copy, RotateCw, TriangleAlert } from "lucide-react" import { Button } from "@/components/ui/button" import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard" -const IMPORT_COMMAND = "make import-eks-node-image" +const IMPORT_COMMAND = "spx admin images import --name spinifex-eks-node" export function EksSystemImageRequired({ isRechecking, @@ -25,8 +25,7 @@ export function EksSystemImageRequired({
EKS clusters boot a Spinifex-managed node image (K3s) that is not - shipped with the platform. Install it on the host before creating - a cluster. + shipped with the platform. Import it before creating a cluster.
@@ -48,8 +47,8 @@ export function EksSystemImageRequired({- Run from the Spinifex repo root. The command builds and registers - the node image, then click Recheck. + Run from any authenticated spx CLI host. The command downloads and + registers the published node image, then click Recheck.