1import { read2Resource } from './k8sF/read2ResourceF.mts'2import { secretTemplate } from './k8sF/k8sSecF.mts'3import * as _ from 'lodash-es'4import { genericCert } from './k8sF/genericCertF.mts'5import { debug1Sleep } from '../serverF/sleepF/debugSleepF.mts'6import { decomposeQsFromSec } from '../serverF/secretsF/decomposeQsFromSecF.mts'7import { genericNodePortTmpl } from './k8sF/generic1NodePortTmplF.mts'8import { kubeActionPvc } from './k8sF/pvcF/kubeActionPvcF.mts'9import { resourcesAction } from './k8sF/resourcesActionF.mts'11export const volumesAndMntsForCert = ({mountPath, certName}: {mountPath: string, certName: string}) => {12 const name = 'certman'13 const volumeMounts = [{14 mountPath, name,15 readOnly: true,16 }]17 const volumes = [{18 name,19 secret: {20 secretName: certName21 }22 }]23 return {volumes, volumeMounts}24}26const postgresDeploymentTemplate = ({name, pvcName, cluster_name, dbType: image='postgres:14.1', enableSsl, isCertReady, certName}: {name: string, pvcName: string, cluster_name: string, dbType?: string, enableSsl?: boolean, isCertReady?: boolean, certName?: string}) => {28 const deployWithSsl = enableSsl && isCertReady30 let volumeMounts = [31 {32 mountPath: '/var/lib/postgresql/data',33 name: 'postgres-pv'34 },35 ]36 let volumes = [37 {38 name: 'postgres-pv',39 persistentVolumeClaim: {40 claimName: pvcName41 }42 },43 ]44 if (deployWithSsl) {45 const vlMnts = volumesAndMntsForCert({certName: certName!, mountPath: '/var/lib/postgresql/certman'})46 volumes = [...volumes, ...vlMnts.volumes] as typeof volumes47 volumeMounts = [...volumeMounts, ...vlMnts.volumeMounts]48 }50 return {51 apiVersion: 'apps/v1',52 kind: 'Deployment',53 metadata: {54 name,55 labels: {name, cluster_name},56 },57 spec: {58 replicas: 1,59 selector: {60 matchLabels: {61 name62 }63 },64 template: {65 metadata: {66 labels: {67 name68 }69 },70 spec: {71 initContainers: _.compact([deployWithSsl && {72 name: 'cpcfg',73 image: 'alpine:latest',74 command: ['/bin/sh', '-c', `mkdir -p /var/lib/postgresql/data/pgdata && cp /var/lib/postgresql/certman/tls.crt /var/lib/postgresql/data/pgdata/server.crt && cp /var/lib/postgresql/certman/tls.key /var/lib/postgresql/data/pgdata/server.key && chmod 0600 /var/lib/postgresql/data/pgdata/server.key && grep -qxF 'ssl = on' /var/lib/postgresql/data/pgdata/postgresql.conf || echo 'ssl = on' >> /var/lib/postgresql/data/pgdata/postgresql.conf75 `],76 volumeMounts,77 }]),78 containers: [79 {80 envFrom: [81 {82 secretRef: {83 name84 }85 }86 ],87 env: [88 {89 name: 'POSTGRES_USER',90 value: 'postgres'91 },92 {93 name: 'POSTGRES_DB',94 value: 'postgres'95 },96 {97 name: 'PGDATA',98 value: '/var/lib/postgresql/data/pgdata'99 }100 ],101 image,102 // command: ['sleep', '99999'],103 name: 'postgres',104 volumeMounts105 }106 ],107 volumes108 }109 }110 }111 }113}115export const pgSvcPort = 5432 // careful about changing117export const createPgDbFromQs = async ({118 sizeGb, qsName, action, dbType, cluster_name: notClusterInfoName,119 pvcNameOffset='',120}: {sizeGb: number, qsName: string, action: string, dbType?: string, cluster_name?: string, pvcNameOffset?: string}) => {122 let {nodePort, cluster_name, password: POSTGRES_PASSWORD, svcName: name,123 hostname,124 enableSsl,125 } = await decomposeQsFromSec(qsName as import('../serverF/secretsF/getPlainSecAI.mts').secretNameType)127 cluster_name ||= notClusterInfoName!129 const certName = name + '-cert'130 const cert = genericCert({name: certName, commonName: hostname})132 let isCertReady = false133 if (action == 'apply' && enableSsl) {134 while (true) {135 const existingCert = await read2Resource({resource: cert, cluster_name})136 if (existingCert) {137 const {status: {conditions}} = existingCert as any138 isCertReady = conditions[0].type == 'Ready' && conditions[0].status == 'True'139 } else {140 await resourcesAction({resources: [cert], cluster_name, action})141 }142 if (isCertReady) break143 await debug1Sleep(10 * 1000, `waiting for issuance of cert ${certName}..`)144 }145 }147 const pvcName = name + pvcNameOffset148 const pvcProps = {sizeGb, name: pvcName, cluster_name, isEncPv: true}149 const resources = _.compact([150 enableSsl && cert,151 secretTemplate({name, secretsH: {POSTGRES_PASSWORD}}),152 postgresDeploymentTemplate({name, cluster_name: cluster_name!, dbType, enableSsl, pvcName, isCertReady, certName}),153 genericNodePortTmpl({name, nodePort: nodePort!, svcPort: pgSvcPort}),154 ])155 const promises: Promise<unknown>[] = [156 kubeActionPvc({...pvcProps, action, cluster_name}),157 ]158 if (action != 'delpvcs') {159 promises.push(160 resourcesAction({resources, action, cluster_name}),161 )162 }164 await Promise.all(promises)165 return resources166}