diff --git a/packages/k8s/package-lock.json b/packages/k8s/package-lock.json index 4116517..4b1cf67 100644 --- a/packages/k8s/package-lock.json +++ b/packages/k8s/package-lock.json @@ -15,7 +15,8 @@ "@kubernetes/client-node": "^1.1.2", "hooklib": "file:../hooklib", "js-yaml": "^4.1.0", - "shlex": "^2.1.2" + "shlex": "^2.1.2", + "uuid": "^11.1.0" }, "devDependencies": { "@types/jest": "^27.4.1", @@ -4868,6 +4869,19 @@ "requires-port": "^1.0.0" } }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", diff --git a/packages/k8s/package.json b/packages/k8s/package.json index 4a176c1..115c9d4 100644 --- a/packages/k8s/package.json +++ b/packages/k8s/package.json @@ -19,7 +19,8 @@ "@kubernetes/client-node": "^1.1.2", "hooklib": "file:../hooklib", "js-yaml": "^4.1.0", - "shlex": "^2.1.2" + "shlex": "^2.1.2", + "uuid": "^11.1.0" }, "devDependencies": { "@types/jest": "^27.4.1", diff --git a/packages/k8s/src/k8s/index.ts b/packages/k8s/src/k8s/index.ts index 021b383..70c3a47 100644 --- a/packages/k8s/src/k8s/index.ts +++ b/packages/k8s/src/k8s/index.ts @@ -127,8 +127,10 @@ export async function createPod( mergePodSpecWithOptions(appPod.spec, extension.spec) } - const { body } = await k8sApi.createNamespacedPod(namespace(), appPod) - return body + return await k8sApi.createNamespacedPod({ + namespace: namespace(), + body: appPod + }) } export async function createJob( @@ -183,46 +185,41 @@ export async function createJob( } } - const { body } = await k8sBatchV1Api.createNamespacedJob(namespace(), job) - return body + return await k8sBatchV1Api.createNamespacedJob({ + namespace: namespace(), + body: job + }) } export async function getContainerJobPodName(jobName: string): Promise { const selector = `job-name=${jobName}` const backOffManager = new BackOffManager(60) while (true) { - const podList = await k8sApi.listNamespacedPod( - namespace(), - undefined, - undefined, - undefined, - undefined, - selector, - 1 - ) - - if (!podList.body.items?.length) { + const podList = await k8sApi.listNamespacedPod({ + namespace: namespace(), + labelSelector: selector, + limit: 1 + }) + if (!podList.items?.length) { await backOffManager.backOff() continue } - if (!podList.body.items[0].metadata?.name) { + if (!podList.items[0].metadata?.name) { throw new Error( `Failed to determine the name of the pod for job ${jobName}` ) } - return podList.body.items[0].metadata.name + return podList.items[0].metadata.name } } export async function deletePod(podName: string): Promise { - await k8sApi.deleteNamespacedPod( - podName, - namespace(), - undefined, - undefined, - 0 - ) + await k8sApi.deleteNamespacedPod({ + name: podName, + namespace: namespace(), + gracePeriodSeconds: 0 + }) } export async function execPodStep( @@ -315,8 +312,10 @@ export async function createDockerSecret( ) } - const { body } = await k8sApi.createNamespacedSecret(namespace(), secret) - return body + return await k8sApi.createNamespacedSecret({ + namespace: namespace(), + body: secret + }) } export async function createSecretForEnvs(envs: { @@ -340,29 +339,28 @@ export async function createSecretForEnvs(envs: { secret.data[key] = Buffer.from(value).toString('base64') } - await k8sApi.createNamespacedSecret(namespace(), secret) + await k8sApi.createNamespacedSecret({ namespace: namespace(), body: secret }) return secretName } export async function deleteSecret(secretName: string): Promise { - await k8sApi.deleteNamespacedSecret(secretName, namespace()) + await k8sApi.deleteNamespacedSecret({ + name: secretName, + namespace: namespace() + }) } export async function pruneSecrets(): Promise { - const secretList = await k8sApi.listNamespacedSecret( - namespace(), - undefined, - undefined, - undefined, - undefined, - new RunnerInstanceLabel().toString() - ) - if (!secretList.body.items.length) { + const secretList = await k8sApi.listNamespacedSecret({ + namespace: namespace(), + labelSelector: new RunnerInstanceLabel().toString() + }) + if (!secretList.items.length) { return } await Promise.all( - secretList.body.items.map( + secretList.items.map( secret => secret.metadata?.name && deleteSecret(secret.metadata.name) ) ) @@ -422,8 +420,10 @@ async function getPodPhase(podName: string): Promise { PodPhase.FAILED, PodPhase.UNKNOWN ]) - const { body } = await k8sApi.readNamespacedPod(podName, namespace()) - const pod = body + const pod = await k8sApi.readNamespacedPod({ + name: podName, + namespace: namespace() + }) if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) { return PodPhase.UNKNOWN @@ -432,8 +432,10 @@ async function getPodPhase(podName: string): Promise { } async function isJobSucceeded(jobName: string): Promise { - const { body } = await k8sBatchV1Api.readNamespacedJob(jobName, namespace()) - const job = body + const job = await k8sBatchV1Api.readNamespacedJob({ + name: jobName, + namespace: namespace() + }) if (job.status?.failed) { throw new Error(`job ${jobName} has failed`) } @@ -455,47 +457,43 @@ export async function getPodLogs( process.stderr.write(err.message) }) - const r = await log.log(namespace(), podName, containerName, logStream, { + + await log.log(namespace(), podName, containerName, logStream, { follow: true, pretty: false, timestamps: false }) - await new Promise(resolve => r.on('close', () => resolve(null))) + + await new Promise(resolve => logStream.on('close', resolve)) } export async function prunePods(): Promise { - const podList = await k8sApi.listNamespacedPod( - namespace(), - undefined, - undefined, - undefined, - undefined, - new RunnerInstanceLabel().toString() - ) - if (!podList.body.items.length) { + const podList = await k8sApi.listNamespacedPod({ + namespace: namespace(), + labelSelector: new RunnerInstanceLabel().toString() + }) + if (!podList.items.length) { return } await Promise.all( - podList.body.items.map( - pod => pod.metadata?.name && deletePod(pod.metadata.name) - ) + podList.items.map(pod => pod.metadata?.name && deletePod(pod.metadata.name)) ) } export async function getPodStatus( name: string ): Promise { - const { body } = await k8sApi.readNamespacedPod(name, namespace()) - return body.status + const { status } = await k8sApi.readNamespacedPod({ + name, + namespace: namespace() + }) + return status } export async function isAuthPermissionsOK(): Promise { const sar = new k8s.V1SelfSubjectAccessReview() - const asyncs: Promise<{ - response: unknown - body: k8s.V1SelfSubjectAccessReview - }>[] = [] + const asyncs: Promise[] = [] for (const resource of requiredPermissions) { for (const verb of resource.verbs) { sar.spec = new k8s.V1SelfSubjectAccessReviewSpec() @@ -505,11 +503,13 @@ export async function isAuthPermissionsOK(): Promise { sar.spec.resourceAttributes.group = resource.group sar.spec.resourceAttributes.resource = resource.resource sar.spec.resourceAttributes.subresource = resource.subresource - asyncs.push(k8sAuthorizationV1Api.createSelfSubjectAccessReview(sar)) + asyncs.push( + k8sAuthorizationV1Api.createSelfSubjectAccessReview({ body: sar }) + ) } } const responses = await Promise.all(asyncs) - return responses.every(resp => resp.body.status?.allowed) + return responses.every(resp => resp.status?.allowed) } export async function isPodContainerAlpine( @@ -535,9 +535,12 @@ export async function isPodContainerAlpine( } async function getCurrentNodeName(): Promise { - const resp = await k8sApi.readNamespacedPod(getRunnerPodName(), namespace()) + const resp = await k8sApi.readNamespacedPod({ + name: getRunnerPodName(), + namespace: namespace() + }) - const nodeName = resp.body.spec?.nodeName + const nodeName = resp.spec?.nodeName if (!nodeName) { throw new Error('Failed to determine node name') } @@ -647,6 +650,8 @@ export function containerPorts( } export async function getPodByName(name): Promise { - const { body } = await k8sApi.readNamespacedPod(name, namespace()) - return body + return await k8sApi.readNamespacedPod({ + name, + namespace: namespace() + }) }