unity-builder/src/model/cloud-runner/k8s/kubernetes-storage.ts

114 lines
3.7 KiB
TypeScript
Raw Normal View History

2021-06-18 19:52:07 +00:00
import waitUntil from 'async-wait-until';
import * as core from '@actions/core';
import * as k8s from '@kubernetes/client-node';
2021-09-22 20:05:21 +00:00
import BuildParameters from '../../build-parameters';
import CloudRunnerLogger from '../services/cloud-runner-logger';
2022-01-31 21:50:41 +00:00
import YAML from 'yaml';
2021-06-18 19:52:07 +00:00
class KubernetesStorage {
2021-06-18 20:12:06 +00:00
public static async createPersistentVolumeClaim(
buildParameters: BuildParameters,
pvcName: string,
kubeClient: k8s.CoreV1Api,
namespace: string,
) {
2021-06-18 19:52:07 +00:00
if (buildParameters.kubeVolume) {
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(buildParameters.kubeVolume);
2021-06-18 19:52:07 +00:00
pvcName = buildParameters.kubeVolume;
return;
}
2021-08-17 17:12:13 +00:00
const pvcList = (await kubeClient.listNamespacedPersistentVolumeClaim(namespace)).body.items.map(
(x) => x.metadata?.name,
);
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`Current PVCs in namespace ${namespace}`);
CloudRunnerLogger.log(JSON.stringify(pvcList, undefined, 4));
2021-08-20 03:19:00 +00:00
if (pvcList.includes(pvcName)) {
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`pvc ${pvcName} already exists`);
2021-08-17 17:12:13 +00:00
core.setOutput('volume', pvcName);
return;
}
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`Creating PVC ${pvcName} (does not exist)`);
2021-08-21 19:49:52 +00:00
const result = await KubernetesStorage.createPVC(pvcName, buildParameters, kubeClient, namespace);
await KubernetesStorage.handleResult(result, kubeClient, namespace, pvcName);
}
public static async getPVCPhase(kubeClient: k8s.CoreV1Api, name: string, namespace: string) {
2021-09-15 03:20:04 +00:00
try {
return (await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body.status?.phase;
} catch (error) {
core.error('Failed to get PVC phase');
core.error(JSON.stringify(error, undefined, 4));
throw error;
}
2021-08-21 19:49:52 +00:00
}
public static async watchUntilPVCNotPending(kubeClient: k8s.CoreV1Api, name: string, namespace: string) {
2021-09-15 03:20:04 +00:00
try {
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`watch Until PVC Not Pending ${name} ${namespace}`);
CloudRunnerLogger.log(`${await this.getPVCPhase(kubeClient, name, namespace)}`);
2021-09-15 03:20:04 +00:00
await waitUntil(
async () => {
return (await this.getPVCPhase(kubeClient, name, namespace)) !== 'Pending';
},
{
timeout: 500000,
intervalBetweenAttempts: 15000,
},
);
2022-01-31 21:50:41 +00:00
} catch (error: any) {
2021-09-15 03:20:04 +00:00
core.error('Failed to watch PVC');
2022-01-31 21:50:41 +00:00
core.error(error.toString());
2021-09-15 03:20:04 +00:00
core.error(
`PVC Body: ${JSON.stringify(
(await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body,
undefined,
4,
)}`,
);
throw error;
}
2021-08-21 19:49:52 +00:00
}
private static async createPVC(
pvcName: string,
buildParameters: BuildParameters,
kubeClient: k8s.CoreV1Api,
namespace: string,
) {
2021-06-18 19:52:07 +00:00
const pvc = new k8s.V1PersistentVolumeClaim();
pvc.apiVersion = 'v1';
pvc.kind = 'PersistentVolumeClaim';
pvc.metadata = {
name: pvcName,
};
pvc.spec = {
2021-09-08 20:21:15 +00:00
accessModes: ['ReadWriteOnce'],
2021-06-18 19:52:07 +00:00
resources: {
requests: {
storage: buildParameters.kubeVolumeSize,
},
},
};
2022-01-31 21:50:41 +00:00
if (process.env.K8S_PVC_SPEC) {
pvc.spec = YAML.parse(process.env.K8S_PVC_SPEC);
}
2021-06-18 22:55:48 +00:00
const result = await kubeClient.createNamespacedPersistentVolumeClaim(namespace, pvc);
2021-08-21 19:49:52 +00:00
return result;
}
private static async handleResult(
result: { response: import('http').IncomingMessage; body: k8s.V1PersistentVolumeClaim },
kubeClient: k8s.CoreV1Api,
namespace: string,
pvcName: string,
) {
2021-12-29 15:33:07 +00:00
const name = result.body.metadata?.name || '';
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`PVC ${name} created`);
2021-08-21 19:14:17 +00:00
await this.watchUntilPVCNotPending(kubeClient, name, namespace);
2021-09-21 18:27:04 +00:00
CloudRunnerLogger.log(`PVC ${name} is ready and not pending`);
core.setOutput('volume', pvcName);
2021-06-18 19:52:07 +00:00
}
}
export default KubernetesStorage;