cleanup k8s
parent
81ca1ad876
commit
d988a725e4
|
|
@ -1728,9 +1728,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|||
const k8s = __importStar(__webpack_require__(89679));
|
||||
const core = __importStar(__webpack_require__(42186));
|
||||
const kubernetes_storage_1 = __importDefault(__webpack_require__(43951));
|
||||
const kubernetes_logging_1 = __importDefault(__webpack_require__(68547));
|
||||
const kubernetes_task_runner_1 = __importDefault(__webpack_require__(7181));
|
||||
const kubernetes_secret_1 = __importDefault(__webpack_require__(71586));
|
||||
const kubernetes_utils_1 = __importDefault(__webpack_require__(96494));
|
||||
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
|
||||
const kubernetes_job_spec_factory_1 = __importDefault(__webpack_require__(1739));
|
||||
const kubernetes_service_account_1 = __importDefault(__webpack_require__(42915));
|
||||
|
|
@ -1786,11 +1785,11 @@ class Kubernetes {
|
|||
cloud_runner_logger_1.default.log('Creating build job');
|
||||
yield this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||
cloud_runner_logger_1.default.log('Job created');
|
||||
this.setPodNameAndContainerName(yield kubernetes_utils_1.default.findPodFromJob(this.kubeClient, this.jobName, this.namespace));
|
||||
this.setPodNameAndContainerName(yield Kubernetes.findPodFromJob(this.kubeClient, this.jobName, this.namespace));
|
||||
cloud_runner_logger_1.default.log('Watching pod until running');
|
||||
yield kubernetes_utils_1.default.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
||||
yield kubernetes_task_runner_1.default.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
||||
cloud_runner_logger_1.default.log('Pod running, streaming logs');
|
||||
yield kubernetes_logging_1.default.streamLogs(this.kubeConfig, this.kubeClient, this.jobName, this.podName, 'main', this.namespace, cloud_runner_logger_1.default.log);
|
||||
yield kubernetes_task_runner_1.default.runTask(this.kubeConfig, this.kubeClient, this.jobName, this.podName, 'main', this.namespace, cloud_runner_logger_1.default.log);
|
||||
yield this.cleanupTaskResources();
|
||||
}
|
||||
catch (error) {
|
||||
|
|
@ -1843,6 +1842,16 @@ class Kubernetes {
|
|||
yield this.kubeClient.deleteNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
|
||||
});
|
||||
}
|
||||
static findPodFromJob(kubeClient, jobName, namespace) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const namespacedPods = yield kubeClient.listNamespacedPod(namespace);
|
||||
const pod = namespacedPods.body.items.find((x) => { var _a, _b; return ((_b = (_a = x.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b['job-name']) === jobName; });
|
||||
if (pod === undefined) {
|
||||
throw new Error("pod with job-name label doesn't exist");
|
||||
}
|
||||
return pod;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.default = Kubernetes;
|
||||
|
||||
|
|
@ -1996,106 +2005,6 @@ class KubernetesJobSpecFactory {
|
|||
exports.default = KubernetesJobSpecFactory;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 68547:
|
||||
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const client_node_1 = __webpack_require__(89679);
|
||||
const stream_1 = __webpack_require__(92413);
|
||||
const cloud_runner_logger_1 = __importDefault(__webpack_require__(22855));
|
||||
const cloud_runner_state_1 = __webpack_require__(70912);
|
||||
const core = __importStar(__webpack_require__(42186));
|
||||
const fs_1 = __importDefault(__webpack_require__(35747));
|
||||
const cloud_runner_statics_1 = __webpack_require__(90828);
|
||||
class KubernetesLogging {
|
||||
static streamLogs(kubeConfig, kubeClient, jobName, podName, containerName, namespace, logCallback) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
cloud_runner_logger_1.default.log(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
|
||||
const stream = new stream_1.Writable();
|
||||
let didStreamAnyLogs = false;
|
||||
stream._write = (chunk, encoding, next) => {
|
||||
didStreamAnyLogs = true;
|
||||
let message = chunk.toString();
|
||||
message = `[${cloud_runner_statics_1.CloudRunnerStatics.logPrefix}] ${message}`;
|
||||
if (cloud_runner_state_1.CloudRunnerState.buildParams.logToFile) {
|
||||
fs_1.default.appendFileSync(`${cloud_runner_state_1.CloudRunnerState.buildGuid}-outputfile.txt`, `${message}\n`);
|
||||
}
|
||||
logCallback(message);
|
||||
next();
|
||||
};
|
||||
const logOptions = {
|
||||
follow: true,
|
||||
pretty: false,
|
||||
previous: false,
|
||||
};
|
||||
try {
|
||||
const resultError = yield new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { return new client_node_1.Log(kubeConfig).log(namespace, podName, containerName, stream, resolve, logOptions); }));
|
||||
if (resultError) {
|
||||
throw resultError;
|
||||
}
|
||||
if (!didStreamAnyLogs) {
|
||||
core.error('Failed to stream any logs, listing namespace events, check for an error with the container');
|
||||
core.error(JSON.stringify({
|
||||
events: (yield kubeClient.listNamespacedEvent(namespace)).body.items
|
||||
.filter((x) => {
|
||||
return x.involvedObject.name === podName || x.involvedObject.name === jobName;
|
||||
})
|
||||
.map((x) => {
|
||||
return {
|
||||
type: x.involvedObject.kind,
|
||||
name: x.involvedObject.name,
|
||||
message: x.message,
|
||||
};
|
||||
}),
|
||||
}, undefined, 4));
|
||||
throw new Error(`No logs streamed from k8s`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
throw error;
|
||||
}
|
||||
cloud_runner_logger_1.default.log('end of log stream');
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.default = KubernetesLogging;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 71586:
|
||||
|
|
@ -2354,11 +2263,30 @@ exports.default = KubernetesStorage;
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 96494:
|
||||
/***/ 7181:
|
||||
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
|
|
@ -2372,17 +2300,62 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
|
||||
const client_node_1 = __webpack_require__(89679);
|
||||
const stream_1 = __webpack_require__(92413);
|
||||
const cloud_runner_logger_1 = __importDefault(__webpack_require__(22855));
|
||||
class KubernetesUtilities {
|
||||
static findPodFromJob(kubeClient, jobName, namespace) {
|
||||
const cloud_runner_state_1 = __webpack_require__(70912);
|
||||
const core = __importStar(__webpack_require__(42186));
|
||||
const fs_1 = __importDefault(__webpack_require__(35747));
|
||||
const cloud_runner_statics_1 = __webpack_require__(90828);
|
||||
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
|
||||
class KubernetesTaskRunner {
|
||||
static runTask(kubeConfig, kubeClient, jobName, podName, containerName, namespace, logCallback) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const namespacedPods = yield kubeClient.listNamespacedPod(namespace);
|
||||
const pod = namespacedPods.body.items.find((x) => { var _a, _b; return ((_b = (_a = x.metadata) === null || _a === void 0 ? void 0 : _a.labels) === null || _b === void 0 ? void 0 : _b['job-name']) === jobName; });
|
||||
if (pod === undefined) {
|
||||
throw new Error("pod with job-name label doesn't exist");
|
||||
cloud_runner_logger_1.default.log(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
|
||||
const stream = new stream_1.Writable();
|
||||
let didStreamAnyLogs = false;
|
||||
stream._write = (chunk, encoding, next) => {
|
||||
didStreamAnyLogs = true;
|
||||
let message = chunk.toString();
|
||||
message = `[${cloud_runner_statics_1.CloudRunnerStatics.logPrefix}] ${message}`;
|
||||
if (cloud_runner_state_1.CloudRunnerState.buildParams.logToFile) {
|
||||
fs_1.default.appendFileSync(`${cloud_runner_state_1.CloudRunnerState.buildGuid}-outputfile.txt`, `${message}\n`);
|
||||
}
|
||||
logCallback(message);
|
||||
next();
|
||||
};
|
||||
const logOptions = {
|
||||
follow: true,
|
||||
pretty: false,
|
||||
previous: false,
|
||||
};
|
||||
try {
|
||||
const resultError = yield new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { return new client_node_1.Log(kubeConfig).log(namespace, podName, containerName, stream, resolve, logOptions); }));
|
||||
if (resultError) {
|
||||
throw resultError;
|
||||
}
|
||||
if (!didStreamAnyLogs) {
|
||||
core.error('Failed to stream any logs, listing namespace events, check for an error with the container');
|
||||
core.error(JSON.stringify({
|
||||
events: (yield kubeClient.listNamespacedEvent(namespace)).body.items
|
||||
.filter((x) => {
|
||||
return x.involvedObject.name === podName || x.involvedObject.name === jobName;
|
||||
})
|
||||
.map((x) => {
|
||||
return {
|
||||
type: x.involvedObject.kind,
|
||||
name: x.involvedObject.name,
|
||||
message: x.message,
|
||||
};
|
||||
}),
|
||||
}, undefined, 4));
|
||||
throw new Error(`No logs streamed from k8s`);
|
||||
}
|
||||
}
|
||||
return pod;
|
||||
catch (error) {
|
||||
throw error;
|
||||
}
|
||||
cloud_runner_logger_1.default.log('end of log stream');
|
||||
});
|
||||
}
|
||||
static watchUntilPodRunning(kubeClient, podName, namespace) {
|
||||
|
|
@ -2404,7 +2377,7 @@ class KubernetesUtilities {
|
|||
});
|
||||
}
|
||||
}
|
||||
exports.default = KubernetesUtilities;
|
||||
exports.default = KubernetesTaskRunner;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
|
@ -3247,8 +3220,7 @@ class ImageEnvironmentFactory {
|
|||
if (p.value === '' || p.value === undefined) {
|
||||
continue;
|
||||
}
|
||||
string += `--env ${p.name}="${p.value}" \
|
||||
`;
|
||||
string += `--env ${p.name}="${p.value}" `;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -5,13 +5,13 @@ import { CloudRunnerProviderInterface } from '../services/cloud-runner-provider-
|
|||
import CloudRunnerSecret from '../services/cloud-runner-secret';
|
||||
import KubernetesStorage from './kubernetes-storage';
|
||||
import CloudRunnerEnvironmentVariable from '../services/cloud-runner-environment-variable';
|
||||
import KubernetesLogging from './kubernetes-logging';
|
||||
import KubernetesTaskRunner from './kubernetes-task-runner';
|
||||
import KubernetesSecret from './kubernetes-secret';
|
||||
import KubernetesUtilities from './kubernetes-utils';
|
||||
import waitUntil from 'async-wait-until';
|
||||
import KubernetesJobSpecFactory from './kubernetes-job-spec-factory';
|
||||
import KubernetesServiceAccount from './kubernetes-service-account';
|
||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||
import { CoreV1Api } from '@kubernetes/client-node';
|
||||
|
||||
class Kubernetes implements CloudRunnerProviderInterface {
|
||||
private kubeConfig: k8s.KubeConfig;
|
||||
|
|
@ -99,13 +99,11 @@ class Kubernetes implements CloudRunnerProviderInterface {
|
|||
CloudRunnerLogger.log('Creating build job');
|
||||
await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||
CloudRunnerLogger.log('Job created');
|
||||
this.setPodNameAndContainerName(
|
||||
await KubernetesUtilities.findPodFromJob(this.kubeClient, this.jobName, this.namespace),
|
||||
);
|
||||
this.setPodNameAndContainerName(await Kubernetes.findPodFromJob(this.kubeClient, this.jobName, this.namespace));
|
||||
CloudRunnerLogger.log('Watching pod until running');
|
||||
await KubernetesUtilities.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
||||
await KubernetesTaskRunner.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
|
||||
CloudRunnerLogger.log('Pod running, streaming logs');
|
||||
await KubernetesLogging.streamLogs(
|
||||
await KubernetesTaskRunner.runTask(
|
||||
this.kubeConfig,
|
||||
this.kubeClient,
|
||||
this.jobName,
|
||||
|
|
@ -164,5 +162,13 @@ class Kubernetes implements CloudRunnerProviderInterface {
|
|||
) {
|
||||
await this.kubeClient.deleteNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
|
||||
}
|
||||
static async findPodFromJob(kubeClient: CoreV1Api, jobName: string, namespace: string) {
|
||||
const namespacedPods = await kubeClient.listNamespacedPod(namespace);
|
||||
const pod = namespacedPods.body.items.find((x) => x.metadata?.labels?.['job-name'] === jobName);
|
||||
if (pod === undefined) {
|
||||
throw new Error("pod with job-name label doesn't exist");
|
||||
}
|
||||
return pod;
|
||||
}
|
||||
}
|
||||
export default Kubernetes;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ import { CloudRunnerState } from '../state/cloud-runner-state';
|
|||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import { CloudRunnerStatics } from '../cloud-runner-statics';
|
||||
import waitUntil from 'async-wait-until';
|
||||
|
||||
class KubernetesLogging {
|
||||
static async streamLogs(
|
||||
class KubernetesTaskRunner {
|
||||
static async runTask(
|
||||
kubeConfig: KubeConfig,
|
||||
kubeClient: CoreV1Api,
|
||||
jobName: string,
|
||||
|
|
@ -69,6 +70,24 @@ class KubernetesLogging {
|
|||
}
|
||||
CloudRunnerLogger.log('end of log stream');
|
||||
}
|
||||
|
||||
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
|
||||
let success: boolean = false;
|
||||
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
|
||||
await waitUntil(
|
||||
async () => {
|
||||
const phase = (await kubeClient.readNamespacedPodStatus(podName, namespace))?.body.status?.phase;
|
||||
success = phase === 'Running';
|
||||
if (success || phase !== 'Pending') return true;
|
||||
return false;
|
||||
},
|
||||
{
|
||||
timeout: 500000,
|
||||
intervalBetweenAttempts: 15000,
|
||||
},
|
||||
);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesLogging;
|
||||
export default KubernetesTaskRunner;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { CoreV1Api } from '@kubernetes/client-node';
|
||||
import waitUntil from 'async-wait-until';
|
||||
import CloudRunnerLogger from '../services/cloud-runner-logger';
|
||||
|
||||
class KubernetesUtilities {
|
||||
static async findPodFromJob(kubeClient: CoreV1Api, jobName: string, namespace: string) {
|
||||
const namespacedPods = await kubeClient.listNamespacedPod(namespace);
|
||||
const pod = namespacedPods.body.items.find((x) => x.metadata?.labels?.['job-name'] === jobName);
|
||||
if (pod === undefined) {
|
||||
throw new Error("pod with job-name label doesn't exist");
|
||||
}
|
||||
return pod;
|
||||
}
|
||||
|
||||
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
|
||||
let success: boolean = false;
|
||||
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
|
||||
await waitUntil(
|
||||
async () => {
|
||||
const phase = (await kubeClient.readNamespacedPodStatus(podName, namespace))?.body.status?.phase;
|
||||
success = phase === 'Running';
|
||||
if (success || phase !== 'Pending') return true;
|
||||
return false;
|
||||
},
|
||||
{
|
||||
timeout: 500000,
|
||||
intervalBetweenAttempts: 15000,
|
||||
},
|
||||
);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
export default KubernetesUtilities;
|
||||
|
|
@ -11,8 +11,7 @@ class ImageEnvironmentFactory {
|
|||
if (p.value === '' || p.value === undefined) {
|
||||
continue;
|
||||
}
|
||||
string += `--env ${p.name}="${p.value}" \
|
||||
`;
|
||||
string += `--env ${p.name}="${p.value}" `;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue