4import * as _ from 'lodash-es' 15import { spawnSync } from 'child_process' 24 peertubeImage, peertubePort, redisImage, redisName, redisPort, 25 peertubeUid, storageSizeGb, 28type EptPeertubeProps = { 34const name = 'peertube' 35const ptSecretName = tsSec('peertube-appsecret') 37export const eptPeertube = async ({hostname, adminEmail, instanceName}: EptPeertubeProps) => { 40 appCfgCtx.enterWith({...getAppCfg(), name, dbQsCfg: {dbQsName: `${name}_qs`}}) 45 const {volumes: dataVols, volumeMounts: dataMnts} = pvcVolumeMounts({name, mountPath: '/data'}) 47 const ingressAnnotH = { 48 'nginx.ingress.kubernetes.io/proxy-body-size': '0', 49 'nginx.ingress.kubernetes.io/proxy-read-timeout': '3600', 50 'nginx.ingress.kubernetes.io/proxy-send-timeout': '3600', 55 strategy: {type: 'Recreate'}, 58 name: 'fix-permissions', 60 command: ['sh', '-c', `chown -R ${peertubeUid}:${peertubeUid} /data`], 61 volumeMounts: dataMnts, 64 name, image: peertubeImage, 65 ports: [{containerPort: peertubePort}], 66 volumeMounts: dataMnts, 68 preStop: { exec: { command: ['sh', '-c', 'sleep 10'] } }, 71 httpGet: {path: '/api/v1/config', port: peertubePort}, 72 failureThreshold: 36, periodSeconds: 10, 75 httpGet: {path: '/api/v1/config', port: peertubePort}, 79 PEERTUBE_WEBSERVER_HOSTNAME: hostname, 80 PEERTUBE_WEBSERVER_HTTPS: 'true', 81 PEERTUBE_DB_HOSTNAME: `${name}-rw.default`, 82 PEERTUBE_DB_PORT: '5432', 83 PEERTUBE_DB_USERNAME: 'app', 84 PEERTUBE_DB_NAME: 'app', 85 PEERTUBE_DB_SSL: 'false', 86 PEERTUBE_DB_PASSWORD: {secretKeyRef: {name: `${name}-app`, key: 'password'}}, 87 PEERTUBE_REDIS_HOSTNAME: redisName, 88 PEERTUBE_REDIS_PORT: String(redisPort), 89 PEERTUBE_SECRET: {secretKeyRef: {name: `${name}-secret`, key: ptSecretName}}, 90 PEERTUBE_ADMIN_EMAIL: adminEmail, 91 PEERTUBE_INSTANCE_NAME: instanceName, 92 UV_THREADPOOL_SIZE: '128', 97 const resources = _.compact([ 101 strategy: {type: 'Recreate'}, 102 volumes: [{name: 'redis-data', emptyDir: {}}], 104 name: redisName, image: redisImage, 105 volumeMounts: [{name: 'redis-data', mountPath: '/data'}], 119 if (action === 'apply') { 121 if (rootPw) await ensureRootPw({cluster_name, rootPw}) 124 if (_.includes(['info', 'apply'], action)) { 127 betLog({url: `https://${hostname}`, login: 'root', rootPw: rootPwVal, adminEmail, dbEp: dbEps[0]?.regEpPath}) 131const ensureRootPw = async ({cluster_name, rootPw}: {cluster_name: string, rootPw: string}) => { 133 const kubeEnv = {...process.env, KUBECONFIG: kubeConfigPath} 135 if (!podName) { betLog('peertube pod not found, skip rootPw set'); return } 137 for (let i = 0; i < 36; i++) { 138 const probe = spawnSync('kubectl', ['exec', podName, '--', 'curl', '-sf', 'http://localhost:9000/api/v1/config'], 139 {encoding: 'utf-8', env: kubeEnv, stdio: 'pipe'}) 140 if (probe.status === 0) break 141 if (i === 35) { betLog('peertube not ready, skip rootPw set'); return } 145 const result = spawnSync('kubectl', ['exec', '-i', podName, '--', 'npm', 'run', 'reset-password', '--', '-u', 'root'], 146 {input: `${rootPw}\n${rootPw}\n`, encoding: 'utf-8', env: kubeEnv, timeout: 30_000}) 148 if (result.status === 0) { 151 betLog('!rootPw set failed — password is in data/secrets2/peertube-rootpassword for manual reset')