You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by al...@apache.org on 2020/04/21 03:11:44 UTC
[openwhisk-wskdebug] 01/01: use docker api client dockerode instead
of `docker` child process
This is an automated email from the ASF dual-hosted git repository.
alexkli pushed a commit to branch dockerode
in repository https://gitbox.apache.org/repos/asf/openwhisk-wskdebug.git
commit 657f4c364f25c202fcbee425441f7217f65efc81
Author: Alexander Klimetschek <ak...@adobe.com>
AuthorDate: Mon Apr 20 20:09:05 2020 -0700
use docker api client dockerode instead of `docker` child process
- improves performance slightly as no child process execution is required
- easier to use API than building cli arguments & parsing stdout
---
package-lock.json | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
package.json | 1 +
src/debugger.js | 10 ++-
src/invoker.js | 127 ++++++++++++++++++++++++--------
src/log.js | 6 ++
5 files changed, 319 insertions(+), 37 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index ae04f84..9912708 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -462,6 +462,14 @@
"integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=",
"dev": true
},
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
"astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -479,11 +487,34 @@
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
"binary-extensions": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
},
+ "bl": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
+ "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==",
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -508,6 +539,20 @@
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true
},
+ "buffer": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
+ "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
"caching-transform": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
@@ -567,6 +612,11 @@
"readdirp": "~3.3.0"
}
},
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
"clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -645,6 +695,17 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
+ "concat-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.0.2",
+ "typedarray": "^0.0.6"
+ }
+ },
"convert-source-map": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
@@ -733,6 +794,27 @@
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true
},
+ "docker-modem": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-2.1.2.tgz",
+ "integrity": "sha512-fwlfnsK9WV+m+qc/NZCiGt+oYAMjmCUeir0a/l3oHb0yc8FhRAucdwT4htKD3aLtV+1w2syQePH9pQFxsq1GFA==",
+ "requires": {
+ "debug": "^4.1.1",
+ "readable-stream": "^3.5.0",
+ "split-ca": "^1.0.1",
+ "ssh2": "^0.8.7"
+ }
+ },
+ "dockerode": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.2.0.tgz",
+ "integrity": "sha512-C+y/W4Kks7YLBsfUOTMkk1IVilb4cdj+rE+UZ5hnE+rpcn2frSs7kX+6H8GteTqHcv8sln+GyxuP1qdno3IzIw==",
+ "requires": {
+ "concat-stream": "~2.0.0",
+ "docker-modem": "^2.1.0",
+ "tar-fs": "~2.0.1"
+ }
+ },
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -755,6 +837,14 @@
"iconv-lite": "~0.4.13"
}
},
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
"es-abstract": {
"version": "1.17.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
@@ -1202,6 +1292,11 @@
"integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==",
"dev": true
},
+ "fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+ },
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -1402,6 +1497,11 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -1452,8 +1552,7 @@
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"inquirer": {
"version": "7.1.0",
@@ -1971,6 +2070,11 @@
"minimist": "^1.2.5"
}
},
+ "mkdirp-classic": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz",
+ "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g=="
+ },
"mocha": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz",
@@ -2472,7 +2576,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
"requires": {
"wrappy": "1"
}
@@ -2690,6 +2793,15 @@
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
"dev": true
},
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -2702,6 +2814,16 @@
"integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==",
"dev": true
},
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
"readdirp": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
@@ -2922,12 +3044,35 @@
}
}
},
+ "split-ca": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz",
+ "integrity": "sha1-bIOv82kvphJW4M0ZfgXp3hV2kaY="
+ },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
+ "ssh2": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.8.9.tgz",
+ "integrity": "sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==",
+ "requires": {
+ "ssh2-streams": "~0.4.10"
+ }
+ },
+ "ssh2-streams": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz",
+ "integrity": "sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==",
+ "requires": {
+ "asn1": "~0.2.0",
+ "bcrypt-pbkdf": "^1.0.2",
+ "streamsearch": "~0.1.2"
+ }
+ },
"stream-events": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
@@ -2937,6 +3082,11 @@
"stubs": "^3.0.0"
}
},
+ "streamsearch": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
+ "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
+ },
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
@@ -2989,6 +3139,21 @@
"es-abstract": "^1.17.5"
}
},
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ }
+ }
+ },
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@@ -3082,6 +3247,29 @@
}
}
},
+ "tar-fs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
+ "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.0.0"
+ }
+ },
+ "tar-stream": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz",
+ "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==",
+ "requires": {
+ "bl": "^4.0.1",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ }
+ },
"teeny-request": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz",
@@ -3155,6 +3343,11 @@
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
"dev": true
},
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -3170,6 +3363,11 @@
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
@@ -3199,6 +3397,11 @@
"integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=",
"dev": true
},
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@@ -3299,8 +3502,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"write": {
"version": "1.0.3",
diff --git a/package.json b/package.json
index 3c90c97..f98e612 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"chalk": "^4.0.0",
"clone": "^2.1.2",
"debug": "^4.1.1",
+ "dockerode": "^3.2.0",
"fetch-retry": "^3.1.0",
"fs-extra": "^8.1.0",
"isomorphic-fetch": "^2.2.1",
diff --git a/src/debugger.js b/src/debugger.js
index e7d250b..58462ef 100644
--- a/src/debugger.js
+++ b/src/debugger.js
@@ -287,11 +287,19 @@ class Debugger {
if (this.agentMgr) {
await this.tryCatch(this.agentMgr.shutdown());
}
+
+ // ------------< critical removal must happen above this line >---------------
+
+ // in VS Code, we will not run beyond this line upon debug stop.
+ // this is because invoker.stop() will kill the container & thus close the
+ // debug port, upon which VS Code kills the debug process (us)
if (this.invoker) {
await this.tryCatch(this.invoker.stop());
- log.debug(`stopped container: ${this.invoker.name()}`);
}
+
if (this.watcher) {
+ // this is not critical on a process exit, only if Debugger is used programmatically
+ // and might be reused for a new run()
await this.tryCatch(this.watcher.stop());
log.debug("stopped source file watching");
}
diff --git a/src/invoker.js b/src/invoker.js
index 32b9d65..7d85134 100644
--- a/src/invoker.js
+++ b/src/invoker.js
@@ -22,6 +22,7 @@ const fetch = require('fetch-retry')(require('isomorphic-fetch'));
const kinds = require('./kinds/kinds');
const path = require('path');
const log = require("./log");
+const Docker = require('dockerode');
const RUNTIME_PORT = 8080;
const INIT_RETRY_DELAY_MS = 100;
@@ -32,11 +33,13 @@ const OPENWHISK_DEFAULTS = {
memory: 256
};
-function execute(cmd, options, debug2) {
+function execute(cmd, options) {
cmd = cmd.replace(/\s+/g, ' ');
+
+ log.verboseStep(`${cmd}`)
+
const result = execSync(cmd, options);
- (debug2 || log.debug)(`executed: ${cmd}`);
if (result) {
return result.toString().trim();
} else {
@@ -54,6 +57,39 @@ function resolveValue(value, ...args) {
}
}
+function asContainerName(name) {
+ // docker container names are restricted to [a-zA-Z0-9][a-zA-Z0-9_.-]*
+
+ // 1. replace special characters with dash
+ name = name.replace(/[^a-zA-Z0-9_.-]+/g, '-');
+ // 2. leading character is more limited
+ name = name.replace(/^[^a-zA-Z0-9]+/g, '');
+ // 3. (nice to have) remove trailing special chars
+ name = name.replace(/[^a-zA-Z0-9]+$/g, '');
+
+ return name;
+}
+
+function addressForContainerPort(containerInfo, port) {
+ if (containerInfo && containerInfo.NetworkSettings && containerInfo.NetworkSettings.Ports) {
+ const ports = containerInfo.NetworkSettings.Ports;
+ // example:
+ // Ports {
+ // '8080/tcp': [ { HostIp: '0.0.0.0', HostPort: '32812' } ],
+ // '9229/tcp': [ { HostIp: '0.0.0.0', HostPort: '9229' } ]
+ // }
+ const portEntry = ports[`${port}/tcp`];
+ if (portEntry && Array.isArray(portEntry) && portEntry.length >= 1) {
+ const address = portEntry[0];
+ return `${address.HostIp}:${address.HostPort}`;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+}
+
class OpenWhiskInvoker {
constructor(actionName, action, options, wskProps, wsk) {
this.actionName = actionName;
@@ -79,12 +115,14 @@ class OpenWhiskInvoker {
this.wskProps = wskProps;
this.wsk = wsk;
- this.containerName = this.asContainerName(`wskdebug-${this.action.name}-${Date.now()}`);
+ this.containerName = asContainerName(`wskdebug-${this.action.name}-${Date.now()}`);
+ this.docker = new Docker();
}
async checkIfDockerAvailable() {
try {
- execute("docker info", {stdio: 'ignore'});
+ await this.docker.info();
+ log.debug("docker - availability check")
} catch (e) {
throw new Error("Docker not running on local system. A local docker environment is required for the debugger.")
}
@@ -190,8 +228,10 @@ class OpenWhiskInvoker {
await this.checkIfDockerAvailable();
try {
- execute(`docker inspect --type=image ${this.image} 2> /dev/null`);
+ await this.docker.getImage(this.image).inspect();
+ debug2(`docker - image inspected, is present: ${this.image}`)
} catch (e) {
+ debug2(`docker - image inspected, not found: ${this.image}`)
// make sure the user can see the image download process as part of docker run
showDockerRunOutput = true;
log.warn(`
@@ -208,10 +248,42 @@ class OpenWhiskInvoker {
`);
}
+ // console.log(this.debug.command);
+ // console.log(this.debug.command.split(" "));
+
+ // TODO: switch docker run to dockerode.run()
+ // - find the minimal HostConfig that works for the below run options
+ // https://docs.docker.com/engine/api/v1.37/#operation/ContainerCreate
+ // https://github.com/apocas/dockerode/issues/257
+ // https://github.com/apocas/dockerode/blob/master/lib/docker.js#L1442
+ // https://medium.com/@johnnyeric/how-to-reproduce-command-docker-run-via-docker-remote-api-with-node-js-5918d7b221ea
+ // - kinds/nodejs.js has to switch from docker args to HostConfig map for -e and -v
+ // - --docker-args (this.dockerArgsFromUser) must be parsed and turned into HostConfig
+ // - replaces docker logs call as well, using streams to pass and write into sdtout/err
+ // - allows to intercept logging using our log.log() & log.error() calls (?)
+ // - also must use global.mochaLogFile
+ // - no stdin needed
+ // - returns dockerode container object (store as this.container)
+ // - call this.container.kill() on it to get rid of it (already done in stop())
+
+ // await this.docker.run(
+ // this.image,
+ // [ 'sh', '-c', ...this.debug.command.split(" ") ],
+ // showDockerRunOutput ? [process.stdout] : [],
+ // {
+ // HostConfig: {
+ // AutoRemove: true,
+ // PortBindings: {
+ // [`${RUNTIME_PORT}/tcp`]: [{ HostPort: RUNTIME_PORT }]
+ // }
+ // }
+ // }
+ // );
+ // log.debug("docker - run");
execute(
`docker run
-d
- --name ${this.name()}
+ --name ${this.containerName}
--rm
-m ${this.memory}
-p ${RUNTIME_PORT}
@@ -222,11 +294,16 @@ class OpenWhiskInvoker {
${this.debug.command}
`,
// live stream view for docker image download output
- { stdio: showDockerRunOutput ? "inherit" : null },
- debug2
+ { stdio: showDockerRunOutput ? "inherit" : null }
);
+ debug2(`docker - started container ${this.containerName}`);
- this.containerRunning = true;
+ this.container = this.docker.getContainer(this.containerName);
+
+ // ask docker for the exposed IP and port of the RUNTIME_PORT on the container
+ const containerInfo = await this.container.inspect();
+ debug2(`docker - retrieved container metadata`);
+ this.containerURL = `http://${addressForContainerPort(containerInfo, RUNTIME_PORT)}`;
log.stopSpinner();
spawn("docker", ["logs", "-t", "-f", this.name()], {
@@ -236,6 +313,7 @@ class OpenWhiskInvoker {
global.mochaLogFile || "inherit" // stderr
]
});
+ log.debug(`docker - trailing logs`);
}
getSourcePath() {
@@ -308,40 +386,27 @@ class OpenWhiskInvoker {
}
async stop() {
- if (this.containerRunning) {
- execute(`docker kill ${this.name()}`);
+ if (this.container) {
+ // log this here for VS Code, will be the last visible log message since
+ // we will be killed by VS code after the container is gone after the kill()
+ log.log(`Stopping container ${this.name()}.`);
+ await this.container.kill();
+ delete this.container;
+ log.debug(`docker - stopped container ${this.name()}`);
}
}
name() {
- return this.containerName;
+ return this.container ? this.container.id : "";
}
url() {
- if (!this.containerURL) {
- // ask docker for the exposed IP and port of the RUNTIME_PORT on the container
- const host = execute(`docker port ${this.name()} ${RUNTIME_PORT}`);
- this.containerURL = `http://${host}`;
- }
- return this.containerURL;
+ return this.containerURL || "";
}
timeout() {
return this.action.limits.timeout || OPENWHISK_DEFAULTS.timeout;
}
-
- asContainerName(name) {
- // docker container names are restricted to [a-zA-Z0-9][a-zA-Z0-9_.-]*
-
- // 1. replace special characters with dash
- name = name.replace(/[^a-zA-Z0-9_.-]+/g, '-');
- // 2. leading character is more limited
- name = name.replace(/^[^a-zA-Z0-9]+/g, '');
- // 3. (nice to have) remove trailing special chars
- name = name.replace(/[^a-zA-Z0-9]+$/g, '');
-
- return name;
- }
}
module.exports = OpenWhiskInvoker;
diff --git a/src/log.js b/src/log.js
index fc39e25..8c13932 100644
--- a/src/log.js
+++ b/src/log.js
@@ -117,6 +117,12 @@ module.exports = {
}
},
+ verboseStep: function(...args) {
+ if (this.isVerbose) {
+ this.step(...args);
+ }
+ },
+
verboseWrite: function(text) {
if (this.isVerbose) {
process.stdout.write(text);