kubernetes-smktest
Version:
Smoke Test apply for kubernetes clusters
439 lines (367 loc) • 11.1 kB
JavaScript
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;
};