diff --git a/.travis.yml b/.travis.yml index 21608d2..9d1e14f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +# https://medium.com/@quentin.mcgaw/cross-architecture-docker-builds-with-travis-ci-arm-s390x-etc-8f754e20aaef dist: bionic sudo: required @@ -14,19 +15,25 @@ env: # - DOCKER_BUILD_PLATFORM=linux/arm64 # - FOO=bar BAR=baz +#addons: +# apt: +# packages: +# - docker-ce + # uname -m # aarch64 # x86_64 # armv7l before_install: - uname -a + - sudo cat /etc/docker/daemon.json + - sudo systemctl status docker.service + - sudo service docker restart - export ARCH=$([ $(uname -m) = "x86_64" ] && echo "amd64" || echo "arm64") - mkdir -p ~/.docker/cli-plugins/ - wget -O ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.3.1/buildx-v0.3.1.linux-${ARCH} - chmod a+x ~/.docker/cli-plugins/docker-buildx - - echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json - - mkdir -p $HOME/.docker - - echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json + - sudo cat /etc/docker/daemon.json - docker info - docker buildx version install: diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6a87727 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Travis Glenn Hansen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bce9e27 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Introduction + +`democratic-csi` implements the `csi` (container storage interface) spec +providing storage for various container orchestration systems (ie: Kubernetes). + +The current focus is providing storage via iscsi/nfs from zfs-based storage +systems, predominantly `FreeNAS / TrueNAS` and `ZoL` on `Ubuntu`. + +The current drivers implement depth and breadth of the `csi` spec, so you have +access to resizing, snapshots, etc, etc. + +`democratic-csi` is 2 things: + +- several implementations of `csi` drivers + - freenas-nfs (manages zfs datasets to share over nfs) + - freenas-iscsi (manages zfs zvols to share over iscsi) + - zfs-generic-nfs (works with any ZoL installation...ie: Ubuntu) + - zfs-generic-iscsi (works with any ZoL installation...ie: Ubuntu) + - zfs-local-ephemeral-inline (provisions node-local zfs datasets) +- framework for developing `csi` drivers + +If you have any interest in providing a `csi` driver, simply open an issue to +discuss. The project provides an extensive framework to build from making it +relatively easy to implement new drivers. + +# Installation + +Predominantly 2 things are needed: + +- node prep: https://netapp-trident.readthedocs.io/en/stable-v20.04/kubernetes/operations/tasks/worker.html +- deploy the driver into the cluster (`helm` chart provided with sample + `values.yaml`) + +You should install/configure the requirements for both nfs and iscsi. + +## Helm Installation + +``` +helm repo add democratic-csi https://democratic-csi.github.io/charts/ +helm repo update +helm search democratic-csi/ + +# copy proper values file from https://github.com/democratic-csi/charts/tree/master/stable/democratic-csi/examples +# edit as appropriate +# examples are from helm v2, alter as appropriate for v3 + +helm upgrade \ +--install \ +--values freenas-iscsi.yaml \ +--namespace democratic-csi \ +zfs-iscsi democratic-csi/democratic-csi + +helm upgrade \ +--install \ +--values freenas-nfs.yaml \ +--namespace democratic-csi \ +zfs-nfs democratic-csi/democratic-csi +``` + +## Multiple Deployments + +You may install multiple deployments of each/any driver. It requires the following: + +- Use a new helm release name for each deployment +- Make sure you have a unique `csiDriver.name` in the values file +- Use unqiue names for your storage classes (per cluster) +- Use a unique parent dataset (ie: don't try to use the same parent across deployments or clusters) diff --git a/bin/democratic-csi b/bin/democratic-csi index 9c0e4c2..7d4ee06 100755 --- a/bin/democratic-csi +++ b/bin/democratic-csi @@ -11,7 +11,7 @@ const args = require("yargs") .option("driver-config-file", { describe: "provide a path to driver config file", config: true, - configParser: path => { + configParser: (path) => { try { options = JSON.parse(fs.readFileSync(path, "utf-8")); return true; @@ -23,40 +23,40 @@ const args = require("yargs") } catch (e) {} throw new Error("failed parsing config file: " + path); - } + }, }) .demandOption(["driver-config-file"], "driver-config-file is required") .option("log-level", { describe: "log level", - choices: ["error", "warn", "info", "verbose", "debug", "silly"] + choices: ["error", "warn", "info", "verbose", "debug", "silly"], }) .option("csi-version", { describe: "versin of the csi spec to load", - choices: ["0.2.0", "0.3.0", "1.0.0", "1.1.0", "1.2.0"] + choices: ["0.2.0", "0.3.0", "1.0.0", "1.1.0", "1.2.0"], }) .demandOption(["csi-version"], "csi-version is required") .option("csi-name", { - describe: "name to use for driver registration" + describe: "name to use for driver registration", }) .demandOption(["csi-name"], "csi-name is required") .option("csi-mode", { describe: "mode of the controller", choices: ["controller", "node"], type: "array", - default: ["controller", "node"] + default: ["controller", "node"], }) .demandOption(["csi-mode"], "csi-mode is required") .option("server-address", { describe: "listen address for the server", - type: "string" + type: "string", }) .option("server-port", { describe: "listen port for the server", - type: "number" + type: "number", }) .option("server-socket", { describe: "listen socket for the server", - type: "string" + type: "string", }) .version() .help().argv; @@ -87,7 +87,7 @@ const packageDefinition = protoLoader.loadSync(PROTO_PATH, { longs: String, enums: String, defaults: true, - oneofs: true + oneofs: true, }); const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); @@ -97,7 +97,10 @@ logger.info("initializing csi driver: %s", options.driver); let driver; try { - driver = require("../src/driver/factory").factory({ logger, args, cache, package }, options); + driver = require("../src/driver/factory").factory( + { logger, args, cache, package }, + options + ); } catch (err) { logger.error(err.toString()); process.exit(1); @@ -127,20 +130,26 @@ async function requestHandlerProxy(call, callback, serviceMethodName) { ); callback(null, response); } catch (e) { + let message; + if (e instanceof Error) { + message = e.toString(); + } else { + message = JSON.stringify(e); + } + logger.error( "handler error - driver: %s method: %s error: %s", driver.constructor.name, serviceMethodName, - JSON.stringify(e) + message ); if (e.name == "GrpcError") { callback(e); } else { // TODO: only show real error string in development mode - const message = true - ? e.toString() - : "unknown error, please inspect service logs"; + message = true ? message : "unknown error, please inspect service logs"; + callback({ code: grpc.status.INTERNAL, message }); } } @@ -159,7 +168,7 @@ function getServer() { }, async Probe(call, callback) { requestHandlerProxy(call, callback, arguments.callee.name); - } + }, }); // Controller Service @@ -200,7 +209,7 @@ function getServer() { }, async ControllerExpandVolume(call, callback) { requestHandlerProxy(call, callback, arguments.callee.name); - } + }, }); } @@ -230,7 +239,7 @@ function getServer() { }, async NodeGetInfo(call, callback) { requestHandlerProxy(call, callback, arguments.callee.name); - } + }, }); } @@ -274,8 +283,8 @@ if (bindSocket) { csiServer.start(); [`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach( - eventType => { - process.on(eventType, code => { + (eventType) => { + process.on(eventType, (code) => { console.log(`running server shutdown, exit code: ${code}`); let socketPath = args.serverSocket || ""; socketPath = socketPath.replace(/^unix:\/\//g, ""); diff --git a/examples/zfs-local-ephemeral-inline.yaml b/examples/zfs-local-ephemeral-inline.yaml new file mode 100644 index 0000000..df1922a --- /dev/null +++ b/examples/zfs-local-ephemeral-inline.yaml @@ -0,0 +1,16 @@ +driver: zfs-local-ephemeral-inline +service: + identity: {} + controller: {} + node: {} +zfs: + #chroot: "/host" + datasetParentName: tank/k8s/inline + properties: + # add any arbitrary properties you want here + #refquota: + # value: 10M + # allowOverride: false # default is to allow inline settings to override + #refreservation: + # value: 5M + # ... diff --git a/package-lock.json b/package-lock.json index 886e626..2e7e573 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,27 +5,63 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.10.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@babel/runtime-corejs3": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz", + "integrity": "sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, "@grpc/proto-loader": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.3.tgz", - "integrity": "sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz", + "integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==", "requires": { "lodash.camelcase": "^4.3.0", "protobufjs": "^6.8.6" @@ -37,9 +73,9 @@ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "protobufjs": { - "version": "6.8.8", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", - "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz", + "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -51,8 +87,8 @@ "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.0", - "@types/node": "^10.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", "long": "^4.0.0" } } @@ -118,43 +154,40 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, "@types/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", - "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, "@types/node": { - "version": "10.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.9.tgz", - "integrity": "sha512-NelG/dSahlXYtSoVPErrp06tYFrvzj8XLWmKA+X8x0W//4MqbUyZu++giUG/v0bjAT6/Qxa8IjodrfdACyb0Fg==" + "version": "13.13.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.13.tgz", + "integrity": "sha512-UfvBE9oRCAJVzfR+3eWm/sdLFe/qroAPEXP3GPJ1SehQiEVgZT6NQZWYbPMiJ3UdcKM06v4j+S1lTcdWCmw+3g==" }, "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==" }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==" }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", - "requires": { - "type-fest": "^0.8.1" - } + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-regex": { "version": "5.0.0", @@ -205,12 +238,9 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, "asynckit": { "version": "0.4.0", @@ -223,9 +253,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" }, "balanced-match": { "version": "1.0.0", @@ -250,12 +280,12 @@ } }, "bunyan": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", - "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.14.tgz", + "integrity": "sha512-LlahJUxXzZLuw/hetUQJmRgZ1LF6+cr5TPpRj6jf327AsiIq2jhYEH4oqUUkVKTor+9w2BT3oxVwhzE5lw9tcg==", "requires": { "dtrace-provider": "~0.8", - "moment": "^2.10.6", + "moment": "^2.19.3", "mv": "~2", "safe-json-stringify": "~1" } @@ -284,33 +314,51 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -319,6 +367,16 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "code-point-at": { @@ -357,15 +415,10 @@ "simple-swizzle": "^0.2.2" } }, - "colornames": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", - "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" - }, "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "colorspace": { "version": "1.1.2", @@ -394,28 +447,24 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "dashdash": { @@ -449,16 +498,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "diagnostics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" - } - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -486,22 +525,22 @@ } }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "enabled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", - "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", - "requires": { - "env-variable": "0.0.x" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, - "env-variable": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", - "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "requires": { + "ansi-colors": "^4.1.1" + } }, "escape-string-regexp": { "version": "1.0.5", @@ -509,94 +548,78 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz", - "integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", + "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.0.0", + "eslint-visitor-keys": "^1.2.0", + "espree": "^7.1.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", + "levn": "^0.4.1", "lodash": "^4.17.14", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "requires": { "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" }, "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", + "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", - "eslint-visitor-keys": "^1.1.0" + "acorn": "^7.2.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.2.0" } }, "esprima": { @@ -605,11 +628,18 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==" + } } }, "esrecurse": { @@ -635,30 +665,20 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -666,22 +686,14 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-safe-stringify": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", - "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "fecha": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", - "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" - }, - "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", - "requires": { - "escape-string-regexp": "^1.0.5" - } + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" }, "file-entry-cache": { "version": "5.0.1", @@ -708,12 +720,27 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + } } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" + }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "forever-agent": { "version": "0.6.1", @@ -767,17 +794,20 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "requires": { "is-glob": "^4.0.1" } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "requires": { + "type-fest": "^0.8.1" + } }, "grpc-uds": { "version": "0.1.4", @@ -819,14 +849,6 @@ "sshpk": "^1.7.0" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -860,41 +882,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "inquirer": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", - "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -923,15 +910,10 @@ "is-extglob": "^2.1.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, "is-typedarray": { "version": "1.0.0", @@ -959,9 +941,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1004,12 +986,9 @@ } }, "kuler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", - "requires": { - "colornames": "^1.1.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, "lcid": { "version": "1.0.0", @@ -1020,12 +999,12 @@ } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "locate-path": { @@ -1037,9 +1016,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.18.tgz", + "integrity": "sha512-au4L1q0HKcaaa37qOdpWWhwzDnB/taYJfRiKULnaT+Ml9UaBIjJ2SOJMeLtSeeLT+zUdyFMm0+ts+j4eeuUpIA==" }, "lodash.camelcase": { "version": "4.3.0", @@ -1052,13 +1031,13 @@ "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" }, "logform": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", - "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", "requires": { "colors": "^1.2.1", "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", + "fecha": "^4.2.0", "ms": "^2.1.1", "triple-beam": "^1.3.0" } @@ -1077,23 +1056,18 @@ } }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "requires": { - "mime-db": "1.40.0" + "mime-db": "1.44.0" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1103,22 +1077,22 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", "optional": true }, "ms": { @@ -1126,11 +1100,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, "mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", @@ -1140,30 +1109,6 @@ "mkdirp": "~0.5.1", "ncp": "~2.0.0", "rimraf": "~2.4.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "optional": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", - "optional": true, - "requires": { - "glob": "^6.0.1" - } - } } }, "nan": { @@ -1182,11 +1127,6 @@ "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "optional": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -1206,29 +1146,24 @@ } }, "one-time": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", - "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" - }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "requires": { - "mimic-fn": "^2.1.0" + "fn.name": "1.x.x" } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, "optjs": { @@ -1244,15 +1179,10 @@ "lcid": "^1.0.0" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } @@ -1289,9 +1219,9 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "performance-now": { "version": "2.1.0", @@ -1299,9 +1229,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, "process-nextick-args": { "version": "2.0.1", @@ -1401,9 +1331,9 @@ } }, "psl": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.33.tgz", - "integrity": "sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { "version": "2.1.1", @@ -1416,28 +1346,29 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -1446,7 +1377,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -1456,9 +1387,16 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } } }, "require-directory": { @@ -1476,43 +1414,34 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "optional": true, "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "^2.1.0" - } - }, - "rxjs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", - "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", - "requires": { - "tslib": "^1.9.0" + "glob": "^6.0.1" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "optional": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-json-stringify": { "version": "1.2.0", @@ -1526,9 +1455,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" }, "set-blocking": { "version": "2.0.0", @@ -1536,22 +1465,17 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "simple-swizzle": { "version": "0.2.2", @@ -1584,17 +1508,17 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "ssh2": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.8.6.tgz", - "integrity": "sha512-T0cPmEtmtC8WxSupicFDjx3vVUdNXO8xu2a/D5bjt8ixOUCe387AgvxU3mJgEHpu7+Sq1ZYx4d3P2pl/yxMH+w==", + "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.7" + "ssh2-streams": "~0.4.10" } }, "ssh2-streams": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.7.tgz", - "integrity": "sha512-JhF8BNfeguOqVHOLhXjzLlRKlUP8roAEhiT/y+NcBQCqpRUupLNrRf2M+549OPNVGx21KgKktug4P3MY/IvTig==", + "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", @@ -1637,19 +1561,22 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } } } }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "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.1.0" + "safe-buffer": "~5.2.0" } }, "strip-ansi": { @@ -1661,9 +1588,9 @@ } }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==" }, "supports-color": { "version": "5.5.0", @@ -1684,22 +1611,16 @@ "string-width": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -1735,33 +1656,13 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, "triple-beam": { @@ -1769,11 +1670,6 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -1788,11 +1684,11 @@ "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", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-fest": { @@ -1814,14 +1710,14 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" }, "verror": { "version": "1.10.0", @@ -1834,9 +1730,9 @@ } }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "requires": { "isexe": "^2.0.0" } @@ -1852,40 +1748,57 @@ "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" }, "winston": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", - "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", "requires": { - "async": "^2.6.1", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^2.1.1", - "one-time": "0.0.4", - "readable-stream": "^3.1.1", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.3.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "winston-transport": "^4.4.0" } }, "winston-transport": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", - "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", "requires": { - "readable-stream": "^2.3.6", + "readable-stream": "^2.3.7", "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "word-wrap": { @@ -1904,9 +1817,9 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", - "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "requires": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" @@ -1924,6 +1837,14 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } } } }, @@ -1940,6 +1861,14 @@ "mkdirp": "^0.5.1" } }, + "xregexp": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", + "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", + "requires": { + "@babel/runtime-corejs3": "^7.8.3" + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -1951,12 +1880,12 @@ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" }, "yargs": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", - "integrity": "sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==", + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.0.tgz", + "integrity": "sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw==", "requires": { "cliui": "^6.0.0", - "decamelize": "^1.2.0", + "decamelize": "^3.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", @@ -1965,13 +1894,23 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^16.1.0" + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "decamelize": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz", + "integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==", + "requires": { + "xregexp": "^4.2.4" + } + } } }, "yargs-parser": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", - "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 2ddadeb..8132aae 100644 --- a/package.json +++ b/package.json @@ -18,17 +18,17 @@ "url": "https://github.com/democratic-csi/democratic-csi.git" }, "dependencies": { - "@grpc/proto-loader": "^0.5.3", - "bunyan": "^1.8.12", - "eslint": "^6.6.0", + "@grpc/proto-loader": "^0.5.4", + "bunyan": "^1.8.14", + "eslint": "^7.4.0", "grpc-uds": "^0.1.4", - "js-yaml": "^3.13.1", + "js-yaml": "^3.14.0", "lru-cache": "^5.1.1", - "request": "^2.88.0", - "ssh2": "^0.8.6", + "request": "^2.88.2", + "ssh2": "^0.8.9", "uri-js": "^4.2.2", - "uuid": "^3.3.3", - "winston": "^3.2.1", - "yargs": "^15.0.2" + "uuid": "^8.2.0", + "winston": "^3.3.3", + "yargs": "^15.4.0" } } diff --git a/src/driver/controller-zfs-ssh/index.js b/src/driver/controller-zfs-ssh/index.js index 61e00df..b432a36 100644 --- a/src/driver/controller-zfs-ssh/index.js +++ b/src/driver/controller-zfs-ssh/index.js @@ -3,6 +3,7 @@ const SshClient = require("../../utils/ssh").SshClient; const { GrpcError, grpc } = require("../../utils/grpc"); const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs"); +const uuidv4 = require("uuid").v4; // zfs common properties const MANAGED_PROPERTY_NAME = "democratic-csi:managed_resource"; @@ -56,7 +57,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { options.service.identity.capabilities.service = [ //"UNKNOWN", - "CONTROLLER_SERVICE" + "CONTROLLER_SERVICE", //"VOLUME_ACCESSIBILITY_CONSTRAINTS" ]; } @@ -66,7 +67,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { options.service.identity.capabilities.volume_expansion = [ //"UNKNOWN", - "ONLINE" + "ONLINE", //"OFFLINE" ]; } @@ -84,7 +85,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "LIST_SNAPSHOTS", "CLONE_VOLUME", //"PUBLISH_READONLY", - "EXPAND_VOLUME" + "EXPAND_VOLUME", ]; } @@ -96,7 +97,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { options.service.node.capabilities.rpc = [ //"UNKNOWN", "STAGE_UNSTAGE_VOLUME", - "GET_VOLUME_STATS" + "GET_VOLUME_STATS", //"EXPAND_VOLUME" ]; break; @@ -105,7 +106,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { //"UNKNOWN", "STAGE_UNSTAGE_VOLUME", "GET_VOLUME_STATS", - "EXPAND_VOLUME" + "EXPAND_VOLUME", ]; break; } @@ -115,7 +116,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { getSshClient() { return new SshClient({ logger: this.ctx.logger, - connection: this.options.sshConnection + connection: this.options.sshConnection, }); } @@ -123,7 +124,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { const sshClient = this.getSshClient(); return new Zetabyte({ executor: new ZfsSshProcessManager(sshClient), - idempotent: true + idempotent: true, }); } @@ -160,7 +161,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { let message = null; //[{"access_mode":{"mode":"SINGLE_NODE_WRITER"},"mount":{"mount_flags":["noatime","_netdev"],"fs_type":"nfs"},"access_type":"mount"}] - const valid = capabilities.every(capability => { + const valid = capabilities.every((capability) => { switch (driverZfsResourceType) { case "filesystem": if (capability.access_type != "mount") { @@ -183,7 +184,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "SINGLE_NODE_READER_ONLY", "MULTI_NODE_READER_ONLY", "MULTI_NODE_SINGLE_WRITER", - "MULTI_NODE_MULTI_WRITER" + "MULTI_NODE_MULTI_WRITER", ].includes(capability.access_mode.mode) ) { message = `invalid access_mode, ${capability.access_mode.mode}`; @@ -210,7 +211,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "SINGLE_NODE_WRITER", "SINGLE_NODE_READER_ONLY", "MULTI_NODE_READER_ONLY", - "MULTI_NODE_SINGLE_WRITER" + "MULTI_NODE_SINGLE_WRITER", ].includes(capability.access_mode.mode) ) { message = `invalid access_mode, ${capability.access_mode.mode}`; @@ -436,12 +437,12 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { // remove snapshots from target await this.removeSnapshotsFromDatatset(datasetName, { - force: true + force: true, }); } else { try { response = await zb.zfs.clone(fullSnapshotName, datasetName, { - properties: volumeProperties + properties: volumeProperties, }); } catch (err) { if (err.toString().includes("dataset does not exist")) { @@ -461,7 +462,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { await zb.zfs.destroy(fullSnapshotName, { recurse: true, force: true, - defer: true + defer: true, }); } catch (err) { if (err.toString().includes("dataset does not exist")) { @@ -543,21 +544,21 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { // remove snapshots from target await this.removeSnapshotsFromDatatset(datasetName, { - force: true + force: true, }); // remove snapshot from source await zb.zfs.destroy(fullSnapshotName, { recurse: true, force: true, - defer: true + defer: true, }); } else { // create clone // zfs origin property contains parent info, ie: pool0/k8s/test/PVC-111@clone-test try { response = await zb.zfs.clone(fullSnapshotName, datasetName, { - properties: volumeProperties + properties: volumeProperties, }); } catch (err) { if (err.toString().includes("dataset does not exist")) { @@ -587,7 +588,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { await zb.zfs.create(datasetName, { parents: true, properties: volumeProperties, - size: driverZfsResourceType == "volume" ? capacity_bytes : false + size: driverZfsResourceType == "volume" ? capacity_bytes : false, }); } @@ -632,7 +633,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "compression", VOLUME_CSI_NAME_PROPERTY_NAME, VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME, - VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME + VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME, ]); properties = properties[datasetName]; driver.ctx.logger.debug("zfs props data: %j", properties); @@ -641,7 +642,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { if (this.options.zfs.datasetPermissionsMode) { command = sshClient.buildCommand("chmod", [ this.options.zfs.datasetPermissionsMode, - properties.mountpoint.value + properties.mountpoint.value, ]); driver.ctx.logger.verbose("set permission command: %s", command); response = await sshClient.exec(command); @@ -660,7 +661,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { (this.options.zfs.datasetPermissionsGroup ? this.options.zfs.datasetPermissionsGroup : ""), - properties.mountpoint.value + properties.mountpoint.value, ]); driver.ctx.logger.verbose("set ownership command: %s", command); response = await sshClient.exec(command); @@ -691,7 +692,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { volume_context = await this.createShare(call, datasetName); await zb.zfs.set(datasetName, { [SHARE_VOLUME_CONTEXT_PROPERTY_NAME]: - "'" + JSON.stringify(volume_context) + "'" + "'" + JSON.stringify(volume_context) + "'", }); volume_context["provisioner_driver"] = driver.options.driver; @@ -714,8 +715,8 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { ? capacity_bytes : 0, content_source: volume_content_source, - volume_context - } + volume_context, + }, }; return res; @@ -761,7 +762,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "origin", "refquota", "compression", - VOLUME_CSI_NAME_PROPERTY_NAME + VOLUME_CSI_NAME_PROPERTY_NAME, ]); properties = properties[datasetName]; } catch (err) { @@ -798,7 +799,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { await zb.zfs.destroy(properties.origin.value, { recurse: true, force: true, - defer: true + defer: true, }); } catch (err) { if (err.toString().includes("snapshot has dependent clones")) { @@ -939,7 +940,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { return { capacity_bytes: this.options.zfs.datasetEnableQuotas ? capacity_bytes : 0, - node_expansion_required: driverZfsResourceType == "volume" ? true : false + node_expansion_required: driverZfsResourceType == "volume" ? true : false, }; } @@ -1017,7 +1018,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { } const data = { entries: entries, - next_token: next_token + next_token: next_token, }; return data; @@ -1061,7 +1062,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { SHARE_VOLUME_CONTEXT_PROPERTY_NAME, SUCCESS_PROPERTY_NAME, VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME, - VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME + VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME, ], { types, recurse: true } ); @@ -1069,7 +1070,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { if (err.toString().includes("dataset does not exist")) { return { entries: [], - next_token: null + next_token: null, }; } @@ -1084,7 +1085,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { } entries = []; - response.indexed.forEach(row => { + response.indexed.forEach((row) => { // ignore rows were csi_name is empty if (row[MANAGED_PROPERTY_NAME] != "true") { return; @@ -1142,8 +1143,8 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { ? row["refquota"] : row["volsize"], content_source: volume_content_source, - volume_context - } + volume_context, + }, }); }); @@ -1159,7 +1160,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { const data = { entries: entries, - next_token: next_token + next_token: next_token, }; return data; @@ -1205,7 +1206,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { } const data = { entries: entries, - next_token: next_token + next_token: next_token, }; return data; @@ -1290,7 +1291,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { "used", VOLUME_CSI_NAME_PROPERTY_NAME, SNAPSHOT_CSI_NAME_PROPERTY_NAME, - MANAGED_PROPERTY_NAME + MANAGED_PROPERTY_NAME, ], { types, recurse: true } ); @@ -1314,7 +1315,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { throw new GrpcError(grpc.status.FAILED_PRECONDITION, e.toString()); } - response.indexed.forEach(row => { + response.indexed.forEach((row) => { // skip any snapshots not explicitly created by CO if (row[MANAGED_PROPERTY_NAME] != "true") { return; @@ -1371,10 +1372,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { //https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto creation_time: { seconds: row["creation"], - nanos: 0 + nanos: 0, }, - ready_to_use: true - } + ready_to_use: true, + }, }); }); } @@ -1391,7 +1392,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { const data = { entries: entries, - next_token: next_token + next_token: next_token, }; return data; @@ -1552,7 +1553,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { { recurse: true, force: true, - defer: true + defer: true, } ); @@ -1560,12 +1561,12 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { await zb.zfs.destroy(tmpSnapshotName, { recurse: true, force: true, - defer: true + defer: true, }); } else { try { await zb.zfs.snapshot(fullSnapshotName, { - properties: snapshotProperties + properties: snapshotProperties, }); } catch (err) { if (err.toString().includes("dataset does not exist")) { @@ -1592,7 +1593,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { VOLUME_CSI_NAME_PROPERTY_NAME, SNAPSHOT_CSI_NAME_PROPERTY_NAME, SNAPSHOT_CSI_SOURCE_VOLUME_ID_PROPERTY_NAME, - MANAGED_PROPERTY_NAME + MANAGED_PROPERTY_NAME, ], { types } ); @@ -1623,10 +1624,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { //https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto creation_time: { seconds: properties.creation.value, - nanos: 0 + nanos: 0, }, - ready_to_use: true - } + ready_to_use: true, + }, }; } @@ -1673,7 +1674,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { await zb.zfs.destroy(fullSnapshotName, { recurse: true, force: true, - defer: zb.helpers.isZfsSnapshot(snapshot_id) // only defer when snapshot + defer: zb.helpers.isZfsSnapshot(snapshot_id), // only defer when snapshot }); } catch (err) { if (err.toString().includes("snapshot has dependent clones")) { @@ -1720,8 +1721,8 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { confirmed: { volume_context: call.request.volume_context, volume_capabilities: call.request.volume_capabilities, // TODO: this is a bit crude, should return *ALL* capabilities, not just what was requested - parameters: call.request.parameters - } + parameters: call.request.parameters, + }, }; } } diff --git a/src/driver/factory.js b/src/driver/factory.js index b2dfec9..8863e42 100644 --- a/src/driver/factory.js +++ b/src/driver/factory.js @@ -1,14 +1,21 @@ const { FreeNASDriver } = require("./freenas"); const { ControllerZfsGenericDriver } = require("./controller-zfs-generic"); +const { + ZfsLocalEphemeralInlineDriver, +} = require("./zfs-local-ephemeral-inline"); function factory(ctx, options) { switch (options.driver) { case "freenas-nfs": case "freenas-iscsi": + case "truenas-nfs": + case "truenas-iscsi": return new FreeNASDriver(ctx, options); case "zfs-generic-nfs": case "zfs-generic-iscsi": return new ControllerZfsGenericDriver(ctx, options); + case "zfs-local-ephemeral-inline": + return new ZfsLocalEphemeralInlineDriver(ctx, options); default: throw new Error("invalid csi driver: " + options.driver); } diff --git a/src/driver/index.js b/src/driver/index.js index a86830c..dc866c1 100644 --- a/src/driver/index.js +++ b/src/driver/index.js @@ -298,7 +298,11 @@ class CsiBaseDriver { break; case "iscsi": // create DB entry - let nodeDB = {}; + // https://library.netapp.com/ecmdocs/ECMP1654943/html/GUID-8EC685B4-8CB6-40D8-A8D5-031A3899BCDC.html + // put these options in place to force targets managed by csi to be explicitly attached (in the case of unclearn shutdown etc) + let nodeDB = { + "node.startup": "manual" + }; const nodeDBKeyPrefix = "node-db."; const normalizedSecrets = this.getNormalizedParameters( call.request.secrets, diff --git a/src/driver/zfs-local-ephemeral-inline/index.js b/src/driver/zfs-local-ephemeral-inline/index.js new file mode 100644 index 0000000..208afb3 --- /dev/null +++ b/src/driver/zfs-local-ephemeral-inline/index.js @@ -0,0 +1,471 @@ +const fs = require("fs"); +const { CsiBaseDriver } = require("../index"); +const { GrpcError, grpc } = require("../../utils/grpc"); +const { Filesystem } = require("../../utils/filesystem"); +const SshClient = require("../../utils/ssh").SshClient; +const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs"); + +// zfs common properties +const MANAGED_PROPERTY_NAME = "democratic-csi:managed_resource"; +const SUCCESS_PROPERTY_NAME = "democratic-csi:provision_success"; +const VOLUME_CSI_NAME_PROPERTY_NAME = "democratic-csi:csi_volume_name"; +const VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME = + "democratic-csi:volume_context_provisioner_driver"; +const VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME = + "democratic-csi:volume_context_provisioner_instance_id"; + +/** + * https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/20190122-csi-inline-volumes.md + * https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html + * + * Sample calls: + * - https://gcsweb.k8s.io/gcs/kubernetes-jenkins/pr-logs/pull/92387/pull-kubernetes-e2e-gce/1280784994997899264/artifacts/_sig-storage_CSI_Volumes/_Driver_csi-hostpath_/_Testpattern_inline_ephemeral_CSI_volume_ephemeral/should_create_read_write_inline_ephemeral_volume/ + * - https://storage.googleapis.com/kubernetes-jenkins/pr-logs/pull/92387/pull-kubernetes-e2e-gce/1280784994997899264/artifacts/_sig-storage_CSI_Volumes/_Driver_csi-hostpath_/_Testpattern_inline_ephemeral_CSI_volume_ephemeral/should_create_read-only_inline_ephemeral_volume/csi-hostpathplugin-0-hostpath.log + * + * inline drivers are assumed to be mount only (no block support) + * purposely there is no native support for size contraints + * + * TODO: support creating zvols and formatting and mounting locally instead of using zfs dataset? + * + */ +class ZfsLocalEphemeralInlineDriver extends CsiBaseDriver { + constructor(ctx, options) { + super(...arguments); + + options = options || {}; + options.service = options.service || {}; + options.service.identity = options.service.identity || {}; + options.service.controller = options.service.controller || {}; + options.service.node = options.service.node || {}; + + options.service.identity.capabilities = + options.service.identity.capabilities || {}; + + options.service.controller.capabilities = + options.service.controller.capabilities || {}; + + options.service.node.capabilities = options.service.node.capabilities || {}; + + if (!("service" in options.service.identity.capabilities)) { + this.ctx.logger.debug("setting default identity service caps"); + + options.service.identity.capabilities.service = [ + "UNKNOWN", + //"CONTROLLER_SERVICE" + //"VOLUME_ACCESSIBILITY_CONSTRAINTS" + ]; + } + + if (!("volume_expansion" in options.service.identity.capabilities)) { + this.ctx.logger.debug("setting default identity volume_expansion caps"); + + options.service.identity.capabilities.volume_expansion = [ + "UNKNOWN", + //"ONLINE", + //"OFFLINE" + ]; + } + + if (!("rpc" in options.service.controller.capabilities)) { + this.ctx.logger.debug("setting default controller caps"); + + options.service.controller.capabilities.rpc = [ + //"UNKNOWN", + //"CREATE_DELETE_VOLUME", + //"PUBLISH_UNPUBLISH_VOLUME", + //"LIST_VOLUMES", + //"GET_CAPACITY", + //"CREATE_DELETE_SNAPSHOT", + //"LIST_SNAPSHOTS", + //"CLONE_VOLUME", + //"PUBLISH_READONLY", + //"EXPAND_VOLUME" + ]; + } + + if (!("rpc" in options.service.node.capabilities)) { + this.ctx.logger.debug("setting default node caps"); + options.service.node.capabilities.rpc = [ + //"UNKNOWN", + //"STAGE_UNSTAGE_VOLUME", + "GET_VOLUME_STATS", + //"EXPAND_VOLUME", + ]; + } + } + + getSshClient() { + return new SshClient({ + logger: this.ctx.logger, + connection: this.options.sshConnection, + }); + } + + getZetabyte() { + let sshClient; + let executor; + if (this.options.sshConnection) { + sshClient = this.getSshClient(); + executor = new ZfsSshProcessManager(sshClient); + } + return new Zetabyte({ + executor, + idempotent: true, + chroot: this.options.zfs.chroot, + paths: { + zpool: "/usr/sbin/zpool", + zfs: "/usr/sbin/zfs", + }, + }); + } + + getDatasetParentName() { + let datasetParentName = this.options.zfs.datasetParentName; + datasetParentName = datasetParentName.replace(/\/$/, ""); + return datasetParentName; + } + + getVolumeParentDatasetName() { + let datasetParentName = this.getDatasetParentName(); + datasetParentName += "/v"; + datasetParentName = datasetParentName.replace(/\/$/, ""); + return datasetParentName; + } + + assertCapabilities(capabilities) { + // hard code this for now + const driverZfsResourceType = "filesystem"; + this.ctx.logger.verbose("validating capabilities: %j", capabilities); + + let message = null; + //[{"access_mode":{"mode":"SINGLE_NODE_WRITER"},"mount":{"mount_flags":["noatime","_netdev"],"fs_type":"nfs"},"access_type":"mount"}] + const valid = capabilities.every((capability) => { + switch (driverZfsResourceType) { + case "filesystem": + if (capability.access_type != "mount") { + message = `invalid access_type ${capability.access_type}`; + return false; + } + + if ( + capability.mount.fs_type && + !["zfs"].includes(capability.mount.fs_type) + ) { + message = `invalid fs_type ${capability.mount.fs_type}`; + return false; + } + + if ( + capability.mount.mount_flags && + capability.mount.mount_flags.length > 0 + ) { + message = `invalid mount_flags ${capability.mount.mount_flags}`; + return false; + } + + if ( + ![ + "UNKNOWN", + "SINGLE_NODE_WRITER", + "SINGLE_NODE_READER_ONLY", + ].includes(capability.access_mode.mode) + ) { + message = `invalid access_mode, ${capability.access_mode.mode}`; + return false; + } + + return true; + case "volume": + if (capability.access_type == "mount") { + if ( + capability.mount.fs_type && + !["ext3", "ext4", "ext4dev", "xfs"].includes( + capability.mount.fs_type + ) + ) { + message = `invalid fs_type ${capability.mount.fs_type}`; + return false; + } + } + + if ( + ![ + "UNKNOWN", + "SINGLE_NODE_WRITER", + "SINGLE_NODE_READER_ONLY", + ].includes(capability.access_mode.mode) + ) { + message = `invalid access_mode, ${capability.access_mode.mode}`; + return false; + } + + return true; + } + }); + + return { valid, message }; + } + + /** + * This should create a dataset with appropriate volume properties, ensuring + * the mountpoint is the target_path + * + * Any volume_context attributes starting with property. will be set as zfs properties + * + * { + "target_path": "/var/lib/kubelet/pods/f8b237db-19e8-44ae-b1d2-740c9aeea702/volumes/kubernetes.io~csi/my-volume-0/mount", + "volume_capability": { + "AccessType": { + "Mount": {} + }, + "access_mode": { + "mode": 1 + } + }, + "volume_context": { + "csi.storage.k8s.io/ephemeral": "true", + "csi.storage.k8s.io/pod.name": "inline-volume-tester-2ptb7", + "csi.storage.k8s.io/pod.namespace": "ephemeral-468", + "csi.storage.k8s.io/pod.uid": "f8b237db-19e8-44ae-b1d2-740c9aeea702", + "csi.storage.k8s.io/serviceAccount.name": "default", + "foo": "bar" + }, + "volume_id": "csi-8228252978a824126924de00126e6aec7c989a48a39d577bd3ab718647df5555" + } + * + * @param {*} call + */ + async NodePublishVolume(call) { + const driver = this; + const zb = this.getZetabyte(); + + const volume_id = call.request.volume_id; + const staging_target_path = call.request.staging_target_path || ""; + const target_path = call.request.target_path; + const capability = call.request.volume_capability; + const access_type = capability.access_type || "mount"; + const readonly = call.request.readonly; + const volume_context = call.request.volume_context; + + let datasetParentName = this.getVolumeParentDatasetName(); + let name = volume_id; + + if (!datasetParentName) { + throw new GrpcError( + grpc.status.FAILED_PRECONDITION, + `invalid configuration: missing datasetParentName` + ); + } + + if (!name) { + throw new GrpcError( + grpc.status.INVALID_ARGUMENT, + `volume_id is required` + ); + } + + if (!target_path) { + throw new GrpcError( + grpc.status.INVALID_ARGUMENT, + `target_path is required` + ); + } + + if (capability) { + const result = this.assertCapabilities([capability]); + + if (result.valid !== true) { + throw new GrpcError(grpc.status.INVALID_ARGUMENT, result.message); + } + } + + const datasetName = datasetParentName + "/" + name; + + // TODO: support arbitrary values from config + // TODO: support arbitrary props from volume_context + let volumeProperties = {}; + + // set user-supplied properties + // this come from volume_context from keys starting with property. + const base_key = "property."; + const prefixLength = `${base_key}`.length; + Object.keys(volume_context).forEach(function (key) { + if (key.startsWith(base_key)) { + let normalizedKey = key.slice(prefixLength); + volumeProperties[normalizedKey] = volume_context[key]; + } + }); + + // set standard properties + volumeProperties[VOLUME_CSI_NAME_PROPERTY_NAME] = name; + volumeProperties[MANAGED_PROPERTY_NAME] = "true"; + volumeProperties[VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME] = + driver.options.driver; + if (driver.options.instance_id) { + volumeProperties[VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME] = + driver.options.instance_id; + } + volumeProperties[SUCCESS_PROPERTY_NAME] = "true"; + + // NOTE: setting mountpoint will automatically create the full path as necessary so no need for mkdir etc + volumeProperties["mountpoint"] = target_path; + + // does not really make sense for ephemeral volumes..but we'll put it here in case + if (readonly) { + volumeProperties["readonly"] = "on"; + } + + // set driver config properties + if (this.options.zfs.properties) { + Object.keys(driver.options.zfs.properties).forEach(function (key) { + const value = driver.options.zfs.properties[key]["value"]; + const allowOverride = + "allowOverride" in driver.options.zfs.properties[key] + ? driver.options.zfs.properties[key]["allowOverride"] + : true; + + if (!allowOverride || !(key in volumeProperties)) { + volumeProperties[key] = value; + } + }); + } + + await zb.zfs.create(datasetName, { + parents: true, + properties: volumeProperties, + }); + + return {}; + } + + /** + * This should destroy the dataset and remove target_path as appropriate + * + *{ + "target_path": "/var/lib/kubelet/pods/f8b237db-19e8-44ae-b1d2-740c9aeea702/volumes/kubernetes.io~csi/my-volume-0/mount", + "volume_id": "csi-8228252978a824126924de00126e6aec7c989a48a39d577bd3ab718647df5555" + } + * + * @param {*} call + */ + async NodeUnpublishVolume(call) { + const zb = this.getZetabyte(); + const filesystem = new Filesystem(); + let result; + + const volume_id = call.request.volume_id; + const target_path = call.request.target_path; + + let datasetParentName = this.getVolumeParentDatasetName(); + let name = volume_id; + + if (!datasetParentName) { + throw new GrpcError( + grpc.status.FAILED_PRECONDITION, + `invalid configuration: missing datasetParentName` + ); + } + + if (!name) { + throw new GrpcError( + grpc.status.INVALID_ARGUMENT, + `volume_id is required` + ); + } + + if (!target_path) { + throw new GrpcError( + grpc.status.INVALID_ARGUMENT, + `target_path is required` + ); + } + + const datasetName = datasetParentName + "/" + name; + + // NOTE: -f does NOT allow deletes if dependent filesets exist + // NOTE: -R will recursively delete items + dependent filesets + // delete dataset + try { + await zb.zfs.destroy(datasetName, { recurse: true, force: true }); + } catch (err) { + if (err.toString().includes("filesystem has dependent clones")) { + throw new GrpcError( + grpc.status.FAILED_PRECONDITION, + "filesystem has dependent clones" + ); + } + + throw err; + } + + // cleanup publish directory + result = await filesystem.pathExists(target_path); + if (result) { + if (fs.lstatSync(target_path).isDirectory()) { + result = await filesystem.rmdir(target_path); + } else { + result = await filesystem.rm([target_path]); + } + } + + return {}; + } + + /** + * TODO: consider volume_capabilities? + * + * @param {*} call + */ + async GetCapacity(call) { + const driver = this; + const zb = this.getZetabyte(); + + let datasetParentName = this.getVolumeParentDatasetName(); + + if (!datasetParentName) { + throw new GrpcError( + grpc.status.FAILED_PRECONDITION, + `invalid configuration: missing datasetParentName` + ); + } + + if (call.request.volume_capabilities) { + const result = this.assertCapabilities(call.request.volume_capabilities); + + if (result.valid !== true) { + return { available_capacity: 0 }; + } + } + + const datasetName = datasetParentName; + + let properties; + properties = await zb.zfs.get(datasetName, ["avail"]); + properties = properties[datasetName]; + + return { available_capacity: properties.available.value }; + } + + /** + * + * @param {*} call + */ + async ValidateVolumeCapabilities(call) { + const driver = this; + const result = this.assertCapabilities(call.request.volume_capabilities); + + if (result.valid !== true) { + return { message: result.message }; + } + + return { + confirmed: { + volume_context: call.request.volume_context, + volume_capabilities: call.request.volume_capabilities, // TODO: this is a bit crude, should return *ALL* capabilities, not just what was requested + parameters: call.request.parameters, + }, + }; + } +} + +module.exports.ZfsLocalEphemeralInlineDriver = ZfsLocalEphemeralInlineDriver; diff --git a/src/utils/zfs.js b/src/utils/zfs.js index 0d189cc..b47a972 100644 --- a/src/utils/zfs.js +++ b/src/utils/zfs.js @@ -19,13 +19,17 @@ class Zetabyte { options.paths.sudo = "/usr/bin/sudo"; } + if (!options.paths.chroot) { + options.paths.chroot = "/usr/sbin/chroot"; + } + if (!options.timeout) { options.timeout = 10 * 60 * 1000; } if (!options.executor) { options.executor = { - spawn: cp.spawn + spawn: cp.spawn, }; } @@ -36,7 +40,7 @@ class Zetabyte { "free", "cap", "health", - "altroot" + "altroot", ]; zb.DEFAULT_ZFS_LIST_PROPERTIES = [ @@ -45,11 +49,11 @@ class Zetabyte { "avail", "refer", "type", - "mountpoint" + "mountpoint", ]; zb.helpers = { - zfsErrorStr: function(error, stderr) { + zfsErrorStr: function (error, stderr) { if (!error) return null; if (error.killed) return "Process killed due to timeout."; @@ -57,11 +61,11 @@ class Zetabyte { return error.message || (stderr ? stderr.toString() : ""); }, - zfsError: function(error, stderr) { + zfsError: function (error, stderr) { return new Error(zb.helpers.zfsErrorStr(error, stderr)); }, - parseTabSeperatedTable: function(data) { + parseTabSeperatedTable: function (data) { if (!data) { return []; } @@ -86,7 +90,7 @@ class Zetabyte { * * and those fields are tab-separated. */ - parsePropertyList: function(data) { + parsePropertyList: function (data) { if (!data) { return {}; } @@ -94,22 +98,22 @@ class Zetabyte { const lines = data.trim().split("\n"); const properties = {}; - lines.forEach(function(line) { + lines.forEach(function (line) { const fields = line.split("\t"); if (!properties[fields[0]]) properties[fields[0]] = {}; properties[fields[0]][fields[1]] = { value: fields[2], received: fields[3], - source: fields[4] + source: fields[4], }; }); return properties; }, - listTableToPropertyList: function(properties, data) { + listTableToPropertyList: function (properties, data) { const entries = []; - data.forEach(row => { + data.forEach((row) => { let entry = {}; properties.forEach((value, index) => { entry[value] = row[index]; @@ -120,11 +124,11 @@ class Zetabyte { return entries; }, - extractSnapshotName: function(datasetName) { + extractSnapshotName: function (datasetName) { return datasetName.substring(datasetName.indexOf("@") + 1); }, - extractDatasetName: function(datasetName) { + extractDatasetName: function (datasetName) { if (datasetName.includes("@")) { return datasetName.substring(0, datasetName.indexOf("@")); } @@ -132,26 +136,26 @@ class Zetabyte { return datasetName; }, - isZfsSnapshot: function(snapshotName) { + isZfsSnapshot: function (snapshotName) { return snapshotName.includes("@"); }, - extractPool: function(datasetName) { + extractPool: function (datasetName) { const parts = datasetName.split("/"); return parts[0]; }, - extractParentDatasetName: function(datasetName) { + extractParentDatasetName: function (datasetName) { const parts = datasetName.split("/"); parts.pop(); return parts.join("/"); }, - extractLeafName: function(datasetName) { + extractLeafName: function (datasetName) { return datasetName.split("/").pop(); }, - isPropertyValueSet: function(value) { + isPropertyValueSet: function (value) { if ( value === undefined || value === null || @@ -164,7 +168,7 @@ class Zetabyte { return true; }, - generateZvolSize: function(capacity_bytes, block_size) { + generateZvolSize: function (capacity_bytes, block_size) { block_size = "" + block_size; block_size = block_size.toLowerCase(); switch (block_size) { @@ -211,7 +215,7 @@ class Zetabyte { result = Number(result) + Number(block_size); return result; - } + }, }; zb.zpool = { @@ -221,7 +225,7 @@ class Zetabyte { * @param {*} pool * @param {*} vdevs */ - add: function(pool, vdevs) { + add: function (pool, vdevs) { // -f force // -n noop }, @@ -233,7 +237,7 @@ class Zetabyte { * @param {*} device * @param {*} new_device */ - attach: function(pool, device, new_device) { + attach: function (pool, device, new_device) { // -f Forces use of new_device, even if its appears to be in use. }, @@ -242,7 +246,7 @@ class Zetabyte { * * @param {*} pool */ - checkpoint: function(pool) {}, + checkpoint: function (pool) {}, /** * zpool clear [-F [-n]] pool [device] @@ -250,7 +254,7 @@ class Zetabyte { * @param {*} pool * @param {*} device */ - clear: function(pool, device) {}, + clear: function (pool, device) {}, /** * zpool create [-fnd] [-o property=value] ... [-O @@ -261,7 +265,7 @@ class Zetabyte { * zpool create command, including log devices, cache devices, and hot spares. * The input is an object of the form produced by the disklayout library. */ - create: function(pool, options) { + create: function (pool, options) { if (arguments.length != 2) throw Error("Invalid arguments, 2 arguments required"); @@ -290,10 +294,10 @@ class Zetabyte { if (options.tempname) args = args.concat(["-t", options.tempname]); args.push(pool); - options.vdevs.forEach(function(vdev) { + options.vdevs.forEach(function (vdev) { if (vdev.type) args.push(vdev.type); if (vdev.devices) { - vdev.devices.forEach(function(dev) { + vdev.devices.forEach(function (dev) { args.push(dev.name); }); } else { @@ -303,21 +307,21 @@ class Zetabyte { if (options.spares) { args.push("spare"); - options.spares.forEach(function(dev) { + options.spares.forEach(function (dev) { args.push(dev.name); }); } if (options.logs) { args.push("log"); - options.logs.forEach(function(dev) { + options.logs.forEach(function (dev) { args.push(dev.name); }); } if (options.cache) { args.push("cache"); - options.cache.forEach(function(dev) { + options.cache.forEach(function (dev) { args.push(dev.name); }); } @@ -326,7 +330,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -339,7 +343,7 @@ class Zetabyte { * * @param {*} pool */ - destroy: function(pool) { + destroy: function (pool) { if (arguments.length != 1) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -352,7 +356,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -366,7 +370,7 @@ class Zetabyte { * @param {*} pool * @param {*} device */ - detach: function(pool, device) { + detach: function (pool, device) { if (arguments.length != 2) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -379,7 +383,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -392,7 +396,7 @@ class Zetabyte { * * @param {*} pool */ - export: function(pool) { + export: function (pool) { if (arguments.length != 2) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -400,7 +404,7 @@ class Zetabyte { args.push("export"); if (options.force) args.push("-f"); if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -411,7 +415,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -422,21 +426,21 @@ class Zetabyte { /** * zpool get [-Hp] [-o field[,...]] all | property[,...] pool ... */ - get: function() {}, + get: function () {}, /** * zpool history [-il] [pool] ... * * @param {*} pool */ - history: function(pool) { + history: function (pool) { return new Promise((resolve, reject) => { let args = []; args.push("history"); if (options.internal) args.push("-i"); if (options.longFormat) args.push("-l"); if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -447,7 +451,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -468,7 +472,7 @@ class Zetabyte { * * @param {*} options */ - import: function(options = {}) { + import: function (options = {}) { return new Promise((resolve, reject) => { let args = []; args.push("import"); @@ -480,7 +484,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -493,14 +497,14 @@ class Zetabyte { * * @param {*} options */ - iostat: function(options = {}) {}, + iostat: function (options = {}) {}, /** * zpool labelclear [-f] device * * @param {*} device */ - labelclear: function(device) {}, + labelclear: function (device) {}, /** * zpool list [-Hpv] [-o property[,...]] [-T d|u] [pool] ... [inverval @@ -509,7 +513,7 @@ class Zetabyte { * @param {*} pool * @param {*} options */ - list: function(pool, properties, options = {}) { + list: function (pool, properties, options = {}) { if (!(arguments.length >= 1)) throw Error("Invalid arguments"); if (!properties) properties = zb.DEFAULT_ZPOOL_LIST_PROPERTIES; @@ -535,7 +539,7 @@ class Zetabyte { if (options.timestamp) args = args.concat(["-T", options.timestamp]); if (pool) { if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -549,7 +553,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); if (options.parse) { let data = zb.helpers.parseTabSeperatedTable(stdout); @@ -560,7 +564,7 @@ class Zetabyte { return resolve({ properties, data, - indexed + indexed, }); } return resolve({ properties, data: stdout }); @@ -576,7 +580,7 @@ class Zetabyte { * @param {*} device * @param {*} options */ - offline: function(pool, device, options = {}) { + offline: function (pool, device, options = {}) { return new Promise((resolve, reject) => { let args = []; args.push("offline"); @@ -588,7 +592,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -603,7 +607,7 @@ class Zetabyte { * @param {*} device * @param {*} options */ - online: function(pool, device, options = {}) { + online: function (pool, device, options = {}) { return new Promise((resolve, reject) => { let args = []; args.push("online"); @@ -615,7 +619,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -628,7 +632,7 @@ class Zetabyte { * * @param {*} pool */ - reguid: function(pool) { + reguid: function (pool) { return new Promise((resolve, reject) => { let args = []; args.push("reguid"); @@ -638,7 +642,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -654,7 +658,7 @@ class Zetabyte { * @param {*} pool * @param {*} device */ - remove: function(pool, device, options = {}) { + remove: function (pool, device, options = {}) { return new Promise((resolve, reject) => { let args = []; args.push("remove"); @@ -670,7 +674,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -683,7 +687,7 @@ class Zetabyte { * * @param {*} pool */ - reopen: function(pool) { + reopen: function (pool) { return new Promise((resolve, reject) => { let args = []; args.push("reopen"); @@ -693,7 +697,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -708,7 +712,7 @@ class Zetabyte { * @param {*} device * @param {*} new_device */ - replace: function(pool, device, new_device) { + replace: function (pool, device, new_device) { return new Promise((resolve, reject) => { let args = []; args.push("replace"); @@ -723,7 +727,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -736,14 +740,14 @@ class Zetabyte { * * @param {*} pool */ - scrub: function(pool) { + scrub: function (pool) { return new Promise((resolve, reject) => { let args = []; args.push("scrub"); if (options.stop) args.push("-s"); if (options.pause) args.push("-p"); if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -754,7 +758,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -769,7 +773,7 @@ class Zetabyte { * @param {*} property * @param {*} value */ - set: function(pool, property, value) { + set: function (pool, property, value) { return new Promise((resolve, reject) => { let args = []; args.push("set"); @@ -780,7 +784,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } @@ -796,12 +800,12 @@ class Zetabyte { * @param {*} newpool * @param {*} device */ - split: function(pool, newpool, device) {}, + split: function (pool, newpool, device) {}, /** * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] */ - status: function(pool, options = {}) { + status: function (pool, options = {}) { return new Promise((resolve, reject) => { let args = []; if (!("parse" in options)) options.parse = true; @@ -811,7 +815,7 @@ class Zetabyte { if (options.timestamp) args = args.concat(["-T", options.timestamp]); if (pool) { if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -825,7 +829,7 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (options.parse) { stdout = stdout.trim(); if (error || stdout == "no pools available\n") { @@ -855,7 +859,7 @@ class Zetabyte { * * @param {*} pool */ - upgrade: function(pool) { + upgrade: function (pool) { return new Promise((resolve, reject) => { let args = []; args.push("upgrade"); @@ -863,7 +867,7 @@ class Zetabyte { if (options.all) args.push("-a"); if (pool) { if (Array.isArray(pool)) { - pool.forEach(item => { + pool.forEach((item) => { args.push(item); }); } else { @@ -875,13 +879,13 @@ class Zetabyte { zb.options.paths.zpool, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(stderr); return resolve(stdout); } ); }); - } + }, }; zb.zfs = { @@ -892,7 +896,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - create: function(dataset, options = {}) { + create: function (dataset, options = {}) { if (!(arguments.length >= 1)) throw new (Error("Invalid arguments"))(); return new Promise((resolve, reject) => { @@ -921,7 +925,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if ( error && !(idempotent && stderr.includes("dataset already exists")) @@ -942,7 +946,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - destroy: function(dataset, options = {}) { + destroy: function (dataset, options = {}) { if (!(arguments.length >= 1)) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -969,7 +973,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if ( error && !( @@ -993,7 +997,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - snapshot: function(dataset, options = {}) { + snapshot: function (dataset, options = {}) { if (!(arguments.length >= 1)) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1022,7 +1026,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if ( error && !(idempotent && stderr.includes("dataset already exists")) @@ -1040,7 +1044,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - rollback: function(dataset, options = {}) { + rollback: function (dataset, options = {}) { if (!(arguments.length >= 1)) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1055,7 +1059,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { /** * cannot rollback to 'foo/bar/baz@foobar': more recent snapshots or bookmarks exist * use '-r' to force deletion of the following snapshots and bookmarks: @@ -1074,7 +1078,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - clone: function(snapshot, dataset, options = {}) { + clone: function (snapshot, dataset, options = {}) { if (!(arguments.length >= 2)) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1101,7 +1105,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if ( error && !(idempotent && stderr.includes("dataset already exists")) @@ -1139,7 +1143,7 @@ class Zetabyte { args.push("'" + command.join(" ") + "'"); - zb.exec("/bin/sh", args, { timeout: zb.options.timeout }, function( + zb.exec("/bin/sh", args, { timeout: zb.options.timeout }, function ( error, stdout, stderr @@ -1155,7 +1159,7 @@ class Zetabyte { * * @param {*} dataset */ - promote: function(dataset) { + promote: function (dataset) { if (arguments.length != 1) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1167,7 +1171,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } @@ -1185,7 +1189,7 @@ class Zetabyte { * @param {*} target * @param {*} options */ - rename: function(source, target, options = {}) { + rename: function (source, target, options = {}) { if (!(arguments.length >= 2)) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1202,7 +1206,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } @@ -1218,7 +1222,7 @@ class Zetabyte { * @param {*} dataset * @param {*} options */ - list: function(dataset, properties, options = {}) { + list: function (dataset, properties, options = {}) { if (!(arguments.length >= 1)) throw Error("Invalid arguments"); if (!properties) properties = zb.DEFAULT_ZFS_LIST_PROPERTIES; @@ -1258,7 +1262,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); if (options.parse) { let data = zb.helpers.parseTabSeperatedTable(stdout); @@ -1269,7 +1273,7 @@ class Zetabyte { return resolve({ properties, data, - indexed + indexed, }); } return resolve({ properties, data: stdout }); @@ -1284,7 +1288,7 @@ class Zetabyte { * @param {*} dataset * @param {*} properties */ - set: function(dataset, properties) { + set: function (dataset, properties) { if (arguments.length != 2) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1307,7 +1311,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } @@ -1327,7 +1331,7 @@ class Zetabyte { * @param {*} dataset * @param {*} properties */ - get: function(dataset, properties = "all", options = {}) { + get: function (dataset, properties = "all", options = {}) { if (!(arguments.length >= 2)) throw Error("Invalid arguments"); if (!properties) properties = "all"; if (Array.isArray(properties) && !properties.length > 0) @@ -1344,7 +1348,7 @@ class Zetabyte { if (options.parse) args = args.concat([ "-o", - ["name", "property", "value", "received", "source"] + ["name", "property", "value", "received", "source"], ]); if (options.fields && !options.parse) { let fields; @@ -1394,7 +1398,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); if (options.parse) { return resolve(zb.helpers.parsePropertyList(stdout)); @@ -1411,7 +1415,7 @@ class Zetabyte { * @param {*} dataset * @param {*} property */ - inherit: function(dataset, property) { + inherit: function (dataset, property) { if (arguments.length != 2) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1426,7 +1430,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } @@ -1439,7 +1443,7 @@ class Zetabyte { * * @param {*} dataset */ - remap: function(dataset) { + remap: function (dataset) { if (arguments.length != 1) throw Error("Invalid arguments"); return new Promise((resolve, reject) => { @@ -1451,7 +1455,7 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } @@ -1465,7 +1469,7 @@ class Zetabyte { * * @param {*} dataset */ - upgrade: function(options = {}, dataset) { + upgrade: function (options = {}, dataset) { return new Promise((resolve, reject) => { let args = []; args.push("upgrade"); @@ -1481,13 +1485,13 @@ class Zetabyte { zb.options.paths.zfs, args, { timeout: zb.options.timeout }, - function(error, stdout, stderr) { + function (error, stdout, stderr) { if (error) return reject(zb.helpers.zfsError(error, stderr)); return resolve(stdout); } ); }); - } + }, }; } @@ -1518,6 +1522,13 @@ class Zetabyte { break; } + if (zb.options.chroot) { + args = args || []; + args.unshift(command); + args.unshift(zb.options.chroot); + command = zb.options.paths.chroot; + } + if (zb.options.sudo) { args = args || []; args.unshift(command); @@ -1535,15 +1546,15 @@ class Zetabyte { } if (callback) { - child.stdout.on("data", function(data) { + child.stdout.on("data", function (data) { stdout = stdout + data; }); - child.stderr.on("data", function(data) { + child.stderr.on("data", function (data) { stderr = stderr + data; }); - child.on("close", function(error) { + child.on("close", function (error) { if (timeout) { clearTimeout(timeout); } @@ -1600,7 +1611,7 @@ class ZfsSshProcessManager { proxy.stdout = stdout; proxy.stderr = stderr; - proxy.kill = function(signal = "SIGTERM") { + proxy.kill = function (signal = "SIGTERM") { proxy.emit("kill", signal); }; @@ -1609,7 +1620,7 @@ class ZfsSshProcessManager { client.debug("ZfsProcessManager arguments: " + JSON.stringify(arguments)); client.logger.verbose("ZfsProcessManager command: " + command); - client.exec(command, {}, proxy).catch(err => { + client.exec(command, {}, proxy).catch((err) => { proxy.stderr.emit("data", err.message); proxy.emit("close", 1, "SIGQUIT"); });