1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

Adding deployment details view

This commit is contained in:
Ewout Prangsma 2018-07-05 17:16:36 +02:00
parent 81b98028b3
commit a65aa3ecef
No known key found for this signature in database
GPG key ID: 4DBAD380D93D0698
15 changed files with 791 additions and 112 deletions

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,15 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/helper-module-imports": {
"version": "7.0.0-beta.40",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.40.tgz",
"integrity": "sha512-QFOskAKWbqJSBbGIl/Y1igJI4mW0A+wD5NFqsgDJj85KSvj/dHM4wNGIeqCi85nN9aMa4DgTBBrzUK4zSMsN2Q==",
"requires": {
"@babel/types": "7.0.0-beta.40",
"lodash": "^4.2.0"
}
},
"@babel/runtime": {
"version": "7.0.0-beta.51",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.51.tgz",
@ -20,12 +29,98 @@
}
}
},
"@babel/types": {
"version": "7.0.0-beta.40",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.40.tgz",
"integrity": "sha512-uXCGCzTgMZxcSUzutCPtZmXbVC+cvENgS2e0tRuhn+Y1hZnMb8IHP0Trq7Q2MB/eFmG5pKrAeTIUfQIe5kA4Tg==",
"requires": {
"esutils": "^2.0.2",
"lodash": "^4.2.0",
"to-fast-properties": "^2.0.0"
},
"dependencies": {
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
}
}
},
"@emotion/babel-utils": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.5.tgz",
"integrity": "sha1-NNeETrUy0Rdcj8cBdb63TQcb++s=",
"requires": {
"@emotion/hash": "^0.6.3",
"@emotion/memoize": "^0.6.3",
"@emotion/serialize": "^0.8.3",
"convert-source-map": "^1.5.1",
"find-root": "^1.1.0",
"source-map": "^0.7.2"
},
"dependencies": {
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
}
}
},
"@emotion/hash": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.3.tgz",
"integrity": "sha1-DnpWBGJvxsbUrEBhovWsgNUCYqQ="
},
"@emotion/is-prop-valid": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.6.3.tgz",
"integrity": "sha1-sElW4tZVAn/ojGI0Zp/XBk+wccw=",
"requires": {
"@emotion/memoize": "^0.6.3"
}
},
"@emotion/memoize": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.3.tgz",
"integrity": "sha1-ZDeaHWr2+NT+i9bv6dnoJOpLItg="
},
"@emotion/serialize": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.8.3.tgz",
"integrity": "sha1-D61Vual/lSPmsf1vtvdLbLQcf4s=",
"requires": {
"@emotion/hash": "^0.6.3",
"@emotion/memoize": "^0.6.3",
"@emotion/unitless": "^0.6.3",
"@emotion/utils": "^0.7.1"
}
},
"@emotion/stylis": {
"version": "0.6.10",
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.6.10.tgz",
"integrity": "sha1-fTIeY568i6I6zlmQwg6U3Ou4890="
},
"@emotion/unitless": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.6.3.tgz",
"integrity": "sha1-ZWguaKgnAccO77ONf5QaLAv6kN4="
},
"@emotion/utils": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.7.1.tgz",
"integrity": "sha1-5E5ZbQPJ8WujsSetMzqKByvLWgo="
},
"abab": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
"integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=",
"dev": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
@ -286,7 +381,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
@ -801,6 +895,32 @@
"babel-types": "^6.26.0"
}
},
"babel-plugin-emotion": {
"version": "9.2.4",
"resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-9.2.4.tgz",
"integrity": "sha1-pOVKgJf2ugbLvHqQY5J6+v6f5zo=",
"requires": {
"@babel/helper-module-imports": "7.0.0-beta.40",
"@emotion/babel-utils": "^0.6.4",
"@emotion/hash": "^0.6.2",
"@emotion/memoize": "^0.6.1",
"@emotion/stylis": "^0.6.10",
"babel-plugin-macros": "^2.0.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"convert-source-map": "^1.5.0",
"find-root": "^1.1.0",
"mkdirp": "^0.5.1",
"source-map": "^0.5.7",
"touch": "^1.0.0"
},
"dependencies": {
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
}
}
},
"babel-plugin-istanbul": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
@ -819,6 +939,55 @@
"integrity": "sha1-r+3IU70/jcNUjqZx++adA8wsF2c=",
"dev": true
},
"babel-plugin-macros": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.2.2.tgz",
"integrity": "sha512-wq6DYqjNmSPskGyhOeRIbmuvLtsHTfc6ROtGqapTttIGL1RoQmM3V5N8aJiDxPaw3/fveIsVspF51E3V7qTOMQ==",
"requires": {
"cosmiconfig": "^4.0.0"
},
"dependencies": {
"cosmiconfig": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
"requires": {
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"parse-json": "^4.0.0",
"require-from-string": "^2.0.1"
}
},
"esprima": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
"integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
},
"js-yaml": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
}
},
"require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
}
}
},
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
@ -852,8 +1021,7 @@
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=",
"dev": true
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
},
"babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0",
@ -2393,8 +2561,7 @@
"convert-source-map": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
"integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
"dev": true
"integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU="
},
"cookie": {
"version": "0.3.1",
@ -2466,6 +2633,28 @@
"elliptic": "^6.0.0"
}
},
"create-emotion": {
"version": "9.2.4",
"resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-9.2.4.tgz",
"integrity": "sha1-CkN59r8HCMVP4mv81ra9NZLozyM=",
"requires": {
"@emotion/hash": "^0.6.2",
"@emotion/memoize": "^0.6.1",
"@emotion/stylis": "^0.6.10",
"@emotion/unitless": "^0.6.2",
"csstype": "^2.5.2",
"stylis": "^3.5.0",
"stylis-rule-sheet": "^0.0.10"
}
},
"create-emotion-styled": {
"version": "9.2.3",
"resolved": "https://registry.npmjs.org/create-emotion-styled/-/create-emotion-styled-9.2.3.tgz",
"integrity": "sha1-F/sTs65MFl6m5aETVquLnKHa2cU=",
"requires": {
"@emotion/is-prop-valid": "^0.6.1"
}
},
"create-error-class": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
@ -2781,6 +2970,11 @@
"cssom": "0.3.x"
}
},
"csstype": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.5.tgz",
"integrity": "sha512-EGMjeoiN3aqEX5u/cyH5mSdGBDGdLcCQvcEcBWNGFSPXKd9uOTIeVG91YQ22OxI44DKpvI+4C7VUSmEpsHWJaA=="
},
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@ -3209,6 +3403,15 @@
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
"dev": true
},
"emotion": {
"version": "9.2.4",
"resolved": "https://registry.npmjs.org/emotion/-/emotion-9.2.4.tgz",
"integrity": "sha1-ATnnzBVLKEX0ua+qmW3U3hO7kOM=",
"requires": {
"babel-plugin-emotion": "^9.2.4",
"create-emotion": "^9.2.4"
}
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@ -3254,7 +3457,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"requires": {
"is-arrayish": "^0.2.1"
}
@ -3750,8 +3952,7 @@
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"etag": {
"version": "1.8.1",
@ -4260,6 +4461,11 @@
"pkg-dir": "^2.0.0"
}
},
"find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
@ -5250,6 +5456,28 @@
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
"dev": true
},
"history": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz",
"integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==",
"requires": {
"invariant": "^2.2.1",
"loose-envify": "^1.2.0",
"resolve-pathname": "^2.2.0",
"value-equal": "^0.4.0",
"warning": "^3.0.0"
},
"dependencies": {
"warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
"integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
"requires": {
"loose-envify": "^1.0.0"
}
}
}
},
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@ -5261,6 +5489,11 @@
"minimalistic-crypto-utils": "^1.0.1"
}
},
"hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
},
"home-or-tmp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
@ -5766,7 +5999,6 @@
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dev": true,
"requires": {
"loose-envify": "^1.0.0"
}
@ -5818,8 +6050,7 @@
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-binary-path": {
"version": "1.0.1",
@ -5908,8 +6139,7 @@
"is-directory": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
"dev": true
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
},
"is-dotfile": {
"version": "1.0.3",
@ -6991,6 +7221,11 @@
"integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
"dev": true
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@ -7558,8 +7793,7 @@
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mixin-deep": {
"version": "1.3.1",
@ -7586,7 +7820,6 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
}
@ -7750,6 +7983,14 @@
"which": "^1.3.0"
}
},
"nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
"requires": {
"abbrev": "1"
}
},
"normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
@ -8190,7 +8431,6 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
"integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
"dev": true,
"requires": {
"isarray": "0.0.1"
},
@ -8198,8 +8438,7 @@
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
"dev": true
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
}
}
},
@ -9924,12 +10163,48 @@
"prop-types": "^15.6.0"
}
},
"react-emotion": {
"version": "9.2.4",
"resolved": "https://registry.npmjs.org/react-emotion/-/react-emotion-9.2.4.tgz",
"integrity": "sha1-mOAPcM4spO4TkjRgEj52PkksATo=",
"requires": {
"babel-plugin-emotion": "^9.2.4",
"create-emotion-styled": "^9.2.3"
}
},
"react-error-overlay": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.0.tgz",
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==",
"dev": true
},
"react-router": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
"integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==",
"requires": {
"history": "^4.7.2",
"hoist-non-react-statics": "^2.5.0",
"invariant": "^2.2.4",
"loose-envify": "^1.3.1",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.1",
"warning": "^4.0.1"
}
},
"react-router-dom": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz",
"integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==",
"requires": {
"history": "^4.7.2",
"invariant": "^2.2.4",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.1",
"react-router": "^4.3.1",
"warning": "^4.0.1"
}
},
"react-scripts": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-1.1.4.tgz",
@ -10398,6 +10673,11 @@
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
"dev": true
},
"resolve-pathname": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz",
"integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg=="
},
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@ -11060,8 +11340,7 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"sshpk": {
"version": "1.14.2",
@ -11230,6 +11509,16 @@
"schema-utils": "^0.3.0"
}
},
"stylis": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.1.tgz",
"integrity": "sha512-yM4PyeHuwhIOUHNJxi1/Mbq8kVLv4AkyE7IYLP/LK0lIFcr3tRa2H1iZlBYKIxOlf+/jruBTe8DdKSyQX9w4OA=="
},
"stylis-rule-sheet": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
@ -11503,6 +11792,14 @@
"integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
"dev": true
},
"touch": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-1.0.0.tgz",
"integrity": "sha1-RJy+LbrlqMgDjjDXH6D/RklHxN4=",
"requires": {
"nopt": "~1.0.10"
}
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
@ -11936,6 +12233,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
"value-equal": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz",
"integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -11977,6 +12279,14 @@
"makeerror": "1.0.x"
}
},
"warning": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.1.tgz",
"integrity": "sha512-rAVtTNZw+cQPjvGp1ox0XC5Q2IBFyqoqh+QII4J/oguyu83Bax1apbo2eqB8bHRS+fqYUBagys6lqUoVwKSmXQ==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watch": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz",

