parameters which help the project to gain a better understanding of
the way Ceph is used.
-Data is sent over HTTPS to *telemetry.ceph.com*.
+Data is sent secured to *https://telemetry.ceph.com*.
Sample report
-------------
- tasks.mgr.dashboard.test_role
- tasks.mgr.dashboard.test_settings
- tasks.mgr.dashboard.test_summary
+ - tasks.mgr.dashboard.test_telemetry
- tasks.mgr.dashboard.test_user
--- /dev/null
+from .helper import DashboardTestCase, JObj
+
+
+class TelemetryTest(DashboardTestCase):
+
+ pre_enabled_status = True
+
+ @classmethod
+ def setUpClass(cls):
+ super(TelemetryTest, cls).setUpClass()
+ data = cls._get('/api/mgr/module/telemetry')
+ cls.pre_enabled_status = data['enabled']
+
+ @classmethod
+ def tearDownClass(cls):
+ if cls.pre_enabled_status:
+ cls._enable_module()
+ else:
+ cls._disable_module()
+ super(TelemetryTest, cls).tearDownClass()
+
+ def test_disable_module(self):
+ self._enable_module()
+ self._check_telemetry_enabled(True)
+ self._disable_module()
+ self._check_telemetry_enabled(False)
+
+ def test_enable_module_correct_license(self):
+ self._disable_module()
+ self._check_telemetry_enabled(False)
+
+ self._put('/api/telemetry', {
+ 'enable': True,
+ 'license_name': 'sharing-1-0'
+ })
+ self.assertStatus(200)
+ self._check_telemetry_enabled(True)
+
+ def test_enable_module_empty_license(self):
+ self._disable_module()
+ self._check_telemetry_enabled(False)
+
+ self._put('/api/telemetry', {
+ 'enable': True,
+ 'license_name': ''
+ })
+ self.assertStatus(400)
+ self.assertError(code='telemetry_enable_license_missing')
+ self._check_telemetry_enabled(False)
+
+ def test_enable_module_invalid_license(self):
+ self._disable_module()
+ self._check_telemetry_enabled(False)
+
+ self._put('/api/telemetry', {
+ 'enable': True,
+ 'license_name': 'invalid-license'
+ })
+ self.assertStatus(400)
+ self.assertError(code='telemetry_enable_license_missing')
+ self._check_telemetry_enabled(False)
+
+ def test_get_report(self):
+ self._enable_module()
+ data = self._get('/api/telemetry/report')
+ self.assertStatus(200)
+ schema = JObj({
+ 'report': JObj({}, allow_unknown=True),
+ 'device_report': JObj({}, allow_unknown=True)
+ })
+ self.assertSchema(data, schema)
+
+ @classmethod
+ def _enable_module(cls):
+ cls._put('/api/telemetry', {
+ 'enable': True,
+ 'license_name': 'sharing-1-0'
+ })
+
+ @classmethod
+ def _disable_module(cls):
+ cls._put('/api/telemetry', {
+ 'enable': False
+ })
+
+ def _check_telemetry_enabled(self, enabled):
+ data = self._get('/api/mgr/module/telemetry')
+ self.assertStatus(200)
+ self.assertEqual(data['enabled'], enabled)
* bulk_delete()
* get(key)
* set(data, key)
+ * singleton_set(data)
* delete(key)
Test with curl:
('bulk_delete', {'method': 'DELETE', 'resource': False, 'status': 204}),
('get', {'method': 'GET', 'resource': True, 'status': 200}),
('delete', {'method': 'DELETE', 'resource': True, 'status': 204}),
- ('set', {'method': 'PUT', 'resource': True, 'status': 200})
+ ('set', {'method': 'PUT', 'resource': True, 'status': 200}),
+ ('singleton_set', {'method': 'PUT', 'resource': False, 'status': 200})
])
@classmethod
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from . import ApiController, RESTController
+from .. import mgr
+from ..exceptions import DashboardException
+from ..security import Scope
+
+
+@ApiController('/telemetry', Scope.CONFIG_OPT)
+class Telemetry(RESTController):
+
+ @RESTController.Collection('GET')
+ def report(self):
+ """
+ Get Ceph and device report data
+ :return: Ceph and device report data
+ :rtype: dict
+ """
+ return mgr.remote('telemetry', 'get_report', 'all')
+
+ def singleton_set(self, enable=True, license_name=None):
+ """
+ Enables or disables sending data collected by the Telemetry
+ module.
+ :param enable: Enable or disable sending data
+ :type enable: bool
+ :param license_name: License string e.g. 'sharing-1-0' to
+ make sure the user is aware of and accepts the license
+ for sharing Telemetry data.
+ :type license_name: string
+ """
+ if enable:
+ if not license_name or (license_name != 'sharing-1-0'):
+ raise DashboardException(
+ code='telemetry_enable_license_missing',
+ msg='Telemetry data is licensed under the Community Data License Agreement - '
+ 'Sharing - Version 1.0 (https://cdla.io/sharing-1-0/). To enable, add '
+ '{"license": "sharing-1-0"} to the request payload.'
+ )
+ mgr.remote('telemetry', 'on')
+ else:
+ mgr.remote('telemetry', 'off')
}
},
"fsevents": {
- "dev": true,
- "optional": true,
- "requires": {
- "node-pre-gyp": "*"
- },
"dependencies": {
- "abbrev": {
+ "npm-bundled": {
"version": "1.1.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
},
- "aproba": {
- "version": "1.2.0",
+ "semver": {
+ "version": "5.7.1",
"bundled": true,
- "dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
- "balanced-match": {
- "version": "1.0.0",
+ "safe-buffer": {
+ "version": "5.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "brace-expansion": {
- "version": "1.1.11",
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
}
},
- "chownr": {
- "version": "1.1.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
+ "safer-buffer": {
+ "version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "concat-map": {
- "version": "0.0.1",
+ "wide-align": {
+ "version": "1.1.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
},
- "console-control-strings": {
- "version": "1.1.0",
+ "once": {
+ "version": "1.4.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
},
- "core-util-is": {
- "version": "1.0.2",
+ "strip-ansi": {
+ "version": "3.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
},
- "debug": {
- "version": "3.2.6",
+ "nopt": {
+ "version": "4.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ms": "^2.1.1"
+ "abbrev": "1",
+ "osenv": "^0.1.4"
}
},
- "deep-extend": {
- "version": "0.6.0",
+ "console-control-strings": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "delegates": {
+ "fs.realpath": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "detect-libc": {
- "version": "1.0.3",
+ "tar": {
+ "version": "4.4.13",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
},
- "fs-minipass": {
- "version": "1.2.7",
+ "brace-expansion": {
+ "version": "1.1.11",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minipass": "^2.6.0"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "fs.realpath": {
- "version": "1.0.0",
+ "os-tmpdir": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "gauge": {
- "version": "2.7.4",
+ "minipass": {
+ "version": "2.9.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
}
},
- "glob": {
- "version": "7.1.6",
+ "yallist": {
+ "version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
+ "optional": true
},
- "has-unicode": {
- "version": "2.0.1",
+ "code-point-at": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "iconv-lite": {
- "version": "0.4.24",
+ "rc": {
+ "version": "1.2.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
}
},
- "ignore-walk": {
- "version": "3.0.3",
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "minizlib": {
+ "version": "1.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minimatch": "^3.0.4"
+ "minipass": "^2.9.0"
}
},
- "inflight": {
- "version": "1.0.6",
+ "osenv": {
+ "version": "0.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
}
},
- "inherits": {
- "version": "2.0.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
+ "signal-exit": {
+ "version": "3.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
- "isarray": {
- "version": "1.0.0",
+ "sax": {
+ "version": "1.2.4",
"bundled": true,
- "dev": true,
"optional": true
},
- "minimatch": {
- "version": "3.0.4",
+ "node-pre-gyp": {
+ "version": "0.14.0",
"bundled": true,
- "dev": true,
- "optional": true,
"requires": {
- "brace-expansion": "^1.1.7"
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
}
},
- "minimist": {
- "version": "1.2.5",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "minipass": {
- "version": "2.9.0",
+ "gauge": {
+ "version": "2.7.4",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
}
},
- "minizlib": {
- "version": "1.3.3",
+ "ansi-regex": {
+ "version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "^2.9.0"
- }
+ "optional": true
},
- "mkdirp": {
- "version": "0.5.3",
+ "has-unicode": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "optional": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
},
"ms": {
"version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "needle": {
- "version": "2.3.3",
+ "readable-stream": {
+ "version": "2.3.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
+ "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"
}
},
- "node-pre-gyp": {
- "version": "0.14.0",
+ "aproba": {
+ "version": "1.2.0",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4.4.2"
- }
+ "optional": true
},
- "nopt": {
- "version": "4.0.3",
+ "strip-json-comments": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
+ "optional": true
},
- "npm-bundled": {
- "version": "1.1.1",
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "npm-normalize-package-bin": "^1.0.1"
+ "ms": "^2.1.1"
}
},
- "npm-normalize-package-bin": {
- "version": "1.0.1",
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "chownr": {
+ "version": "1.1.4",
"bundled": true,
- "dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"ignore-walk": "^3.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
- "npmlog": {
- "version": "4.1.2",
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
}
},
- "number-is-nan": {
+ "npm-normalize-package-bin": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "dev": true,
"optional": true
},
- "once": {
- "version": "1.4.0",
+ "needle": {
+ "version": "2.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "wrappy": "1"
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
}
},
- "os-homedir": {
- "version": "1.0.2",
+ "ini": {
+ "version": "1.3.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "os-tmpdir": {
- "version": "1.0.2",
+ "minimatch": {
+ "version": "3.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
},
- "osenv": {
- "version": "0.1.5",
+ "mkdirp": {
+ "version": "0.5.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
+ "minimist": "^1.2.5"
}
},
- "path-is-absolute": {
- "version": "1.0.1",
+ "set-blocking": {
+ "version": "2.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "process-nextick-args": {
- "version": "2.0.1",
+ "wrappy": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "rc": {
- "version": "1.2.8",
+ "fs-minipass": {
+ "version": "1.2.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
+ "minipass": "^2.6.0"
}
},
- "readable-stream": {
- "version": "2.3.7",
+ "core-util-is": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true,
- "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"
- }
+ "optional": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
},
"rimraf": {
"version": "2.7.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"glob": "^7.1.3"
}
},
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
+ "minimist": {
+ "version": "1.2.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "semver": {
- "version": "5.7.1",
+ "glob": {
+ "version": "7.1.6",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
},
- "set-blocking": {
- "version": "2.0.0",
+ "object-assign": {
+ "version": "4.1.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "signal-exit": {
- "version": "3.0.2",
+ "delegates": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "string-width": {
- "version": "1.0.2",
+ "ignore-walk": {
+ "version": "3.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
+ "minimatch": "^3.0.4"
}
},
- "string_decoder": {
- "version": "1.1.1",
+ "inflight": {
+ "version": "1.0.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "ansi-regex": "^2.0.0"
+ "once": "^1.3.0",
+ "wrappy": "1"
}
},
- "strip-json-comments": {
- "version": "2.0.1",
+ "path-is-absolute": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "tar": {
- "version": "4.4.13",
+ "iconv-lite": {
+ "version": "0.4.24",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.8.6",
- "minizlib": "^1.2.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.3"
+ "safer-buffer": ">= 2.1.2 < 3"
}
},
- "util-deprecate": {
- "version": "1.0.2",
+ "detect-libc": {
+ "version": "1.0.3",
"bundled": true,
- "dev": true,
"optional": true
},
- "wide-align": {
- "version": "1.1.3",
+ "string_decoder": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "string-width": "^1.0.2 || 2"
+ "safe-buffer": "~5.1.0"
}
},
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "yallist": {
- "version": "3.1.1",
+ "abbrev": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true
}
},
}
},
"mem": {
- "dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^2.0.0",
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"os-locale": {
"version": "3.1.0",
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
"dev": true
},
+ "@types/file-saver": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.1.tgz",
+ "integrity": "sha512-g1QUuhYVVAamfCifK7oB7G3aIl4BbOyzDOqVyUfEr4tfBKrXfeH+M+Tg7HKCXSrbzxYdhyCP7z9WbKo0R2hBCw=="
+ },
"@types/glob": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
}
}
},
+ "file-saver": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
+ "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
+ },
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
- "fsevents": {
- "dev": true,
- "optional": true,
- "version": "2.1.2"
- },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
}
},
"mem": {
- "dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^2.0.0",
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"os-locale": {
"version": "3.1.0",
}
},
"fsevents": {
- "dev": true,
- "optional": true,
- "requires": {
- "node-pre-gyp": "*"
- },
"dependencies": {
- "abbrev": {
+ "npm-bundled": {
"version": "1.1.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
},
- "aproba": {
- "version": "1.2.0",
+ "semver": {
+ "version": "5.7.1",
"bundled": true,
- "dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
- "balanced-match": {
- "version": "1.0.0",
+ "safe-buffer": {
+ "version": "5.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "brace-expansion": {
- "version": "1.1.11",
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
}
},
- "chownr": {
- "version": "1.1.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
+ "safer-buffer": {
+ "version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "concat-map": {
- "version": "0.0.1",
+ "wide-align": {
+ "version": "1.1.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
},
- "console-control-strings": {
- "version": "1.1.0",
+ "once": {
+ "version": "1.4.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
},
- "core-util-is": {
- "version": "1.0.2",
+ "strip-ansi": {
+ "version": "3.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
},
- "debug": {
- "version": "3.2.6",
+ "nopt": {
+ "version": "4.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ms": "^2.1.1"
+ "abbrev": "1",
+ "osenv": "^0.1.4"
}
},
- "deep-extend": {
- "version": "0.6.0",
+ "console-control-strings": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "delegates": {
+ "fs.realpath": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "detect-libc": {
- "version": "1.0.3",
+ "tar": {
+ "version": "4.4.13",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
},
- "fs-minipass": {
- "version": "1.2.7",
+ "brace-expansion": {
+ "version": "1.1.11",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minipass": "^2.6.0"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "fs.realpath": {
- "version": "1.0.0",
+ "os-tmpdir": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "gauge": {
- "version": "2.7.4",
+ "minipass": {
+ "version": "2.9.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
}
},
- "glob": {
- "version": "7.1.6",
+ "yallist": {
+ "version": "3.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
}
},
- "has-unicode": {
- "version": "2.0.1",
+ "deep-extend": {
+ "version": "0.6.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "iconv-lite": {
- "version": "0.4.24",
+ "minizlib": {
+ "version": "1.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "minipass": "^2.9.0"
}
},
- "ignore-walk": {
- "version": "3.0.3",
+ "osenv": {
+ "version": "0.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
}
},
- "inherits": {
- "version": "2.0.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
+ "signal-exit": {
+ "version": "3.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
- "isarray": {
- "version": "1.0.0",
+ "sax": {
+ "version": "1.2.4",
"bundled": true,
- "dev": true,
"optional": true
},
- "minimatch": {
- "version": "3.0.4",
+ "node-pre-gyp": {
+ "version": "0.14.0",
"bundled": true,
- "dev": true,
- "optional": true,
"requires": {
- "brace-expansion": "^1.1.7"
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
}
},
- "minimist": {
- "version": "1.2.5",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "minipass": {
- "version": "2.9.0",
+ "gauge": {
+ "version": "2.7.4",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
}
},
- "minizlib": {
- "version": "1.3.3",
+ "ansi-regex": {
+ "version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "^2.9.0"
- }
+ "optional": true
},
- "mkdirp": {
- "version": "0.5.3",
+ "has-unicode": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "optional": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
},
"ms": {
"version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "needle": {
- "version": "2.3.3",
+ "readable-stream": {
+ "version": "2.3.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
+ "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"
}
},
- "node-pre-gyp": {
- "version": "0.14.0",
+ "aproba": {
+ "version": "1.2.0",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4.4.2"
- }
+ "optional": true
},
- "nopt": {
- "version": "4.0.3",
+ "strip-json-comments": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
+ "optional": true
},
- "npm-bundled": {
- "version": "1.1.1",
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "npm-normalize-package-bin": "^1.0.1"
+ "ms": "^2.1.1"
}
},
- "npm-normalize-package-bin": {
- "version": "1.0.1",
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "chownr": {
+ "version": "1.1.4",
"bundled": true,
- "dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"ignore-walk": "^3.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
- "npmlog": {
- "version": "4.1.2",
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
}
},
- "number-is-nan": {
+ "npm-normalize-package-bin": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "object-assign": {
- "version": "4.1.1",
+ "needle": {
+ "version": "2.3.3",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "ini": {
+ "version": "1.3.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "once": {
- "version": "1.4.0",
+ "minimatch": {
+ "version": "3.0.4",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "wrappy": "1"
+ "brace-expansion": "^1.1.7"
}
},
- "os-homedir": {
- "version": "1.0.2",
+ "mkdirp": {
+ "version": "0.5.3",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "os-tmpdir": {
+ "wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "osenv": {
- "version": "0.1.5",
+ "fs-minipass": {
+ "version": "1.2.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
+ "minipass": "^2.6.0"
}
},
- "path-is-absolute": {
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "process-nextick-args": {
- "version": "2.0.1",
+ "isarray": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "rc": {
- "version": "1.2.8",
+ "rimraf": {
+ "version": "2.7.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
+ "glob": "^7.1.3"
}
},
- "readable-stream": {
- "version": "2.3.7",
+ "minimist": {
+ "version": "1.2.5",
"bundled": true,
- "dev": true,
- "optional": true,
- "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"
- }
+ "optional": true
},
- "rimraf": {
- "version": "2.7.1",
+ "glob": {
+ "version": "7.1.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "glob": "^7.1.3"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
}
},
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "semver": {
- "version": "5.7.1",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
+ "object-assign": {
+ "version": "4.1.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "signal-exit": {
- "version": "3.0.2",
+ "delegates": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
+ "ignore-walk": {
+ "version": "3.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "~5.1.0"
+ "minimatch": "^3.0.4"
}
},
- "strip-ansi": {
- "version": "3.0.1",
+ "inflight": {
+ "version": "1.0.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "once": "^1.3.0",
+ "wrappy": "1"
}
},
- "strip-json-comments": {
- "version": "2.0.1",
+ "path-is-absolute": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "tar": {
- "version": "4.4.13",
+ "iconv-lite": {
+ "version": "0.4.24",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.8.6",
- "minizlib": "^1.2.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.3"
+ "safer-buffer": ">= 2.1.2 < 3"
}
},
- "util-deprecate": {
- "version": "1.0.2",
+ "detect-libc": {
+ "version": "1.0.3",
"bundled": true,
- "dev": true,
"optional": true
},
- "wide-align": {
- "version": "1.1.3",
+ "string_decoder": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "string-width": "^1.0.2 || 2"
+ "safe-buffer": "~5.1.0"
}
},
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "yallist": {
- "version": "3.1.1",
+ "abbrev": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true
}
},
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
- "dev": true,
"requires": {
"p-defer": "^1.0.0"
}
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
"dev": true
},
- "mem": {
- "requires": {
- "mimic-fn": "^1.0.0"
- },
- "version": "4.3.0"
- },
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
- "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
},
"mini-css-extract-plugin": {
"version": "0.8.0",
"dependencies": {
"mem": {
"version": "4.3.0"
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
}
}
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
- "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
- "dev": true
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
},
"p-each-series": {
"version": "2.1.0",
"p-is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
- "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
- "dev": true
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
},
"p-limit": {
"version": "1.3.0",
}
},
"fsevents": {
- "dev": true,
- "optional": true,
- "requires": {
- "node-pre-gyp": "*"
- },
"dependencies": {
- "abbrev": {
+ "npm-bundled": {
"version": "1.1.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
},
- "aproba": {
- "version": "1.2.0",
+ "semver": {
+ "version": "5.7.1",
"bundled": true,
- "dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
- "balanced-match": {
- "version": "1.0.0",
+ "safe-buffer": {
+ "version": "5.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "brace-expansion": {
- "version": "1.1.11",
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
}
},
- "chownr": {
- "version": "1.1.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
+ "safer-buffer": {
+ "version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "concat-map": {
- "version": "0.0.1",
+ "wide-align": {
+ "version": "1.1.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
},
- "console-control-strings": {
- "version": "1.1.0",
+ "once": {
+ "version": "1.4.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
},
- "core-util-is": {
- "version": "1.0.2",
+ "strip-ansi": {
+ "version": "3.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
},
- "debug": {
- "version": "3.2.6",
+ "nopt": {
+ "version": "4.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ms": "^2.1.1"
+ "abbrev": "1",
+ "osenv": "^0.1.4"
}
},
- "deep-extend": {
- "version": "0.6.0",
+ "console-control-strings": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "delegates": {
+ "fs.realpath": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "bundled": true,
- "dev": true,
"optional": true
},
- "fs-minipass": {
- "version": "1.2.7",
+ "tar": {
+ "version": "4.4.13",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minipass": "^2.6.0"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
}
},
- "glob": {
- "version": "7.1.6",
+ "brace-expansion": {
+ "version": "1.1.11",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "has-unicode": {
- "version": "2.0.1",
+ "os-tmpdir": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "iconv-lite": {
- "version": "0.4.24",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore-walk": {
- "version": "3.0.3",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
+ "minipass": {
+ "version": "2.9.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
}
},
- "inherits": {
- "version": "2.0.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
+ "yallist": {
+ "version": "3.1.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
+ "code-point-at": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "minimatch": {
- "version": "3.0.4",
+ "rc": {
+ "version": "1.2.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "brace-expansion": "^1.1.7"
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
}
},
- "minimist": {
- "version": "1.2.5",
+ "deep-extend": {
+ "version": "0.6.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "minipass": {
- "version": "2.9.0",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
"minizlib": {
"version": "1.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"minipass": "^2.9.0"
}
},
- "mkdirp": {
- "version": "0.5.3",
+ "osenv": {
+ "version": "0.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minimist": "^1.2.5"
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
}
},
- "ms": {
- "version": "2.1.2",
+ "signal-exit": {
+ "version": "3.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "needle": {
- "version": "2.3.3",
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
+ "number-is-nan": "^1.0.0"
}
},
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "optional": true
+ },
"node-pre-gyp": {
"version": "0.14.0",
"bundled": true,
- "dev": true,
- "optional": true,
"requires": {
"detect-libc": "^1.0.2",
"mkdirp": "^0.5.1",
"tar": "^4.4.2"
}
},
- "nopt": {
- "version": "4.0.3",
+ "gauge": {
+ "version": "2.7.4",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
}
},
- "npm-bundled": {
- "version": "1.1.1",
+ "ansi-regex": {
+ "version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "npm-normalize-package-bin": "^1.0.1"
- }
+ "optional": true
},
- "npm-normalize-package-bin": {
- "version": "1.0.1",
+ "has-unicode": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "npm-packlist": {
- "version": "1.4.8",
+ "os-homedir": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1",
- "npm-normalize-package-bin": "^1.0.1"
- }
+ "optional": true
},
- "npmlog": {
- "version": "4.1.2",
+ "ms": {
+ "version": "2.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "readable-stream": {
+ "version": "2.3.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
+ "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"
}
},
- "number-is-nan": {
- "version": "1.0.1",
+ "aproba": {
+ "version": "1.2.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "object-assign": {
- "version": "4.1.1",
+ "strip-json-comments": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "once": {
- "version": "1.4.0",
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "wrappy": "1"
+ "ms": "^2.1.1"
}
},
- "os-homedir": {
+ "util-deprecate": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "os-tmpdir": {
- "version": "1.0.2",
+ "chownr": {
+ "version": "1.1.4",
"bundled": true,
- "dev": true,
"optional": true
},
- "osenv": {
- "version": "0.1.5",
+ "npm-packlist": {
+ "version": "1.4.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
},
- "path-is-absolute": {
- "version": "1.0.1",
+ "balanced-match": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "process-nextick-args": {
- "version": "2.0.1",
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "rc": {
- "version": "1.2.8",
+ "needle": {
+ "version": "2.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
}
},
- "readable-stream": {
- "version": "2.3.7",
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
"bundled": true,
- "dev": true,
"optional": true,
"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"
+ "brace-expansion": "^1.1.7"
}
},
- "rimraf": {
- "version": "2.7.1",
+ "mkdirp": {
+ "version": "0.5.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "glob": "^7.1.3"
+ "minimist": "^1.2.5"
}
},
- "safe-buffer": {
- "version": "5.1.2",
+ "set-blocking": {
+ "version": "2.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "safer-buffer": {
- "version": "2.1.2",
+ "wrappy": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "sax": {
- "version": "1.2.4",
+ "fs-minipass": {
+ "version": "1.2.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "semver": {
- "version": "5.7.1",
+ "number-is-nan": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "set-blocking": {
- "version": "2.0.0",
+ "isarray": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "signal-exit": {
- "version": "3.0.2",
+ "rimraf": {
+ "version": "2.7.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "string-width": {
- "version": "1.0.2",
+ "glob": {
+ "version": "7.1.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
}
},
- "string_decoder": {
- "version": "1.1.1",
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "~5.1.0"
+ "minimatch": "^3.0.4"
}
},
- "strip-ansi": {
- "version": "3.0.1",
+ "inflight": {
+ "version": "1.0.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "once": "^1.3.0",
+ "wrappy": "1"
}
},
- "strip-json-comments": {
- "version": "2.0.1",
+ "path-is-absolute": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "tar": {
- "version": "4.4.13",
+ "iconv-lite": {
+ "version": "0.4.24",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.8.6",
- "minizlib": "^1.2.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.3"
+ "safer-buffer": ">= 2.1.2 < 3"
}
},
- "util-deprecate": {
- "version": "1.0.2",
+ "detect-libc": {
+ "version": "1.0.3",
"bundled": true,
- "dev": true,
"optional": true
},
- "wide-align": {
- "version": "1.1.3",
+ "string_decoder": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "string-width": "^1.0.2 || 2"
+ "safe-buffer": "~5.1.0"
}
},
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "yallist": {
- "version": "3.1.1",
+ "abbrev": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true
}
},
}
},
"fsevents": {
- "dev": true,
- "optional": true,
- "requires": {
- "node-pre-gyp": "*"
- },
"dependencies": {
- "abbrev": {
+ "npm-bundled": {
"version": "1.1.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
},
- "aproba": {
- "version": "1.2.0",
+ "semver": {
+ "version": "5.7.1",
"bundled": true,
- "dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
- "balanced-match": {
- "version": "1.0.0",
+ "safe-buffer": {
+ "version": "5.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "brace-expansion": {
- "version": "1.1.11",
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
}
},
- "chownr": {
- "version": "1.1.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
+ "safer-buffer": {
+ "version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "concat-map": {
- "version": "0.0.1",
+ "wide-align": {
+ "version": "1.1.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
},
- "console-control-strings": {
- "version": "1.1.0",
+ "once": {
+ "version": "1.4.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
},
- "core-util-is": {
- "version": "1.0.2",
+ "strip-ansi": {
+ "version": "3.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
},
- "debug": {
- "version": "3.2.6",
+ "nopt": {
+ "version": "4.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ms": "^2.1.1"
+ "abbrev": "1",
+ "osenv": "^0.1.4"
}
},
- "deep-extend": {
- "version": "0.6.0",
+ "console-control-strings": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "delegates": {
+ "fs.realpath": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "detect-libc": {
- "version": "1.0.3",
+ "tar": {
+ "version": "4.4.13",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
},
- "fs-minipass": {
- "version": "1.2.7",
+ "brace-expansion": {
+ "version": "1.1.11",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minipass": "^2.6.0"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "fs.realpath": {
- "version": "1.0.0",
+ "os-tmpdir": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "gauge": {
- "version": "2.7.4",
+ "minipass": {
+ "version": "2.9.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
}
},
- "glob": {
- "version": "7.1.6",
+ "yallist": {
+ "version": "3.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
+ "optional": true
},
- "has-unicode": {
- "version": "2.0.1",
+ "code-point-at": {
+ "version": "1.1.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "iconv-lite": {
- "version": "0.4.24",
+ "rc": {
+ "version": "1.2.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
}
},
- "ignore-walk": {
- "version": "3.0.3",
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "minizlib": {
+ "version": "1.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "minimatch": "^3.0.4"
+ "minipass": "^2.9.0"
}
},
- "inflight": {
- "version": "1.0.6",
+ "osenv": {
+ "version": "0.1.5",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
}
},
- "inherits": {
- "version": "2.0.4",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
+ "signal-exit": {
+ "version": "3.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
- "isarray": {
- "version": "1.0.0",
+ "sax": {
+ "version": "1.2.4",
"bundled": true,
- "dev": true,
"optional": true
},
- "minimatch": {
- "version": "3.0.4",
+ "node-pre-gyp": {
+ "version": "0.14.0",
"bundled": true,
- "dev": true,
- "optional": true,
"requires": {
- "brace-expansion": "^1.1.7"
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
}
},
- "minimist": {
- "version": "1.2.5",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "minipass": {
- "version": "2.9.0",
+ "gauge": {
+ "version": "2.7.4",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
}
},
- "minizlib": {
- "version": "1.3.3",
+ "ansi-regex": {
+ "version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minipass": "^2.9.0"
- }
+ "optional": true
},
- "mkdirp": {
- "version": "0.5.3",
+ "has-unicode": {
+ "version": "2.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "optional": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
},
"ms": {
"version": "2.1.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "needle": {
- "version": "2.3.3",
+ "readable-stream": {
+ "version": "2.3.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
+ "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"
}
},
- "node-pre-gyp": {
- "version": "0.14.0",
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4.4.2"
- }
+ "optional": true
},
- "nopt": {
- "version": "4.0.3",
+ "debug": {
+ "version": "3.2.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
+ "ms": "^2.1.1"
}
},
- "npm-bundled": {
- "version": "1.1.1",
+ "util-deprecate": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "npm-normalize-package-bin": "^1.0.1"
- }
+ "optional": true
},
- "npm-normalize-package-bin": {
- "version": "1.0.1",
+ "chownr": {
+ "version": "1.1.4",
"bundled": true,
- "dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.4.8",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"ignore-walk": "^3.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
- "npmlog": {
- "version": "4.1.2",
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
}
},
- "number-is-nan": {
+ "npm-normalize-package-bin": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "dev": true,
"optional": true
},
- "once": {
- "version": "1.4.0",
+ "needle": {
+ "version": "2.3.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "wrappy": "1"
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
}
},
- "os-homedir": {
- "version": "1.0.2",
+ "ini": {
+ "version": "1.3.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "os-tmpdir": {
- "version": "1.0.2",
+ "minimatch": {
+ "version": "3.0.4",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
},
- "osenv": {
- "version": "0.1.5",
+ "mkdirp": {
+ "version": "0.5.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
+ "minimist": "^1.2.5"
}
},
- "path-is-absolute": {
- "version": "1.0.1",
+ "set-blocking": {
+ "version": "2.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "process-nextick-args": {
- "version": "2.0.1",
+ "wrappy": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
"optional": true
},
- "rc": {
- "version": "1.2.8",
+ "fs-minipass": {
+ "version": "1.2.7",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
+ "minipass": "^2.6.0"
}
},
- "readable-stream": {
- "version": "2.3.7",
+ "core-util-is": {
+ "version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true,
- "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"
- }
+ "optional": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
},
"rimraf": {
"version": "2.7.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
"glob": "^7.1.3"
}
},
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
+ "minimist": {
+ "version": "1.2.5",
"bundled": true,
- "dev": true,
"optional": true
},
- "semver": {
- "version": "5.7.1",
+ "glob": {
+ "version": "7.1.6",
"bundled": true,
- "dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
},
- "set-blocking": {
- "version": "2.0.0",
+ "object-assign": {
+ "version": "4.1.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "signal-exit": {
- "version": "3.0.2",
+ "delegates": {
+ "version": "1.0.0",
"bundled": true,
- "dev": true,
"optional": true
},
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
+ "ignore-walk": {
+ "version": "3.0.3",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "safe-buffer": "~5.1.0"
+ "minimatch": "^3.0.4"
}
},
- "strip-ansi": {
- "version": "3.0.1",
+ "inflight": {
+ "version": "1.0.6",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "ansi-regex": "^2.0.0"
+ "once": "^1.3.0",
+ "wrappy": "1"
}
},
- "strip-json-comments": {
- "version": "2.0.1",
+ "path-is-absolute": {
+ "version": "1.0.1",
"bundled": true,
- "dev": true,
"optional": true
},
- "tar": {
- "version": "4.4.13",
+ "iconv-lite": {
+ "version": "0.4.24",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.8.6",
- "minizlib": "^1.2.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.3"
+ "safer-buffer": ">= 2.1.2 < 3"
}
},
- "util-deprecate": {
- "version": "1.0.2",
+ "detect-libc": {
+ "version": "1.0.3",
"bundled": true,
- "dev": true,
"optional": true
},
- "wide-align": {
- "version": "1.1.3",
+ "string_decoder": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true,
"requires": {
- "string-width": "^1.0.2 || 2"
+ "safe-buffer": "~5.1.0"
}
},
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "dev": true,
- "optional": true
- },
- "yallist": {
- "version": "3.1.1",
+ "abbrev": {
+ "version": "1.1.1",
"bundled": true,
- "dev": true,
"optional": true
}
},
}
},
"mem": {
- "dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^2.0.0",
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"os-locale": {
"version": "3.1.0",
"@auth0/angular-jwt": "2.1.1",
"@ngx-translate/i18n-polyfill": "1.0.0",
"@swimlane/ngx-datatable": "16.0.3",
+ "@types/file-saver": "^2.0.1",
"angular-tree-component": "8.5.6",
"async-mutex": "0.1.4",
"bootstrap": "4.4.1",
"chart.js": "2.8.0",
"detect-browser": "5.0.0",
+ "file-saver": "^2.0.2",
"fork-awesome": "1.1.7",
"lodash": "4.17.15",
"moment": "2.24.0",
import { MonitoringListComponent } from './ceph/cluster/prometheus/monitoring-list/monitoring-list.component';
import { SilenceFormComponent } from './ceph/cluster/prometheus/silence-form/silence-form.component';
import { ServicesComponent } from './ceph/cluster/services/services.component';
+import { TelemetryComponent } from './ceph/cluster/telemetry/telemetry.component';
import { DashboardComponent } from './ceph/dashboard/dashboard/dashboard.component';
import { Nfs501Component } from './ceph/nfs/nfs-501/nfs-501.component';
import { NfsFormComponent } from './ceph/nfs/nfs-form/nfs-form.component';
component: LogsComponent,
data: { breadcrumbs: 'Cluster/Logs' }
},
+ {
+ path: 'telemetry',
+ component: TelemetryComponent,
+ data: { breadcrumbs: 'Telemetry configuration' }
+ },
{
path: 'monitoring',
data: { breadcrumbs: 'Cluster/Monitoring' },
import { ServiceDaemonListComponent } from './services/service-daemon-list/service-daemon-list.component';
import { ServiceDetailsComponent } from './services/service-details/service-details.component';
import { ServicesComponent } from './services/services.component';
+import { TelemetryComponent } from './telemetry/telemetry.component';
@NgModule({
entryComponents: [
MonitoringListComponent,
HostFormComponent,
ServiceDetailsComponent,
- ServiceDaemonListComponent
+ ServiceDaemonListComponent,
+ TelemetryComponent
]
})
export class ClusterModule {}
--- /dev/null
+<cd-loading-panel *ngIf="loading && !error"
+ i18n>Loading configuration...</cd-loading-panel>
+<cd-alert-panel type="error"
+ *ngIf="loading && error"
+ i18n>The configuration could not be loaded.</cd-alert-panel>
+
+<div class="cd-col-form"
+ *ngIf="!loading && !error">
+ <ng-container [ngSwitch]="step">
+ <!-- Configuration step -->
+ <div *ngSwitchCase="1">
+ <form name="form"
+ #formDir="ngForm"
+ [formGroup]="configForm"
+ novalidate>
+ <div class="card">
+ <div class="card-header"
+ i18n>Step {{ step }} of 2: Telemetry report configuration</div>
+ <div class="card-body">
+ <p i18n>The telemetry module sends anonymous data about this Ceph cluster back to the Ceph developers
+ to help understand how Ceph is used and what problems users may be experiencing.<br/>
+ This data is visualized on <a href="https://telemetry-public.ceph.com/">public dashboards</a>
+ that allow the community to quickly see summary statistics on how many clusters are reporting,
+ their total capacity and OSD count, and version distribution trends.<br/><br/>
+ The data being reported does <b>not</b> contain any sensitive data like pool names, object names, object contents,
+ hostnames, or device serial numbers. It contains counters and statistics on how the cluster has been
+ deployed, the version of Ceph, the distribution of the hosts and other parameters which help the project
+ to gain a better understanding of the way Ceph is used. The data is sent secured to https://telemetry.ceph.com.</p>
+ <div *ngIf="moduleEnabled">
+ The plugin is already <b>enabled</b>. Click <b>Deactivate</b> to disable it.
+ <button type="button"
+ class="btn btn-light"
+ (click)="disableModule('The Telemetry module has been disabled successfully.')"
+ i18n>Deactivate</button>
+ </div>
+ <legend i18n>Channels</legend>
+ <p i18n>The telemetry report is broken down into several "channels", each with a different type of information that can
+ be configured below.</p>
+
+ <!-- Channel basic -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="channel_basic">
+ <ng-container i18n>Basic</ng-container>
+ <cd-helper>
+ <ng-container i18n>Includes basic information about the cluster:</ng-container>
+ <ul>
+ <li i18n>Capacity of the cluster</li>
+ <li i18n>Number of monitors, managers, OSDs, MDSs, object gateways, or other daemons</li>
+ <li i18n>Software version currently being used</li>
+ <li i18n>Number and types of RADOS pools and CephFS file systems</li>
+ <li i18n>Names of configuration options that have been changed from their default (but not their values)</li>
+ </ul>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="channel_basic"
+ formControlName="channel_basic">
+ <label class="custom-control-label"
+ for="channel_basic"></label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Channel crash -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="channel_crash">
+ <ng-container i18n>Crash</ng-container>
+ <cd-helper>
+ <ng-container i18n>Includes information about daemon crashes:</ng-container>
+ <ul>
+ <li i18n>Type of daemon</li>
+ <li i18n>Version of the daemon</li>
+ <li i18n>Operating system (OS distribution, kernel version)</li>
+ <li i18n>Stack trace identifying where in the Ceph code the crash occurred</li>
+ </ul>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="channel_crash"
+ formControlName="channel_crash">
+ <label class="custom-control-label"
+ for="channel_crash"></label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Channel device -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="channel_device">
+ <ng-container i18n>Device</ng-container>
+ <cd-helper i18n-html
+ html="Includes information about device metrics like anonymized SMART metrics.">
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="channel_device"
+ formControlName="channel_device">
+ <label class="custom-control-label"
+ for="channel_device"></label>
+ </div>
+ </div>
+ </div>
+
+ <!-- Channel ident -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="channel_ident">
+ <ng-container i18n>Ident</ng-container>
+ <cd-helper>
+ <ng-container i18n>Includes user-provided identifying information about the cluster:</ng-container>
+ <ul>
+ <li>Cluster description</li>
+ <li>Contact email address</li>
+ </ul>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="channel_ident"
+ formControlName="channel_ident">
+ <label class="custom-control-label"
+ for="channel_ident"></label>
+ </div>
+ </div>
+ </div>
+ <legend>
+ <ng-container i18n>Contact Information</ng-container>
+ <cd-helper i18n>Submitting any contact information is completely optional and disabled by default.</cd-helper>
+ </legend>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="contact"
+ i18n>Contact</label>
+ <div class="cd-col-form-input">
+ <input id="contact"
+ class="form-control"
+ type="text"
+ formControlName="contact"
+ placeholder="Example User <user@example.com>">
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="description"
+ i18n>Description</label>
+ <div class="cd-col-form-input">
+ <input id="description"
+ class="form-control"
+ type="text"
+ formControlName="description"
+ placeholder="My first Ceph cluster"
+ i18n-placeholder>
+ </div>
+ </div>
+ <legend i18n>Advanced Settings</legend>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="interval">
+ <ng-container i18n>Interval</ng-container>
+ <cd-helper i18n>The module compiles and sends a new report every 24 hours by default. You can
+ adjust this interval by setting a different number of hours.</cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <input id="interval"
+ class="form-control"
+ type="number"
+ formControlName="interval">
+ <span class="invalid-feedback"
+ *ngIf="configForm.showError('interval', formDir, 'min')"
+ i18n>The entered value is too low! It must be greater or equal to 8.</span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="proxy">
+ <ng-container i18n>Proxy</ng-container>
+ <cd-helper>
+ <p i18n>If the cluster cannot directly connect to the configured telemetry endpoint
+ (default telemetry.ceph.com), you can configure a HTTP/HTTPS proxy server by e.g. adding
+ https://10.0.0.1:8080</p>
+ <p i18n>You can also include a user:pass if needed e.g. https://ceph:telemetry@10.0.0.1:8080</p>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <input id="proxy"
+ class="form-control"
+ type="text"
+ formControlName="proxy"
+ placeholder="https://10.0.0.1:8080">
+ </div>
+ </div>
+ <br />
+ <p i18n><b>Note:</b> By clicking 'Next' you will first see a preview of the report content before you
+ can activate the automatic submission of your data.</p>
+ </div>
+ <div class="card-footer">
+ <div class="button-group text-right">
+ <button type="button"
+ class="btn btn-light"
+ (click)="next()">
+ <ng-container i18n>Next</ng-container>
+ </button>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <!-- Preview step -->
+ <div *ngSwitchCase="2">
+ <form name="previewForm"
+ #frm="ngForm"
+ [formGroup]="previewForm"
+ novalidate>
+ <div class="card">
+ <div class="card-header"
+ i18n>Step {{ step }} of 2: Telemetry report preview</div>
+ <div class="card-body">
+ <!-- Telemetry report ID -->
+ <div class="form-group row">
+ <label i18n
+ for="reportId"
+ class="cd-col-form-label">Report ID</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ id="reportId"
+ formControlName="reportId"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Telemetry report -->
+ <div class="form-group row">
+ <label i18n
+ for="report"
+ class="cd-col-form-label">Report preview</label>
+ <div class="cd-col-form-input">
+ <textarea class="form-control"
+ id="report"
+ formControlName="report"
+ rows="15"
+ readonly></textarea>
+ </div>
+ </div>
+ <div class="form-group row">
+ <div class="cd-col-form-offset">
+ <button type="button"
+ class="btn btn-light mr-2"
+ title="Download"
+ (click)="download(report, 'telemetry_report.json')"
+ i18n-title>
+ <i class="fa fa-download"></i>
+ </button>
+ <button type="button"
+ class="btn btn-light"
+ cdCopy2ClipboardButton="report"
+ formatted>
+ </button>
+ </div>
+ </div>
+
+ <!-- License agreement -->
+ <div class="form-group row">
+ <div class="cd-col-form-offset">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="licenseAgrmt"
+ name="licenseAgrmt"
+ formControlName="licenseAgrmt">
+ <label class="custom-control-label"
+ for="licenseAgrmt"
+ i18n>I agree to my telemetry data being submitted under the Community Data License Agreement - Sharing - Version 1.0 (<a href="https://cdla.io/sharing-1-0/">https://cdla.io/sharing-1-0/</a>)</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="card-footer">
+ <div class="button-group text-right">
+ <cd-submit-button (submitAction)="onSubmit()"
+ [form]="previewForm">
+ <ng-container i18n>Save</ng-container>
+ </cd-submit-button>
+ <button type="button"
+ class="btn btn-light"
+ (click)="back()"
+ i18n>Back</button>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+ </ng-container>
+</div>
--- /dev/null
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import * as _ from 'lodash';
+import { ToastrModule } from 'ngx-toastr';
+import { of as observableOf } from 'rxjs';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { MgrModuleService } from '../../../shared/api/mgr-module.service';
+import { TelemetryService } from '../../../shared/api/telemetry.service';
+
+import { TextToDownloadService } from '../../../shared/services/text-to-download.service';
+import { SharedModule } from '../../../shared/shared.module';
+import { TelemetryComponent } from './telemetry.component';
+
+describe('TelemetryComponent', () => {
+ let component: TelemetryComponent;
+ let fixture: ComponentFixture<TelemetryComponent>;
+ let mgrModuleService: MgrModuleService;
+ let telemetryService: TelemetryService;
+ let options: any;
+ let configs: any;
+ let httpTesting: HttpTestingController;
+ let router: Router;
+
+ const optionsNames = [
+ 'channel_basic',
+ 'channel_crash',
+ 'channel_device',
+ 'channel_ident',
+ 'contact',
+ 'description',
+ 'device_url',
+ 'enabled',
+ 'interval',
+ 'last_opt_revision',
+ 'leaderboard',
+ 'log_level',
+ 'log_to_cluster',
+ 'log_to_cluster_level',
+ 'log_to_file',
+ 'organization',
+ 'proxy',
+ 'url'
+ ];
+
+ configureTestBed(
+ {
+ declarations: [TelemetryComponent],
+ imports: [
+ HttpClientTestingModule,
+ ReactiveFormsModule,
+ RouterTestingModule,
+ SharedModule,
+ ToastrModule.forRoot()
+ ],
+ providers: i18nProviders
+ },
+ true
+ );
+
+ describe('configForm', () => {
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TelemetryComponent);
+ component = fixture.componentInstance;
+ mgrModuleService = TestBed.get(MgrModuleService);
+ options = {};
+ configs = {};
+ optionsNames.forEach((name) => (options[name] = { name }));
+ optionsNames.forEach((name) => (configs[name] = true));
+ spyOn(mgrModuleService, 'getOptions').and.callFake(() => observableOf(options));
+ spyOn(mgrModuleService, 'getConfig').and.callFake(() => observableOf(configs));
+ fixture.detectChanges();
+ httpTesting = TestBed.get(HttpTestingController);
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate');
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should set module enability to true correctly', () => {
+ expect(component.moduleEnabled).toBeTruthy();
+ });
+
+ it('should set module enability to false correctly', () => {
+ configs['enabled'] = false;
+ component.ngOnInit();
+ expect(component.moduleEnabled).toBeFalsy();
+ });
+
+ it('should filter options list correctly', () => {
+ _.forEach(Object.keys(component.options), (option) => {
+ expect(component.requiredFields).toContain(option);
+ });
+ });
+
+ it('should update the Telemetry configuration', () => {
+ component.updateConfig();
+ const req = httpTesting.expectOne('api/mgr/module/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ config: {}
+ });
+ req.flush({});
+ });
+
+ it('should disable the Telemetry module', () => {
+ const message = 'Module disabled message.';
+ const followUpFunc = function () {
+ return 'followUp';
+ };
+ component.disableModule(message, followUpFunc);
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ enable: false
+ });
+ req.flush({});
+ });
+
+ it('should disable the Telemetry module with default parameters', () => {
+ component.disableModule();
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ enable: false
+ });
+ req.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['']);
+ });
+ });
+
+ describe('previewForm', () => {
+ const reportText = {
+ testA: 'testA',
+ testB: 'testB'
+ };
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TelemetryComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ telemetryService = TestBed.get(TelemetryService);
+ httpTesting = TestBed.get(HttpTestingController);
+ router = TestBed.get(Router);
+ spyOn(router, 'navigate');
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should call TextToDownloadService download function', () => {
+ spyOn(telemetryService, 'getReport').and.returnValue(observableOf(reportText));
+ component.ngOnInit();
+
+ const downloadSpy = spyOn(TestBed.get(TextToDownloadService), 'download');
+ const filename = 'reportText.json';
+ component.download(reportText, filename);
+ expect(downloadSpy).toHaveBeenCalledWith(JSON.stringify(reportText, null, 2), filename);
+ });
+
+ it('should submit', () => {
+ component.onSubmit();
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body).toEqual({
+ enable: true,
+ license_name: 'sharing-1-0'
+ });
+ req.flush({});
+ expect(router.navigate).toHaveBeenCalledWith(['']);
+ });
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+import { ValidatorFn, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+
+import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as _ from 'lodash';
+import { BlockUI, NgBlockUI } from 'ng-block-ui';
+import { forkJoin as observableForkJoin } from 'rxjs';
+
+import { MgrModuleService } from '../../../shared/api/mgr-module.service';
+import { TelemetryService } from '../../../shared/api/telemetry.service';
+import { NotificationType } from '../../../shared/enum/notification-type.enum';
+import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
+import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../shared/forms/cd-validators';
+import { NotificationService } from '../../../shared/services/notification.service';
+import { TextToDownloadService } from '../../../shared/services/text-to-download.service';
+
+@Component({
+ selector: 'cd-telemetry',
+ templateUrl: './telemetry.component.html',
+ styleUrls: ['./telemetry.component.scss']
+})
+export class TelemetryComponent implements OnInit {
+ @BlockUI()
+ blockUI: NgBlockUI;
+
+ error = false;
+ configForm: CdFormGroup;
+ licenseAgrmt = false;
+ loading = false;
+ moduleEnabled: boolean;
+ options: Object = {};
+ previewForm: CdFormGroup;
+ requiredFields = [
+ 'channel_basic',
+ 'channel_crash',
+ 'channel_device',
+ 'channel_ident',
+ 'interval',
+ 'proxy',
+ 'contact',
+ 'description'
+ ];
+ report: object = undefined;
+ reportId: number = undefined;
+ step = 1;
+
+ constructor(
+ private formBuilder: CdFormBuilder,
+ private mgrModuleService: MgrModuleService,
+ private notificationService: NotificationService,
+ private router: Router,
+ private telemetryService: TelemetryService,
+ private i18n: I18n,
+ private textToDownloadService: TextToDownloadService
+ ) {}
+
+ ngOnInit() {
+ this.loading = true;
+ const observables = [
+ this.mgrModuleService.getOptions('telemetry'),
+ this.mgrModuleService.getConfig('telemetry')
+ ];
+ observableForkJoin(observables).subscribe(
+ (resp: object) => {
+ this.moduleEnabled = resp[1]['enabled'];
+ this.options = _.pick(resp[0], this.requiredFields);
+ const configs = _.pick(resp[1], this.requiredFields);
+ this.createConfigForm();
+ this.configForm.setValue(configs);
+ this.loading = false;
+ },
+ (_error) => {
+ this.error = true;
+ }
+ );
+ }
+
+ private createConfigForm() {
+ const controlsConfig = {};
+ _.forEach(Object.values(this.options), (option) => {
+ controlsConfig[option.name] = [option.default_value, this.getValidators(option)];
+ });
+ this.configForm = this.formBuilder.group(controlsConfig);
+ }
+
+ private createPreviewForm() {
+ const controls = {
+ report: JSON.stringify(this.report, null, 2),
+ reportId: this.reportId,
+ licenseAgrmt: [this.licenseAgrmt, Validators.requiredTrue]
+ };
+ this.previewForm = this.formBuilder.group(controls);
+ }
+
+ private getValidators(option: any): ValidatorFn[] {
+ const result = [];
+ switch (option.type) {
+ case 'int':
+ result.push(CdValidators.number());
+ result.push(Validators.required);
+ if (_.isNumber(option.min)) {
+ result.push(Validators.min(option.min));
+ }
+ if (_.isNumber(option.max)) {
+ result.push(Validators.max(option.max));
+ }
+ break;
+ case 'str':
+ if (_.isNumber(option.min)) {
+ result.push(Validators.minLength(option.min));
+ }
+ if (_.isNumber(option.max)) {
+ result.push(Validators.maxLength(option.max));
+ }
+ break;
+ }
+ return result;
+ }
+
+ private getReport() {
+ this.loading = true;
+ this.telemetryService.getReport().subscribe(
+ (resp: object) => {
+ this.report = resp;
+ this.reportId = resp['report']['report_id'];
+ this.createPreviewForm();
+ this.loading = false;
+ this.step++;
+ },
+ (_error) => {
+ this.error = true;
+ }
+ );
+ }
+
+ updateConfig() {
+ const config = {};
+ _.forEach(Object.values(this.options), (option) => {
+ const control = this.configForm.get(option.name);
+ // Append the option only if the value has been modified.
+ if (control.dirty && control.valid) {
+ config[option.name] = control.value;
+ }
+ });
+ this.mgrModuleService.updateConfig('telemetry', config).subscribe(
+ () => {
+ this.disableModule(
+ 'Your settings have been applied successfully. ' +
+ 'Due to privacy/legal reasons the Telemetry module is now disabled until you ' +
+ 'complete the next step and accept the license.',
+ () => {
+ this.getReport();
+ }
+ );
+ },
+ () => {
+ // Reset the 'Submit' button.
+ this.configForm.setErrors({ cdSubmitButton: true });
+ }
+ );
+ }
+
+ download(report: object, fileName: string) {
+ this.textToDownloadService.download(JSON.stringify(report, null, 2), fileName);
+ }
+
+ disableModule(message: string = null, followUpFunc: Function = null) {
+ this.telemetryService.enable(false).subscribe(() => {
+ if (message) {
+ this.notificationService.show(NotificationType.success, this.i18n(message));
+ }
+ if (followUpFunc) {
+ followUpFunc();
+ } else {
+ this.router.navigate(['']);
+ }
+ });
+ }
+
+ next() {
+ if (this.configForm.pristine) {
+ this.getReport();
+ } else {
+ this.updateConfig();
+ }
+ }
+
+ back() {
+ this.step--;
+ }
+
+ onSubmit() {
+ this.telemetryService.enable().subscribe(() => {
+ this.notificationService.show(
+ NotificationType.success,
+ this.i18n('The Telemetry module has been configured and activated successfully.')
+ );
+ this.router.navigate(['']);
+ });
+ }
+}
class="dropdown-item"
routerLink="/user-management">User management</a>
</li>
+ <li *ngIf="configOptPermission.read">
+ <a i18n
+ class="dropdown-item"
+ routerLink="/telemetry">Telemetry configuration</a>
+ </li>
</ul>
</div>
})
export class AdministrationComponent implements OnInit {
userPermission: Permission;
+ configOptPermission: Permission;
icons = Icons;
constructor(private authStorageService: AuthStorageService) {
- this.userPermission = this.authStorageService.getPermissions().user;
+ const permissions = this.authStorageService.getPermissions();
+ this.userPermission = permissions.user;
+ this.configOptPermission = permissions.configOpt;
}
ngOnInit() {}
--- /dev/null
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { TelemetryService } from './telemetry.service';
+
+describe('TelemetryService', () => {
+ let service: TelemetryService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule],
+ providers: [TelemetryService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(TelemetryService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should call getReport', () => {
+ service.getReport().subscribe();
+ const req = httpTesting.expectOne('api/telemetry/report');
+ expect(req.request.method).toBe('GET');
+ });
+
+ it('should call enable to enable module', () => {
+ service.enable(true).subscribe();
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body.enable).toBe(true);
+ expect(req.request.body.license_name).toBe('sharing-1-0');
+ });
+
+ it('should call enable to disable module', () => {
+ service.enable(false).subscribe();
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body.enable).toBe(false);
+ expect(req.request.body.license_name).toBeUndefined();
+ });
+
+ it('should call enable to enable module by default', () => {
+ service.enable().subscribe();
+ const req = httpTesting.expectOne('api/telemetry');
+ expect(req.request.method).toBe('PUT');
+ expect(req.request.body.enable).toBe(true);
+ expect(req.request.body.license_name).toBe('sharing-1-0');
+ });
+});
--- /dev/null
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class TelemetryService {
+ private url = 'api/telemetry';
+
+ constructor(private http: HttpClient) {}
+
+ getReport() {
+ return this.http.get(`${this.url}/report`);
+ }
+
+ enable(enable: boolean = true) {
+ const body = { enable: enable };
+ if (enable) {
+ body['license_name'] = 'sharing-1-0';
+ }
+ return this.http.put(`${this.url}`, body);
+ }
+}
--- /dev/null
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { TextToDownloadService } from './text-to-download.service';
+
+describe('TextToDownloadService', () => {
+ let service: TextToDownloadService;
+
+ configureTestBed({
+ providers: [TextToDownloadService]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(TextToDownloadService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
--- /dev/null
+import { Injectable } from '@angular/core';
+
+import { saveAs } from 'file-saver';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TextToDownloadService {
+ constructor() {}
+
+ download(downloadText: string, filename?: string) {
+ saveAs(new Blob([downloadText]), filename);
+ }
+}