From 3bd6d361e9a868b39ec58cc2ea29335ea986304e Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed <fawzi.mohamed@fhi-berlin.mpg.de> Date: Wed, 24 Oct 2018 12:02:11 +0200 Subject: [PATCH] update kubernetes-client to latest (6.3.0) callback -> promises always return request with result in the body attributes --- app/k8-data.js | 133 ++++++++++++++++++++++--------------------- app/kubernetes.js | 11 ++-- app/routes.js | 65 ++++++++++----------- config/default.hjson | 1 + deploy.sh | 26 +++++---- package.json | 2 +- repl.js | 7 +-- 7 files changed, 124 insertions(+), 121 deletions(-) diff --git a/app/k8-data.js b/app/k8-data.js index 3478373..30c86dd 100644 --- a/app/k8-data.js +++ b/app/k8-data.js @@ -16,6 +16,7 @@ const resolveCache = require('../safe-memory-cache/map.js')({ }) // gets pods with the given labels +// returns the raw response function getPods(labels, next) { let selector = "" let first = true @@ -26,7 +27,7 @@ function getPods(labels, next) { selector += ',' selector += `${k}=${labels[k]}` } - k8.ns(config.k8component.namespace).pods.get({ qs: { labelSelector: selector } }, next) + k8.api.v1.ns(config.k8component.namespace).pods.get({ qs: { labelSelector: selector } }).then(function(data){ next(null, data); }, function(err){ next(err, null) }) } // gets json api formatted pods @@ -36,7 +37,7 @@ function jsonApiPods(labels, next, {details = true}={}) { if (err) { next(err, []) } else { - let podList = pods.items + let podList = pods.body.items if (podList) podList = podList.map(function(pod){ let secondsSinceCreation = (Date.now() - Date.parse(pod.metadata.creationTimestamp))/ 1000.0 @@ -88,6 +89,8 @@ function jsonApiPods(labels, next, {details = true}={}) { podInfo.attributes.data = pod return podInfo }) + else + podList=[] next(null, podList) } }) @@ -153,14 +156,12 @@ function createPod(podName, repl, next) { }, null) } else { const templateValue = yaml.safeLoad(template, 'utf8') - k8.ns(config.k8component.namespace).pod.post({ body: templateValue}, function(err, res2){ - if(err) { - logger.error(`Cannot start pod ${podName}, error: ${stringify(err)}, \n====\ntemplate was ${template}\n====`); - next(err, null) - } else { - logger.info(`Created pod ${podName}: ${stringify(res2)}`) - next(null, res2) - } + k8.api.v1.ns(config.k8component.namespace).pod.post({ body: templateValue}).then(function(res2){ + logger.info(`Created pod ${podName}: ${stringify(res2)}`) + next(null, res2.body) + }, function(err) { + logger.error(`Cannot start pod ${podName}, error: ${err.message} ${stringify(err)}, \n====\ntemplate was ${template}\n====`); + next(err, null) }) } }) @@ -171,49 +172,56 @@ function createPod(podName, repl, next) { /// functions that either gives the running pod or starts it function getOrCreatePod(podName, repl, shouldCreate, next) { - k8.ns(config.k8component.namespace).pod.get(podName, function(err, result) { - if(err || result && - (result.status && ['Error', 'Failed', 'Succeeded'].includes(result.status.phase) || - result.metadata && result.metadata.deletionTimestamp)) { - if (result && result.metadata && result.metadata.deletionTimestamp) { + k8.api.v1.ns(config.k8component.namespace).pod(podName).get().then(function(result) { + if (result && result.body) { + let pod = result.body + if (pod.metadata && pod.metadata.deletionTimestamp) { let error = { error: 'pod shutting down', detail: `Pod ${podName} is shutting down, need to wait to restart` } logger.warn(error.detail) next(error, null) - } else if (result && result.status && ['Error', 'Failed', 'Succeeded'].includes(result.status.phase)) { + } else if (pod.status && ['Error', 'Failed', 'Succeeded'].includes(pod.status.phase)) { if (shouldCreate) { - k8.ns(config.k8component.namespace).pods.delete({ name: podName }, function (err, result) { - if (!err) { - logger.info(`Deleted stopped pod ${podName} to restart it`) - createPod(podName, repl, next) // wait & return 'pod shutting down' instead? - } else { - let error = { - error: 'failed deleting pod', - detail: `Error deleting pod ${podName} while trying to restart it: ${stringify(err)}` - } - logger.warn(error.detail) - next(err, null) + k8.api.v1.ns(config.k8component.namespace).pods.delete({ name: podName }).then(function (delResult) { + logger.info(`Deleted stopped pod ${podName} to restart it`) + createPod(podName, repl, next) // wait & return 'pod shutting down' instead? + }, function(err) { + let error = { + error: 'failed deleting pod', + detail: `Error deleting pod ${podName} while trying to restart it: ${stringify(err)}` } + logger.warn(error.detail) + next(err, null) }); - } else { - let error = { - error: 'pod failed', - detail: `Requested pod ${podName} which failed but should not be created, error: ${stringify(err)}` - } - logger.error(error.detail); - next(error, null) } - } else if (shouldCreate) { + } else { + //logger.debug(`looked up ${podName}: ${stringify(result)}`) + next(null, pod) + } + } else { + if (shouldCreate) { createPod(podName, repl, next) } else { - logger.error(`Requested pod ${podName} which does not exist and should not be created, error: ${stringify(err)}`); - next(err, null) + let error = { + error: 'pod failed', + detail: `Requested pod ${podName} which does not exist and should not be created` + } + logger.error(error.detail); + next(error, null) } + } + }, function(err) { + if (shouldCreate) { + createPod(podName, repl, next) } else { - //logger.debug(`looked up ${podName}: ${stringify(result)}`) - next(null, result) + let error = { + error: 'pod failed', + detail: `Requested pod ${podName} which failed but should not be created, error: ${stringify(err)}` + } + logger.error(error.detail); + next(error, null) } }); } @@ -222,10 +230,11 @@ function resolvePod(repl, next) { const podName = components.podNameForRepl(repl) var v = resolveCache.get(podName) if (v === undefined) { - getOrCreatePod(podName, repl, config.k8component.image.autoRestart, function (err, pod) { + getOrCreatePod(podName, repl, config.k8component.image.autoRestart, function (err, reply) { if (err) { next(err, null) } else { + let pod = reply const portNr = pod.spec.containers[0].ports[0].containerPort const podIp = pod.status.podIP if (podIp) { @@ -281,34 +290,29 @@ function resolvePod(repl, next) { function deletePod(podName, next) { - k8.ns(config.k8component.namespace).pods.delete({ name: podName }, function (err, result) { + k8.api.v1.ns(config.k8component.namespace).pods.delete({ name: podName }).then(function (result) { resolveCache.set(podName, undefined) - if (!err) { - logger.info(`deleted pod ${podName}`) - next(null, result) - } else { - logger.warn(`Error deleting pod ${podName}: ${stringify(err)}`) - next(err, null) - } + logger.info(`deleted pod ${podName}`) + next(null, result.body) + }, function(err) { + logger.warn(`Error deleting pod ${podName}: ${stringify(err)}`) + next(err, null) }) } // returns info about services indexed by service function getServiceInfo(namespace, next, {details = false} = {}) { - k8.ns(namespace).services.get({}, function(err, res) { - if (err) { - next(err, null) - } else { - let services = {} - let master = config.k8Api.url - let masterHostname = new url.URL(master).hostname - let node = config.k8Api.node - let frontendUrl = config.api.frontendUrl - let frontendHostname = new url.URL(frontendUrl).hostname - let frontendProtocol = new url.URL(frontendUrl).protocol - if (res.items) - for (let is in res.items) { - let s = res.items[is] + k8.api.v1.ns(namespace).services.get({}).then(function(res) { + let services = {} + let master = config.k8Api.url + let masterHostname = new url.URL(master).hostname + let node = config.k8Api.node + let frontendUrl = config.app.frontendUrl + let frontendHostname = new url.URL(frontendUrl).hostname + let frontendProtocol = new url.URL(frontendUrl).protocol + if (res.body && res.body.items) + for (let is in res.body.items) { + let s = res.body.items[is] let service = { name: s.metadata.name, namespace: s.metadata.namespace, @@ -329,8 +333,9 @@ function getServiceInfo(namespace, next, {details = false} = {}) { else services[service.name]=[service] } - next(null, services) - } + next(null, services) + }, function(err) { + next(err, null) }) } diff --git a/app/kubernetes.js b/app/kubernetes.js index 3f094dd..8cf058b 100644 --- a/app/kubernetes.js +++ b/app/kubernetes.js @@ -1,6 +1,9 @@ -const K8Api = require('kubernetes-client'), - fs = require('fs'), - config = require('config'); +const K8Api = require('kubernetes-client'); +const fs = require('fs'); +const config = require('config'); +const Client = K8Api.Client; +const k8Config = K8Api.config; +const client = new Client({ config: k8Config.fromKubeconfig(config.k8Api.kubeconfig), version: '1.9' }); var k8options = { url: config.k8Api.url, @@ -14,6 +17,6 @@ if(config.k8Api.ca){ k8options.key = fs.readFileSync(config.k8Api.key); } -const k8 = new K8Api.Core(k8options); +const k8 = client // new K8Api.Core(k8options); module.exports = k8 diff --git a/app/routes.js b/app/routes.js index e515092..b27d561 100644 --- a/app/routes.js +++ b/app/routes.js @@ -108,32 +108,25 @@ module.exports = function (app, redirect, config, proxyServer, proxyRouter, k8, } if (podIp && ready && podInfo.status.phase == 'Running') { // we have a valid and running pod if (cconf.execCommand) { - if (k8.ns(cconf.namespace).pod(podName).exec) { - k8.ns(cconf.namespace).pod(podName).exec.post({ qs: { - command: cconf.execCommand, - stdin: false, - stderr: false, - stdout: false, - tty: false - } }, function(err, value) { - if (err) { - logger.warn(`command ${stringify(execCommand)} on pod ${podName} failed ${stringify(err)}`) - components.evalHtmlTemplate("failedCommand.html", { - podName: podName, - command: stringify(cconf.execCommand), - error: err, - target: target - }, function(err, templateHtml) { - res.status(500).send(templateHtml) - }) - } else { - res.redirect(302, target); - } - }) - } else { - logger.warn(`command ${stringify(execCommand)} on pod ${podName} not yet implemented (should update kubernetes-client)`) + k8.api.v1.ns(cconf.namespace).pod(podName).exec.post({ qs: { + command: cconf.execCommand, + stdin: false, + stderr: true, + stdout: true, + tty: false + } }).then(function(value){ res.redirect(302, target); - } + }, function(err) { + logger.warn(`command ${stringify(execCommand)} on pod ${podName} failed ${stringify(err)}`) + components.evalHtmlTemplate("failedCommand.html", { + podName: podName, + command: stringify(cconf.execCommand), + error: err, + target: target + }, function(err, templateHtml) { + res.status(500).send(templateHtml) + }) + }) } else { res.redirect(302, target); } @@ -211,18 +204,18 @@ module.exports = function (app, redirect, config, proxyServer, proxyRouter, k8, var podName = req.params.podname; var podInfo = components.infoForPodName(podName) if (podInfo.user && loggedUsername === podInfo.user) { - k8.ns(cconf.namespace).pods.get({ name: podName }, function (err, result) { - if (!err) { - res.type('application/vnd.api+json').json({data:{ id: podName, - type: 'pod', - attributes: { - data: result - } - } - }, null, 2); - } else res.type('application/vnd.api+json').json({errors:[{ + k8.api.v1.ns(cconf.namespace).pod(podName).get().then(function (result) { + res.type('application/vnd.api+json').json({data:{ id: podName, + type: 'pod', + attributes: { + data: result.body + } + } + }, null, 2); + }, function(err) { + res.type('application/vnd.api+json').json({errors:[{ id: 'no pod', - detail: `error getting info onn pod ${podName}`, + detail: `error getting info on pod ${podName}`, data: err }]}); }); diff --git a/config/default.hjson b/config/default.hjson index 928f912..99b0abd 100644 --- a/config/default.hjson +++ b/config/default.hjson @@ -29,6 +29,7 @@ usersettings_redis: { host: "user-settings-db-redis-master" } k8Api: { + kubeconfig: "kube-certs/config" url: "https://labdev3-nomad.esc.rzg.mpg.de:6443" node: "labdev3-nomad.esc.rzg.mpg.de" ca: "kube-certs/ca.crt" diff --git a/deploy.sh b/deploy.sh index 37218ba..dc1c1dd 100755 --- a/deploy.sh +++ b/deploy.sh @@ -342,22 +342,28 @@ echo " pushd kube-certs" echo " elif [ -e ../kube-certs ] ; then" echo " pushd ../kube-certs" echo " elif [ -e ~/.minikube ] ; then" -echo " pushd ~/.minikube" +echo " mkdir -p ./kube-certs" +echo " pushd kube-certs" +echo " cp ~/.minikube/ca.crt ~/.minikube/client.crt ~/.minikube/client.key ." +echo " sed \"s|$HOME/.minikube|/usr/src/app/kube-certs|g\" ~/.kube/config > config" +if [ -z "$KUBERNETES_SERVER_URL" ] ; then + echo " echo https://\$(minikube ip):8443 > server.url" +else + echo " echo \"$KUBERNETES_SERVER_URL\" > server.url" +fi +if [ -z "$KUBERNETES_NODE" ] ; then + echo " echo \$(minikube ip) >node.addr" +else + echo " echo \"$KUBERNETES_NODE\" > node.addr" +fi echo " else" echo " pushd ." echo " fi" -if [ -z "$KUBERNETES_SERVER_URL" -a -e "$HOME/.minikube" ] ; then - KUBERNETES_SERVER_URL="https://$(minikube ip):8443" -fi -if [ -z "$KUBERNETES_NODE" -a -e "$HOME/.minikube" ] ; then - KUBERNETES_NODE="$(minikube ip)" -fi - if [ -n "$KUBERNETES_SERVER_URL" ]; then - echo " kubectl create secret generic kube-certs --from-file=ca.crt=ca.crt --from-file=client.crt=client.crt --from-file=client.key=client.key --from-literal=server.url=\"$KUBERNETES_SERVER_URL\" --from-literal=node.addr=\"$KUBERNETES_NODE\"" + echo " kubectl create secret generic kube-certs --from-file=ca.crt=ca.crt --from-file=client.crt=client.crt --from-file=client.key=client.key --from-literal=server.url=\"$KUBERNETES_SERVER_URL\" --from-literal=node.addr=\"$KUBERNETES_NODE\" --from-file=config=config" else - echo " kubectl create secret generic kube-certs --from-file=ca.crt=ca.crt --from-file=client.crt=client.crt --from-file=client.key=client.key --from-file=server.url=server.url --from-file=node.addr=node.addr" + echo " kubectl create secret generic kube-certs --from-file=ca.crt=ca.crt --from-file=client.crt=client.crt --from-file=client.key=client.key --from-file=server.url=server.url --from-file=node.addr=node.addr --from-file=config=config" fi echo " popd" echo "# create secret with web certificates" diff --git a/package.json b/package.json index 0382fb0..cc5b3e4 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "jade": "1.11.0", "js-yaml": "^3.10.0", "json-stringify-safe": "^5.0.1", - "kubernetes-client": "^3.18.1", + "kubernetes-client": "^6.3.0", "memory-store": "0.0.1", "mongoose": "^4.9.5", "morgan": "~1.7.0", diff --git a/repl.js b/repl.js index 7bc7624..857815f 100644 --- a/repl.js +++ b/repl.js @@ -2,11 +2,7 @@ const repl = require('repl') const config = require('config'); const k8 = require('./app/kubernetes')(config); const components = require('./app/components') -var ns = k8.ns(config.k8component.namespace) - -function getService() { - ns.service.get(config.k8component.imageType + '-svc-fawzi2') -} +var ns = k8.api.v1.ns(config.k8component.namespace) function testComponent() { components.templateForImageType("beaker", "fawzi2", {'session': 'pippo'}, function(err,data,repl) { @@ -18,6 +14,5 @@ const r = repl.start('> '); r.context.config = config r.context.k8 = k8 r.context.ns = ns -r.context.getService = getService r.context.components = components r.context.testComponent = testComponent -- GitLab