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