fix errors and bump client node to stable version

This commit is contained in:
Nikola Jokic
2025-04-15 14:53:21 +02:00
parent ff583c8917
commit a7349e7d70
3 changed files with 90 additions and 70 deletions

View File

@@ -15,7 +15,8 @@
"@kubernetes/client-node": "^1.1.2", "@kubernetes/client-node": "^1.1.2",
"hooklib": "file:../hooklib", "hooklib": "file:../hooklib",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"shlex": "^2.1.2" "shlex": "^2.1.2",
"uuid": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.4.1", "@types/jest": "^27.4.1",
@@ -4868,6 +4869,19 @@
"requires-port": "^1.0.0" "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": { "node_modules/v8-to-istanbul": {
"version": "8.1.1", "version": "8.1.1",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz",

View File

@@ -19,7 +19,8 @@
"@kubernetes/client-node": "^1.1.2", "@kubernetes/client-node": "^1.1.2",
"hooklib": "file:../hooklib", "hooklib": "file:../hooklib",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"shlex": "^2.1.2" "shlex": "^2.1.2",
"uuid": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.4.1", "@types/jest": "^27.4.1",

View File

@@ -127,8 +127,10 @@ export async function createPod(
mergePodSpecWithOptions(appPod.spec, extension.spec) mergePodSpecWithOptions(appPod.spec, extension.spec)
} }
const { body } = await k8sApi.createNamespacedPod(namespace(), appPod) return await k8sApi.createNamespacedPod({
return body namespace: namespace(),
body: appPod
})
} }
export async function createJob( export async function createJob(
@@ -183,46 +185,41 @@ export async function createJob(
} }
} }
const { body } = await k8sBatchV1Api.createNamespacedJob(namespace(), job) return await k8sBatchV1Api.createNamespacedJob({
return body namespace: namespace(),
body: job
})
} }
export async function getContainerJobPodName(jobName: string): Promise<string> { export async function getContainerJobPodName(jobName: string): Promise<string> {
const selector = `job-name=${jobName}` const selector = `job-name=${jobName}`
const backOffManager = new BackOffManager(60) const backOffManager = new BackOffManager(60)
while (true) { while (true) {
const podList = await k8sApi.listNamespacedPod( const podList = await k8sApi.listNamespacedPod({
namespace(), namespace: namespace(),
undefined, labelSelector: selector,
undefined, limit: 1
undefined, })
undefined, if (!podList.items?.length) {
selector,
1
)
if (!podList.body.items?.length) {
await backOffManager.backOff() await backOffManager.backOff()
continue continue
} }
if (!podList.body.items[0].metadata?.name) { if (!podList.items[0].metadata?.name) {
throw new Error( throw new Error(
`Failed to determine the name of the pod for job ${jobName}` `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<void> { export async function deletePod(podName: string): Promise<void> {
await k8sApi.deleteNamespacedPod( await k8sApi.deleteNamespacedPod({
podName, name: podName,
namespace(), namespace: namespace(),
undefined, gracePeriodSeconds: 0
undefined, })
0
)
} }
export async function execPodStep( export async function execPodStep(
@@ -315,8 +312,10 @@ export async function createDockerSecret(
) )
} }
const { body } = await k8sApi.createNamespacedSecret(namespace(), secret) return await k8sApi.createNamespacedSecret({
return body namespace: namespace(),
body: secret
})
} }
export async function createSecretForEnvs(envs: { export async function createSecretForEnvs(envs: {
@@ -340,29 +339,28 @@ export async function createSecretForEnvs(envs: {
secret.data[key] = Buffer.from(value).toString('base64') secret.data[key] = Buffer.from(value).toString('base64')
} }
await k8sApi.createNamespacedSecret(namespace(), secret) await k8sApi.createNamespacedSecret({ namespace: namespace(), body: secret })
return secretName return secretName
} }
export async function deleteSecret(secretName: string): Promise<void> { export async function deleteSecret(secretName: string): Promise<void> {
await k8sApi.deleteNamespacedSecret(secretName, namespace()) await k8sApi.deleteNamespacedSecret({
name: secretName,
namespace: namespace()
})
} }
export async function pruneSecrets(): Promise<void> { export async function pruneSecrets(): Promise<void> {
const secretList = await k8sApi.listNamespacedSecret( const secretList = await k8sApi.listNamespacedSecret({
namespace(), namespace: namespace(),
undefined, labelSelector: new RunnerInstanceLabel().toString()
undefined, })
undefined, if (!secretList.items.length) {
undefined,
new RunnerInstanceLabel().toString()
)
if (!secretList.body.items.length) {
return return
} }
await Promise.all( await Promise.all(
secretList.body.items.map( secretList.items.map(
secret => secret.metadata?.name && deleteSecret(secret.metadata.name) secret => secret.metadata?.name && deleteSecret(secret.metadata.name)
) )
) )
@@ -422,8 +420,10 @@ async function getPodPhase(podName: string): Promise<PodPhase> {
PodPhase.FAILED, PodPhase.FAILED,
PodPhase.UNKNOWN PodPhase.UNKNOWN
]) ])
const { body } = await k8sApi.readNamespacedPod(podName, namespace()) const pod = await k8sApi.readNamespacedPod({
const pod = body name: podName,
namespace: namespace()
})
if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) { if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) {
return PodPhase.UNKNOWN return PodPhase.UNKNOWN
@@ -432,8 +432,10 @@ async function getPodPhase(podName: string): Promise<PodPhase> {
} }
async function isJobSucceeded(jobName: string): Promise<boolean> { async function isJobSucceeded(jobName: string): Promise<boolean> {
const { body } = await k8sBatchV1Api.readNamespacedJob(jobName, namespace()) const job = await k8sBatchV1Api.readNamespacedJob({
const job = body name: jobName,
namespace: namespace()
})
if (job.status?.failed) { if (job.status?.failed) {
throw new Error(`job ${jobName} has failed`) throw new Error(`job ${jobName} has failed`)
} }
@@ -455,47 +457,43 @@ export async function getPodLogs(
process.stderr.write(err.message) process.stderr.write(err.message)
}) })
const r = await log.log(namespace(), podName, containerName, logStream, {
await log.log(namespace(), podName, containerName, logStream, {
follow: true, follow: true,
pretty: false, pretty: false,
timestamps: 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<void> { export async function prunePods(): Promise<void> {
const podList = await k8sApi.listNamespacedPod( const podList = await k8sApi.listNamespacedPod({
namespace(), namespace: namespace(),
undefined, labelSelector: new RunnerInstanceLabel().toString()
undefined, })
undefined, if (!podList.items.length) {
undefined,
new RunnerInstanceLabel().toString()
)
if (!podList.body.items.length) {
return return
} }
await Promise.all( await Promise.all(
podList.body.items.map( podList.items.map(pod => pod.metadata?.name && deletePod(pod.metadata.name))
pod => pod.metadata?.name && deletePod(pod.metadata.name)
)
) )
} }
export async function getPodStatus( export async function getPodStatus(
name: string name: string
): Promise<k8s.V1PodStatus | undefined> { ): Promise<k8s.V1PodStatus | undefined> {
const { body } = await k8sApi.readNamespacedPod(name, namespace()) const { status } = await k8sApi.readNamespacedPod({
return body.status name,
namespace: namespace()
})
return status
} }
export async function isAuthPermissionsOK(): Promise<boolean> { export async function isAuthPermissionsOK(): Promise<boolean> {
const sar = new k8s.V1SelfSubjectAccessReview() const sar = new k8s.V1SelfSubjectAccessReview()
const asyncs: Promise<{ const asyncs: Promise<k8s.V1SelfSubjectAccessReview>[] = []
response: unknown
body: k8s.V1SelfSubjectAccessReview
}>[] = []
for (const resource of requiredPermissions) { for (const resource of requiredPermissions) {
for (const verb of resource.verbs) { for (const verb of resource.verbs) {
sar.spec = new k8s.V1SelfSubjectAccessReviewSpec() sar.spec = new k8s.V1SelfSubjectAccessReviewSpec()
@@ -505,11 +503,13 @@ export async function isAuthPermissionsOK(): Promise<boolean> {
sar.spec.resourceAttributes.group = resource.group sar.spec.resourceAttributes.group = resource.group
sar.spec.resourceAttributes.resource = resource.resource sar.spec.resourceAttributes.resource = resource.resource
sar.spec.resourceAttributes.subresource = resource.subresource sar.spec.resourceAttributes.subresource = resource.subresource
asyncs.push(k8sAuthorizationV1Api.createSelfSubjectAccessReview(sar)) asyncs.push(
k8sAuthorizationV1Api.createSelfSubjectAccessReview({ body: sar })
)
} }
} }
const responses = await Promise.all(asyncs) 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( export async function isPodContainerAlpine(
@@ -535,9 +535,12 @@ export async function isPodContainerAlpine(
} }
async function getCurrentNodeName(): Promise<string> { async function getCurrentNodeName(): Promise<string> {
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) { if (!nodeName) {
throw new Error('Failed to determine node name') throw new Error('Failed to determine node name')
} }
@@ -647,6 +650,8 @@ export function containerPorts(
} }
export async function getPodByName(name): Promise<k8s.V1Pod> { export async function getPodByName(name): Promise<k8s.V1Pod> {
const { body } = await k8sApi.readNamespacedPod(name, namespace()) return await k8sApi.readNamespacedPod({
return body name,
namespace: namespace()
})
} }