-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkubectl.js
92 lines (77 loc) · 3.19 KB
/
kubectl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const path = require("path");
const {
docker,
} = require("@kaholo/plugin-library");
const {
generateRandomString,
convertCertificateToBase64,
} = require("./helpers");
const KUBECTL_IMAGE_NAME = "bitnami/kubectl";
const environmentalVariablesNames = {
kubeCertificate: "KUBE_CERT",
kubeToken: "KUBE_TOKEN",
kubeApiServer: "KUBE_API_SERVER",
namespace: "KUBE_NAMESPACE",
};
async function runCommand(params) {
const {
kubeCertificate,
kubeToken,
kubeApiServer,
command: usersCommand,
namespace,
} = params;
const base64Certificate = convertCertificateToBase64(kubeCertificate);
const shellEnvironmentalVariables = {};
shellEnvironmentalVariables[environmentalVariablesNames.kubeCertificate] = base64Certificate;
shellEnvironmentalVariables[environmentalVariablesNames.kubeToken] = kubeToken;
shellEnvironmentalVariables[environmentalVariablesNames.kubeApiServer] = kubeApiServer;
if (namespace) {
shellEnvironmentalVariables[environmentalVariablesNames.namespace] = namespace;
}
const clusterName = `cluster_${generateRandomString()}`;
const userName = `user_${generateRandomString()}`;
const contextName = `context_${generateRandomString()}`;
const workingDirectoryVolumeDefinition = docker.createVolumeDefinition(path.resolve("./"));
// eslint-disable-next-line max-len
shellEnvironmentalVariables[workingDirectoryVolumeDefinition.path.name] = workingDirectoryVolumeDefinition.path.value;
// eslint-disable-next-line max-len
shellEnvironmentalVariables[workingDirectoryVolumeDefinition.mountPoint.name] = workingDirectoryVolumeDefinition.mountPoint.value;
// TODO Check if KUBECONFIG is set and reuse it if it is
const namespaceParam = namespace ? `--namespace=$${environmentalVariablesNames.namespace}` : "";
// First command doesn't need kubectl prefix
const aggregatedCommand = `\
sh -c "\
kubectl config set-cluster ${clusterName} --server=$${environmentalVariablesNames.kubeApiServer} >/dev/null && \
kubectl config set clusters.${clusterName}.certificate-authority-data $${environmentalVariablesNames.kubeCertificate} >/dev/null && \
kubectl config set-context ${contextName} --cluster=${clusterName} --user=${userName} ${namespaceParam} >/dev/null && \
kubectl config set current-context ${contextName} >/dev/null && \
kubectl config set-credentials ${userName} --token=$${environmentalVariablesNames.kubeToken} >/dev/null && \
${sanitizeCommand(usersCommand)}\
"`;
const dockerCommand = docker.buildDockerCommand({
command: aggregatedCommand,
image: KUBECTL_IMAGE_NAME,
additionalArguments: ["--entrypoint", "\"\""], // ignores default entrypoint and allows to call any command
volumeDefinitionsArray: [workingDirectoryVolumeDefinition],
workingDirectory: `$${workingDirectoryVolumeDefinition.mountPoint.name}`,
});
const {
stdout,
stderr,
} = await exec(dockerCommand, {
env: shellEnvironmentalVariables,
});
if (stderr && !stdout) {
throw stderr;
}
return stdout;
}
function sanitizeCommand(command) {
return command.startsWith("kubectl") ? command : `kubectl ${command}`;
}
module.exports = {
runCommand,
};