3import * as _ from 'lodash-es' 19const clusterIssuerTmpl = ({name, email, cfApiKeySecretName, cluster_name}: {name: string, email: string, cfApiKeySecretName: string, cluster_name: string}) => { 21 apiVersion: 'cert-manager.io/v1', 22 kind: 'ClusterIssuer', 25 labels: {cluster_name} 30 privateKeySecretRef: { 33 server: 'https://acme-v02.api.letsencrypt.org/directory', 40 name: cfApiKeySecretName 52const wcClusterIssuerTmpl = ({name, email, cfApiKeySecretName, cluster_name}: {name: string, email: string, cfApiKeySecretName: string, cluster_name: string}) => { 54 apiVersion: 'cert-manager.io/v1', 55 kind: 'ClusterIssuer', 58 labels: {cluster_name}, 63 privateKeySecretRef: { 66 server: 'https://acme-v02.api.letsencrypt.org/directory', 73 name: cfApiKeySecretName, 85export const phasedApplyResources = async ({action, cluster_name, kustDir}: {action: string, cluster_name: string, kustDir: string}) => { 88 let resources = await getResources({path: kustDir, cluster_name}) as KubeResource[] 90 if (action == 'apply') { 91 const nsResA = _.filter(resources, ({kind}) => { 92 return kind == 'Namespace' 94 resources = _.difference(resources, nsResA) 98 const crdResA = _.filter(resources, ({kind}) => { 99 return kind == 'CustomResourceDefinition' 101 resources = _.difference(resources, crdResA) 109export const waitForCertManagerWebhook = async ({cluster_name}: {cluster_name: string}) => { 110 const webhookDeployRes = { 111 apiVersion: 'apps/v1', 113 metadata: { name: 'cert-manager-webhook', namespace: 'cert-manager' } 116 process.stdout.write('waiting for cert-manager-webhook to be ready') 118 predicate: async () => { 119 const deployment = await read2Resource({resource: webhookDeployRes, cluster_name}) 120 if (!deployment) return true // keep waiting 121 const {readyReplicas, replicas} = (deployment as {status?: {readyReplicas?: number, replicas?: number}}).status || {} 122 return !(readyReplicas && readyReplicas >= 1 && readyReplicas === replicas) 125 timeoutLabel: 'cert-manager-webhook ready', 127 console.log(' ready') 128 await sleep(3 * 1000) // extra buffer for webhook to fully initialize 131export const guardHasCfSecret = () => { 133 if (!cfApiKeySecretName) throPtErr('!cfApiKeySecretName') 138 filePath: secretsRelDir + '/' + cfApiKeySecretName, 139 helpText: `Please create with contents: 141 "CF_API_EMAIL": "email@domain.com", 142 "CF_API_KEY": "faketoken123abca39581a86ce7e6991f2d30" 148export const syncCertManagerCore = async ({kustDir}: {kustDir: string}) => { 150 cfApiKeySecretName, cluster_name, 154 const cfSecret = guardHasCfSecret() 156 const {CF_API_EMAIL: email} = cfSecret 158 const cfSecretTmpl = secretEnvTemplate({name: cfApiKeySecretName, kubeName: cfApiKeySecretName}) 159 _.set(cfSecretTmpl, 'metadata.namespace', 'cert-manager') 161 await phasedApplyResources({action, cluster_name, kustDir}) 163 if (action == 'apply') { 164 await waitForCertManagerWebhook({cluster_name}) 168 wcClusterIssuerTmpl({name: leIssuerName, cfApiKeySecretName, email, cluster_name}), 169 clusterIssuerTmpl({name: 'letsencrypt-prod', email, cfApiKeySecretName, cluster_name}),