View file

@ -3,9 +3,12 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"emotion": "^9.2.4",
"react": "^16.4.1",
"react-copy-to-clipboard": "^5.0.1",
"react-dom": "^16.4.1",
"react-emotion": "^9.2.4",
"react-router-dom": "^4.3.1",
"semantic-ui-less": "^2.2.12",
"semantic-ui-react": "^0.81.3"
},

View file

@ -6,16 +6,19 @@ import { apiGet } from './api/api.js';
import { Container, Segment, Message } from 'semantic-ui-react';
import './App.css';
const PodInfoView = ({pod, namespace}) => (
<Segment basic>
<Message>
<Message.Header>Kube-ArangoDB</Message.Header>
<p>Running in Pod <b>{pod}</b> in namespace <b>{namespace}</b>.</p>
</Message>
</Segment>
);
const OperatorsView = ({deployment, pod, namespace}) => (
<Container>
{deployment ? <DeploymentOperator /> : <NoOperator />}
<Segment basic>
<Message>
<Message.Header>Kube-ArangoDB</Message.Header>
<p>Running in Pod <b>{pod}</b> in namespace <b>{namespace}</b>.</p>
</Message>
</Segment>
</Container>
<div>
{deployment ? <DeploymentOperator pod-info={<PodInfoView pod={pod} namespace={namespace}/>}/> : <NoOperator />}
</div>
);
const LoadingView = () => (

View file

@ -13,6 +13,7 @@ class NoOperator extends Component {
<p className="App-intro">
There are no operators available yet.
</p>
{this.props["pod-info"]}
</div>
);
}

