UNPKG

kubernetes-smktest

Version:

Smoke Test apply for kubernetes clusters

439 lines (367 loc) 11.1 kB
const k8s = require("@kubernetes/client-node"); function converter(sentence) { let capitalized = []; let words = sentence.split(" "); //split the sentence into words words.forEach((word) => { let capitalizedWord = word.slice(0, 1).toUpperCase() + word.slice(1); //capitalize the first letter of every word capitalized.push(capitalizedWord); }); let converted = capitalized.join(" "); return converted; } module.exports = converter; module.exports.getKS = async function () { let k8sApi; try { // ! Use outside of cluster. const kc = new k8s.KubeConfig(); kc.loadFromDefault(); k8sApi = kc.makeApiClient(k8s.CoreV1Api); } catch (error) { // ! Use inside of cluster. k8sApi = k8s.Config.fromCluster(); } return k8sApi; }; module.exports.getPods = async function (nameSpace) { const k8sApi = await this.getKS(); let listNamespace = await k8sApi.listNamespacedPod(nameSpace); let dataPods = []; listNamespace.body.items.map((data) => { dataPods.push({ nameSpace: data.metadata.namespace, pod: data.metadata.name, clusterName: data.metadata.clusterName, service: data.metadata.labels.app, statusReady: data.status.containerStatuses[0].ready, "stateRestartCount:": data.status.containerStatuses[0].restartCount, statusStarted: data.status.containerStatuses[0].started, image: data.status.containerStatuses[0].image, lastState: { running: data.status.containerStatuses[0].lastState.running, terminated: data.status.containerStatuses[0].lastState.terminated, waiting: data.status.containerStatuses[0].lastState.waiting, }, state: data.status.containerStatuses[0].state, volumeName: data.spec.volumes, }); }); return dataPods; }; const ora = require("ora"); const Table = require("tty-table"); module.exports.getPodsData = async function (nameSpace) { //! This function get the pods state from kubectl get pods --namespace=edutelling-smktest command const k8sApi = await this.getKS(); let listNamespace = await k8sApi.listNamespacedPod(nameSpace); listNamespace = JSON.stringify(listNamespace.body); listNamespace = JSON.parse(listNamespace); listNamespace = listNamespace.items; let podsStatus = []; let passTest = true; let flag = true; for (const key in listNamespace) { let element = listNamespace[key]; if (element.status.phase !== "Running" && flag) { passTest = false; flag = false; } let passTest2 = true; if (element.status.phase !== "Running") { passTest2 = false; } let podsdata = { name: element.metadata.name, namespace: element.metadata.namespace, nodeName: element.spec.nodeName, volume: element.spec.volumes, podIP: element.status.hostIP, startTime: element.status.startTime, status: element.status.phase, passTest: String(passTest2), }; podsStatus.push(podsdata); } let data = { passTest: passTest, podsStatus: podsStatus, }; return data; }; module.exports.statusPods = async function (nameSpace) { let { passTest, podsStatus } = await this.getPodsData(nameSpace); //! Print table report: let header = [ { value: "nodeName", width: 15 }, { value: "namespace", width: 25, alias: "Namespace" }, { value: "name", width: 40, alias: "Name", align: "rigth" }, { value: "podIP", width: 20 }, { value: "status", width: 10, alias: "Status" }, { value: "startTime", width: 28, align: "rigth", alias: "Start Time" }, { alias: "Active", value: "passTest", width: 15, color: "red", formatter: function (value) { if (value === "true") { value = this.style(value, "bgGreen", "black"); } else { value = this.style(value, "bgRed", "white"); } return value; }, }, ]; let report = Table(header, podsStatus); return { passTest, podsStatus, report }; }; // Get logs state.... module.exports.logsState = async function (nameSpace) { // let { passTest, podsStatus } = await const k8sApi = await this.getKS(); let { passTest, podsStatus } = await this.getPodsData(nameSpace); logsList = []; passTestLogs = true; for (const key in podsStatus) { let dataJson; const element = podsStatus[key]; try { let list = await k8sApi.readNamespacedPodLog(element.name, nameSpace); let logs = list.response.body; try { logs = logs.substring(0, 100) + " ........... " + logs.substring(logs.length - 100, logs.length); } catch (error) { logs = ""; } dataJson = { name: element.name, status: "", logs: logs, reason: "", code: 200, passTest: "true", }; // logsList.push() } catch (error) { passTestLogs = false; dataJson = { name: String(element.name), status: error.response.body.status, logs: error.response.body.message, reason: error.response.body.reason, code: error.response.body.code, passTest: "false", }; } logsList.push(dataJson); } //! Genearate Table Logs Reports let header = [ { value: "name", width: 40, alias: "Name", align: "left" }, { value: "logs", width: 80, alias: "Logs", align: "left" }, { alias: "Logs Error", value: "passTest", align: "left", width: 15, color: "red", formatter: function (value) { if (value === "true") { value = this.style(value, "bgGreen", "black"); } else { value = this.style(value, "bgRed", "white"); } return value; }, }, ]; let report = Table(header, logsList); return { passTest: passTestLogs, logsStatus: logsList, report: report, }; }; //? IP address are alive const ping = require("ping"); // USE EXAMPLE: // let report = true; // this.ping("edutelling-smktest", report); module.exports.ping = async function (nameSpace) { const k8sApi = await this.getKS(); let listNamespace = await k8sApi.listNamespacedPod(nameSpace); listNamespace = JSON.stringify(listNamespace); listNamespace = JSON.parse(listNamespace); // console.log(listNamespace.body.items); let statusPingList = []; let passTest = true; let report; for (const key in listNamespace.body.items) { let data = listNamespace.body.items[key]; // console.log(data); let podsName = data.metadata.name; let podIP = data.status.podIP; let hostIP = data.status.hostIP; let hostIPisAlive = await ping.promise.probe(hostIP); hostIPisAlive = hostIPisAlive.alive; let podIPisAlive = await ping.promise.probe(podIP); podIPisAlive = podIPisAlive.alive; let podNameIsAlive = await ping.promise.probe(podsName); podNameIsAlive = podNameIsAlive.alive; let status = { podName: podsName, podNameIsAlive: String(podNameIsAlive), hostIP: hostIP, hostIPisAlive: String(hostIPisAlive), podIP: podIP, podIPisAlive: String(podIPisAlive), }; statusPingList.push(status); //! General PassTest if (!podNameIsAlive || !hostIPisAlive || !podIPisAlive) { passTest = false; } } //! Print Reports. //! Generate Table: let header = [ { value: "podName", width: 40 }, { alias: "IsAlive", value: "podNameIsAlive", width: 10, color: "red", formatter: function (value) { if (value === "true") { value = this.style(value.toString(), "bgGreen", "black"); } else { value = this.style(value.toString(), "bgRed", "white"); } return value; }, }, { value: "hostIP", width: 25 }, { alias: "IsAlive", value: "hostIPisAlive", width: 10, color: "red", formatter: function (value) { if (value === "true") { value = this.style(value.toString(), "bgGreen", "black"); } else { value = this.style(value.toString(), "bgRed", "white"); } return value; }, }, { value: "podIP", width: 25 }, { alias: "IsAlive", value: "podIPisAlive", width: 10, color: "red", formatter: function (value) { if (value === "true") { value = this.style(value.toString(), "bgGreen", "black"); } else { value = this.style(value.toString(), "bgRed", "white"); } return value; }, }, ]; report = Table(header, statusPingList); return { passTest, statusPingList, report, }; }; //! SMOKE TEST APPLY TO KUBECTL CLUSTER: async function createNamespace(k8sApi) { var namespace = { metadata: { name: "smoke-test-temp-env-01", }, }; let statusCode; return k8sApi.createNamespace(namespace).then( function (response) { // console.log("Created namespace"); // console.log(response); return k8sApi.readNamespace(namespace.metadata.name).then((response) => { // console.log(response.response.statusCode); k8sApi.deleteNamespace( namespace.metadata.name, {} /* delete options */ ); return response.response.statusCode; }); }, (err) => { console.log("Error!: " + err); return 402; } ); } module.exports.createNamespaceTest = async function () { // const k8sApi = await this.getKS(); let statusCode = await Promise.resolve(createNamespace(k8sApi)); let passTest = false; if (statusCode === 200) { passTest = true; } return passTest; }; async function createSecret(k8sApi) { var namespace = { metadata: { name: "smoke-test-temp-env", // namespace: "smoke-test-temp-env", }, }; return k8sApi.createNamespace(namespace).then( function (response) { console.log("Created namespace"); // console.log(response); return k8sApi .readNamespace(namespace.metadata.name) .then(async (response) => { //? (1): Create namespace. let secretData = await k8sApi .createNamespacedSecret(namespace.metadata.name, { apiVersion: "v1", kind: "Secret", name: "secret-smoke-test-temp", metadata: { name: "secret-smoke-test-temp" }, }) .catch((e) => console.log(e)); //? (2): Create example. k8sApi.deleteNamespace( namespace.metadata.name, {} /* delete options */ ); return secretData.response.statusCode; }); }, (err) => { console.log("Error!: " + err); return 402; } ); } module.exports.createSecretTest = async function () { const k8sApi = await this.getKS(); let statusCode = await Promise.resolve(createSecret(k8sApi)); let passTest = false; if (statusCode === 200 || statusCode === 201) { passTest = true; } return passTest; };