1import * as _ from 'lodash-es'2import { isActionSupported } from '../../deployF/k8sF/isActionSupportedF.mts'3import { getKlusterCtx, type KubeResource } from '../../deployF/k8sF/ctxF/klusterCtxF.mts'4import { chalkGreen } from '../../serverF/libChalkF.mts'6import { getNextSvcPortNo } from '../../serverF/getReqEnvConfItemF.mts'7import { ingressTmpl } from '../../deployF/k8sF/ingressF.mts'8import { kubeSvcTmpl } from '../../deployF/k8sF/kubeSvcTmplF.mts'9import { getAppCfg } from '../../deployF/k8sF/ctxF/appCfgCtxF.mts'10import { getNonWcDns, getCfProxied } from '../../deployF/k8sF/get1NonWcDnsF.mts'11import { cleanupExplicitWcDns } from '../../deployF/hostnameF/cleanupExplicitWcDnsAI.mts'12import { ingressAnnotFromAppCfg } from '../../deployF/k8sF/ingressAnnotFromAppCfgF.mts'13import { ingressCommonAnnotationsH } from '../../deployF/ingressBaseCommonAnnotHF.mts'14import { assertDefined } from '../../sharedF/assertsF/assertDefinedF.mts'15import { resourcesAction } from '../../deployF/k8sF/resourcesActionF.mts'16import { getAction } from '../../deployF/ctxF/actionCtxF.mts'18type SyncKlusterCtx = { name: string, kube_extHostname: string, cfProxied?: boolean, fromToWWW?: boolean, wcHostname?: string }20type IngressTemplateProps = {21 name: string22 kube_extHostname: string23 fromToWWW?: boolean24 ingressClassName?: string25 cfProxied?: boolean26 action?: string27}29const ingressTemplate = ({30 name, kube_extHostname, fromToWWW, ingressClassName,31 cfProxied,32}: IngressTemplateProps) => {34 const svcPortNo = appCfg.svcPortNo || getNextSvcPortNo()35 const ingressAnnotH = appCfg.ingressAnnotationsH37 const templateBase = {38 apiVersion: 'networking.k8s.io/v1',39 kind: 'Ingress',40 metadata: {name}41 }43 assertDefined(kube_extHostname)45 const nonWcDns = getNonWcDns(kube_extHostname)47 if (_.isUndefined(cfProxied)) {48 cfProxied = getCfProxied(kube_extHostname)49 }51 const hosts = [kube_extHostname]52 const startsWithWWW = _.startsWith(kube_extHostname, 'www.')53 if (fromToWWW && startsWithWWW) {54 const altExtHostname = _.replace(kube_extHostname, 'www.', '')55 hosts.push(altExtHostname)56 } else {57 fromToWWW = false58 }60 let annotations: Record<string, string> = {61 ...ingressAnnotFromAppCfg({fromToWWW}),62 'nginx.ingress.kubernetes.io/proxy-read-timeout': '99999',63 }64 if (nonWcDns) {65 annotations = {...annotations,66 'external-dns.alpha.kubernetes.io/cloudflare-proxied': cfProxied ? 'true' : 'false',67 'external-dns.alpha.kubernetes.io/hostname': hosts.join(','),68 }69 }70 annotations = {71 ...annotations,72 ...ingressCommonAnnotationsH,73 ...ingressAnnotH,74 }76 return _.merge(templateBase, {77 metadata: {78 annotations,79 },80 spec: {81 ...ingressTmpl({ingressClassName, hostname: kube_extHostname, name}),82 rules: [83 {84 host: kube_extHostname,85 http: {86 paths: [87 {88 path: '/',89 pathType: 'Prefix',90 backend: {91 service: {92 name,93 port: {94 number: svcPortNo95 }96 }97 }98 }99 ]100 }101 }102 ]103 }104 })105}107type SyncResourcesProps = { resources?: KubeResource[] }109export const syncOtherNextAppResources = async (props?: SyncResourcesProps) => {110 let {resources=[]} = props || {} as SyncResourcesProps112 const {113 name, kube_extHostname, cfProxied, fromToWWW, wcHostname,114 } = getKlusterCtx() as SyncKlusterCtx117 if (isActionSupported(action)) {118 const svcPortNo = getAppCfg().svcPortNo || getNextSvcPortNo() as number119 resources = [120 ...resources,121 kubeSvcTmpl({name, portNo: svcPortNo}) as KubeResource,122 ingressTemplate({name, action, kube_extHostname, cfProxied, fromToWWW}) as KubeResource123 ]125 await resourcesAction({resources, action})126 }127 if (action === 'apply' && wcHostname) {128 await cleanupExplicitWcDns(kube_extHostname)129 }130 if (_.includes(['apply', 'info'], action)) {131 console.log(chalkGreen(`\napp hosted at`, getAppCfg().hostedAtUrl || kube_extHostname))132 }133}