View file

@ -0,0 +1,88 @@
import React, { Component } from 'react';
import { apiGet } from '../api/api.js';
import { Accordion, Header, Icon, List, Segment } from 'semantic-ui-react';
import Loading from '../util/Loading.js';
//import CommandInstruction from '../util/CommandInstruction.js';
const MemberGroupsView = ({member_groups}) => (
<div>
{member_groups.map((item) => <MemberListComponent
group={item.group}
members={item.members}
/>)}
</div>
);
const MemberListView = ({group, activeMemberID, onClick, members}) => (
<Segment>
<Header>{group}</Header>
<List divided>
{members.map((item) => <MemberView memberInfo={item} active={item.id === activeMemberID} onClick={onClick}/>)}
</List>
</Segment>
);
const MemberView = ({memberInfo, active, onClick}) => (
<List.Item>
<Accordion>
<Accordion.Title active={active} onClick={() => onClick(memberInfo.id)}>
<Icon name='dropdown' /> {memberInfo.id}
</Accordion.Title>
<Accordion.Content active={active}>
<div>Pod: {memberInfo.pod_name}</div>
<div>PVC: {memberInfo.pvc_name}</div>
<div>PV: {memberInfo.pv_name}</div>
</Accordion.Content>
</Accordion>
</List.Item>
);
class MemberListComponent extends Component {
state = {};
onClick = (id) => {
this.setState({activeMemberID:(this.state.activeMemberID === id) ? null : id});
}
render() {
return (<MemberListView
group={this.props.group}
members={this.props.members}
activeMemberID={this.state.activeMemberID}
onClick={this.onClick}
/>);
}
}
class DeploymentDetails extends Component {
state = {};
componentDidMount() {
this.intervalId = setInterval(this.reloadDeployment, 5000);
this.reloadDeployment();
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
reloadDeployment = async() => {
// TODO
const result = await apiGet(`/api/deployment/${this.props.name}`);
this.setState({deployment:result});
}
render() {
const d = this.state.deployment;
if (!d) {
return (<Loading/>);
}
return (
<div>
<MemberGroupsView member_groups={d.member_groups}/>
</div>
);
}
}
export default DeploymentDetails;

View file

@ -3,6 +3,7 @@ import { apiGet } from '../api/api.js';
import { Icon, Popup, Table } from 'semantic-ui-react';
import Loading from '../util/Loading.js';
import CommandInstruction from '../util/CommandInstruction.js';
import { Link } from "react-router-dom";
const HeaderView = () => (
<Table.Header>
@ -33,23 +34,43 @@ const NoDatabaseLinkView = () => (
</Popup>
);
const RowView = ({name, mode, version, license, ready_pod_count, pod_count, ready_volume_count, volume_count, storage_classes, database_url, delete_command}) => (
const RowView = ({name, mode, environment, version, license, ready_pod_count, pod_count, ready_volume_count, volume_count, storage_classes, database_url, delete_command}) => (
<Table.Row>
<Table.Cell><Icon name="bell" color="red"/></Table.Cell>
<Table.Cell>{name}</Table.Cell>
<Table.Cell>{mode}</Table.Cell>
<Table.Cell>{version} {(license) ? `(${license})` : "" }</Table.Cell>
<Table.Cell>
<Icon name="bell" color="red"/>
</Table.Cell>
<Table.Cell>
<Link to={`/deployment/${name}`}>
{name}
</Link>
</Table.Cell>
<Table.Cell>
{mode}
<span style={{"float":"right"}}>
{(environment==="Development") ? <Popup trigger={<Icon name="laptop"/>} content="Development environment"/>: null}
{(environment==="Production") ? <Popup trigger={<Icon name="warehouse"/>} content="Production environment"/>: null}
</span>
</Table.Cell>
<Table.Cell>
{version}
<span style={{"float":"right"}}>
{(license==="community") ? <Popup trigger={<Icon name="users"/>} content="Community edition"/>: null}
{(license==="enterprise") ? <Popup trigger={<Icon name="dollar"/>} content="Enterprise edition"/>: null}
</span>
</Table.Cell>
<Table.Cell>{ready_pod_count} / {pod_count}</Table.Cell>
<Table.Cell>{ready_volume_count} / {volume_count}</Table.Cell>
<Table.Cell>{storage_classes.map((item) => (item === "") ? "<default>" : item)}</Table.Cell>
<Table.Cell>
{ database_url ? <DatabaseLinkView name={name} url={database_url}/> : <NoDatabaseLinkView/>}
<CommandInstruction
trigger={<Icon floated="right" name="trash alternate"/>}
command={delete_command}
title="Delete deployment"
description="To delete this deployment, run:"
/>
<span style={{"float":"right"}}>
<CommandInstruction
trigger={<Icon link name="trash"/>}
command={delete_command}
title="Delete deployment"
description="To delete this deployment, run:"
/>
</span>
</Table.Cell>
</Table.Row>
);
@ -65,6 +86,7 @@ const ListView = ({items}) => (
name={item.name}
namespace={item.namespace}
mode={item.mode}
environment={item.environment}
version={item.database_version}
license={item.database_license}
ready_pod_count={item.ready_pod_count}

View file

@ -1,18 +1,63 @@
import React, { Component } from 'react';
import DeploymentDetails from './DeploymentDetails.js';
import DeploymentList from './DeploymentList.js';
import { Header, Segment } from 'semantic-ui-react';
//import logo from './logo.svg';
//import './App.css';
import { Header, Menu, Segment } from 'semantic-ui-react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import styled from 'react-emotion';
const StyledMenu = styled(Menu)`
width: 15rem !important;
@media (max-width: 768px) {
width: 10rem !important;
}
`;
const StyledContentBox = styled('div')`
margin-left: 15rem;
@media (max-width: 768px) {
margin-left: 10rem;
}
`;
const ListView = () => (
<div>
<Header dividing>
ArangoDeployments
</Header>
<DeploymentList/>
</div>
);
const DetailView = ({match}) => (
<div>
<Header dividing>
ArangoDeployment {match.params.name}
</Header>
<DeploymentDetails name={match.params.name}/>
</div>
);
class DeploymentOperator extends Component {
render() {
return (
<Segment basic>
<Header dividing>
ArangoDeployments....
</Header>
<DeploymentList/>
</Segment>
<Router>
<div>
<StyledMenu fixed="left" vertical>
<Menu.Item>
<Link to="/">Deployments</Link>
</Menu.Item>
</StyledMenu>
<StyledContentBox>
<Segment basic clearing>
<div>
<Route exact path="/" component={ListView} />
<Route path="/deployment/:name" component={DetailView} />
</div>
</Segment>
{this.props["pod-info"]}
</StyledContentBox>
</div>
</Router>
);
}
}

View file

@ -22,7 +22,9 @@
package deployment
import "github.com/pkg/errors"
import (
"github.com/pkg/errors"
)
var (
maskAny = errors.WithStack

View file

@ -32,6 +32,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
"github.com/arangodb/kube-arangodb/pkg/server"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
@ -50,6 +51,11 @@ func (d *Deployment) Mode() api.DeploymentMode {
return d.GetSpec().GetMode()
}
// Environment returns the environment used in the deployment.
func (d *Deployment) Environment() api.Environment {
return d.GetSpec().GetEnvironment()
}
// PodCount returns the number of pods for the deployment
func (d *Deployment) PodCount() int {
count := 0
@ -192,3 +198,24 @@ func (d *Deployment) DatabaseVersion() (string, string) {
}
return string(info.ArangoDBVersion), license
}
// Members returns all members of the deployment by role.
func (d *Deployment) Members() map[api.ServerGroup][]server.Member {
result := make(map[api.ServerGroup][]server.Member)
status, _ := d.GetStatus()
status.Members.ForeachServerGroup(func(group api.ServerGroup, list api.MemberStatusList) error {
members := make([]server.Member, len(list))
for i, m := range list {
members[i] = member{
d: d,
id: m.ID,
group: group,
}
}
if len(members) > 0 {
result[group] = members
}
return nil
})
return result
}

View file

@ -0,0 +1,68 @@
//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//
package deployment
import (
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type member struct {
d *Deployment
group api.ServerGroup
id string
}
func (m member) status() (api.MemberStatus, bool) {
status, _ := m.d.GetStatus()
result, _, found := status.Members.ElementByID(m.id)
return result, found
}
func (m member) ID() string {
return m.id
}
func (m member) PodName() string {
if status, found := m.status(); found {
return status.PodName
}
return ""
}
func (m member) PVCName() string {
if status, found := m.status(); found {
return status.PersistentVolumeClaimName
}
return ""
}
func (m member) PVName() string {
if status, found := m.status(); found && status.PersistentVolumeClaimName != "" {
pvcs := m.d.deps.KubeCli.CoreV1().PersistentVolumeClaims(m.d.Namespace())
if pvc, err := pvcs.Get(status.PersistentVolumeClaimName, metav1.GetOptions{}); err == nil {
return pvc.Spec.VolumeName
}
}
return ""
}

View file

@ -47,3 +47,16 @@ func (o *Operator) GetDeployments() ([]server.Deployment, error) {
})
return result, nil
}
// GetDeployment returns detailed information for a deployment, managed by the operator, with given name
func (o *Operator) GetDeployment(name string) (server.Deployment, error) {
o.Dependencies.LivenessProbe.Lock()
defer o.Dependencies.LivenessProbe.Unlock()
for _, d := range o.deployments {
if d.Name() == name {
return d, nil
}
}
return nil, maskAny(server.NotFoundError)
}

View file

@ -23,6 +23,7 @@
package server
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
@ -30,13 +31,21 @@ import (
)
var (
maskAny = errors.WithStack
maskAny = errors.WithStack
NotFoundError = fmt.Errorf("not found")
)
func isNotFound(err error) bool {
return err == NotFoundError || errors.Cause(err) == NotFoundError
}
// sendError sends an error on the given context
func sendError(c *gin.Context, err error) {
// TODO proper status handling
code := http.StatusInternalServerError
if isNotFound(err) {
code = http.StatusNotFound
}
c.JSON(code, gin.H{
"error": err.Error(),
})

View file

@ -24,6 +24,8 @@ package server
import (
"net/http"
"sort"
"strings"
"github.com/gin-gonic/gin"
@ -35,6 +37,7 @@ type Deployment interface {
Name() string
Namespace() string
Mode() api.DeploymentMode
Environment() api.Environment
PodCount() int
ReadyPodCount() int
VolumeCount() int
@ -42,11 +45,23 @@ type Deployment interface {
StorageClasses() []string
DatabaseURL() string
DatabaseVersion() (string, string)
Members() map[api.ServerGroup][]Member
}
// Member is the API implemented by a member of an ArangoDeployment.
type Member interface {
ID() string
PodName() string
PVCName() string
PVName() string
}
// DeploymentOperator is the API implemented by the deployment operator.
type DeploymentOperator interface {
// GetDeployments returns basic information for all deployments managed by the operator
GetDeployments() ([]Deployment, error)
// GetDeployment returns detailed information for a deployment, managed by the operator, with given name
GetDeployment(name string) (Deployment, error)
}
// DeploymentInfo is the information returned per deployment.
@ -54,6 +69,7 @@ type DeploymentInfo struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Mode api.DeploymentMode `json:"mode"`
Environment api.Environment `json:"environment"`
PodCount int `json:"pod_count"`
ReadyPodCount int `json:"ready_pod_count"`
VolumeCount int `json:"volume_count"`
@ -64,6 +80,76 @@ type DeploymentInfo struct {
DatabaseLicense string `json:"database_license"`
}
// newDeploymentInfo initializes a DeploymentInfo for the given Deployment.
func newDeploymentInfo(d Deployment) DeploymentInfo {
version, license := d.DatabaseVersion()
return DeploymentInfo{
Name: d.Name(),
Namespace: d.Namespace(),
Mode: d.Mode(),
Environment: d.Environment(),
PodCount: d.PodCount(),
ReadyPodCount: d.ReadyPodCount(),
VolumeCount: d.VolumeCount(),
ReadyVolumeCount: d.ReadyVolumeCount(),
StorageClasses: d.StorageClasses(),
DatabaseURL: d.DatabaseURL(),
DatabaseVersion: version,
DatabaseLicense: license,
}
}
// MemberInfo contains detailed info of a specific member of the deployment
type MemberInfo struct {
ID string `json:"id"`
PodName string `json:"pod_name"`
PVCName string `json:"pvc_name"`
PVName string `json:"pv_name"`
}
// newMemberInfo creates a MemberInfo for the given member
func newMemberInfo(m Member) MemberInfo {
return MemberInfo{
ID: m.ID(),
PodName: m.PodName(),
PVCName: m.PVCName(),
PVName: m.PVName(),
}
}
// MemberGroupInfo contained detailed info of a group (e.g. Agent) of members
type MemberGroupInfo struct {
Group string `json:"group"`
Members []MemberInfo `json:"members"`
}
// DeploymentInfoDetails is the detailed information returned per deployment.
type DeploymentInfoDetails struct {
DeploymentInfo
MemberGroups []MemberGroupInfo `json:"member_groups"`
}
// newDeploymentInfoDetails initializes a DeploymentInfoDetails for the given Deployment.
func newDeploymentInfoDetails(d Deployment) DeploymentInfoDetails {
result := DeploymentInfoDetails{
DeploymentInfo: newDeploymentInfo(d),
}
for group, list := range d.Members() {
memberInfos := make([]MemberInfo, len(list))
for i, m := range list {
memberInfos[i] = newMemberInfo(m)
}
result.MemberGroups = append(result.MemberGroups, MemberGroupInfo{
Group: strings.Title(group.AsRole()),
Members: memberInfos,
})
}
sort.Slice(result.MemberGroups, func(i, j int) bool {
return result.MemberGroups[i].Group < result.MemberGroups[j].Group
})
return result
}
// Handle a GET /api/deployment request
func (s *Server) handleGetDeployments(c *gin.Context) {
if do := s.deps.Operators.DeploymentOperator(); do != nil {
@ -74,20 +160,7 @@ func (s *Server) handleGetDeployments(c *gin.Context) {
} else {
result := make([]DeploymentInfo, len(depls))
for i, d := range depls {
version, license := d.DatabaseVersion()
result[i] = DeploymentInfo{
Name: d.Name(),
Namespace: d.Namespace(),
Mode: d.Mode(),
PodCount: d.PodCount(),
ReadyPodCount: d.ReadyPodCount(),
VolumeCount: d.VolumeCount(),
ReadyVolumeCount: d.ReadyVolumeCount(),
StorageClasses: d.StorageClasses(),
DatabaseURL: d.DatabaseURL(),
DatabaseVersion: version,
DatabaseLicense: license,
}
result[i] = newDeploymentInfo(d)
}
c.JSON(http.StatusOK, gin.H{
"deployments": result,
@ -95,3 +168,17 @@ func (s *Server) handleGetDeployments(c *gin.Context) {
}
}
}
// Handle a GET /api/deployment/:name request
func (s *Server) handleGetDeploymentDetails(c *gin.Context) {
if do := s.deps.Operators.DeploymentOperator(); do != nil {
// Fetch deployments
depl, err := do.GetDeployment(c.Params.ByName("name"))
if err != nil {
sendError(c, err)
} else {
result := newDeploymentInfoDetails(depl)
c.JSON(http.StatusOK, result)
}
}
}

View file

@ -146,6 +146,7 @@ func NewServer(cli corev1.CoreV1Interface, cfg Config, deps Dependencies) (*Serv
// Deployment operator
api.GET("/deployment", s.handleGetDeployments)
api.GET("/deployment/:name", s.handleGetDeploymentDetails)
}
// Dashboard
r.GET("/", createAssetFileHandler(dashboard.Assets.Files["index.html"]))