From d6fafd5ba60db818e257ebf04e4a556e4edfe659 Mon Sep 17 00:00:00 2001 From: Eric Herbrandson Date: Sat, 16 Mar 2019 14:03:15 -0500 Subject: [PATCH] Last minute cleanup. Improving docker build process --- Dockerfile | 26 +-- README.md | 16 ++ client/package-lock.json | 185 ++++++++++----------- client/package.json | 3 +- client/src/app.js | 2 +- client/src/components/containersPanel.js | 11 +- client/src/components/menu.js | 4 +- client/src/components/podsPanel.js | 2 +- client/src/services/api.js | 19 ++- client/src/services/apiProxy.js | 2 +- client/src/views/ingress.js | 4 +- client/src/views/ingresses.js | 5 +- client/src/views/nodes.js | 2 +- client/src/views/persistentVolume.js | 14 +- client/src/views/persistentVolumeClaim.js | 2 +- client/src/views/persistentVolumeClaims.js | 2 +- client/src/views/persistentVolumes.js | 2 +- client/src/views/pod.js | 16 +- client/src/views/service.js | 3 +- client/src/views/serviceAccount.js | 3 +- client/src/views/workloads.js | 7 +- server/index.js | 22 ++- 22 files changed, 192 insertions(+), 160 deletions(-) diff --git a/Dockerfile b/Dockerfile index e59f9b3..6b10a68 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,27 @@ -# THIS IS THE BASEIMAGE THAT ALL OTHER SERVICES ARE BUILT UPON +# Stage 1 - the build react app +FROM node:11.10.0-alpine as build-deps +WORKDIR /usr/src/app +COPY client/package.json client/package-lock.json ./ +RUN npm i +COPY client/ ./ +RUN npm run build + +# Stage 2 - the production environment FROM node:11.10.0-alpine RUN apk add --no-cache tini - ENV NODE_ENV production - -RUN mkdir -p /usr/src/app WORKDIR /usr/src/app - RUN chown -R node:node /usr/src/app/ +EXPOSE 4654 -COPY server/package.json /usr/src/app/ -COPY server/package-lock.json /usr/src/app/ -RUN npm install --production +COPY server/package.json server/package-lock.json ./ +RUN npm i --production -COPY client/build /usr/src/app/public -COPY server /usr/src/app +COPY --from=build-deps /usr/src/app/build /usr/src/app/public +COPY /server ./ USER node -ENTRYPOINT ["/sbin/tini", "--", "node", "."] \ No newline at end of file +ENTRYPOINT ["/sbin/tini", "--", "node", "."] diff --git a/README.md b/README.md index 084ab51..c1acfab 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,19 @@ K8dash relies heavily on [metrics-server](https://github.com/kubernetes-incubato + [Installing metrics-server](https://github.com/kubernetes-incubator/metrics-server) + [Running metrics-server with kubeadm](https://medium.com/@waleedkhan91/how-to-configure-metrics-server-on-kubeadm-provisioned-kubernetes-cluster-f755a2ac43a2) + + +# Development +K8dash is made up of 2 parts. The server and the client. + +### Server +To run the server, run `npm i` from the `/server` directory to install dependencies and then `npm start` to run the server. +The server is a simple express.js server that is primarily responsible for proxying requests to the Kubernetes api server. +During development, the server will use whatever is configured in `~/.kube/config` to connect the desired cluster. + +### Client +For the client, move to the `/client` directory, run `npm i` and then `npm start`. The client is a React application with minimal other dependencies. + +## License + +[Apache License 2.0](https://raw.githubusercontent.com/herbrandson/k8dash/master/LICENSE) \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 2ea8fdc..1ea3687 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1029,14 +1029,14 @@ } }, "@types/node": { - "version": "11.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.10.5.tgz", - "integrity": "sha512-DuIRlQbX4K+d5I+GMnv+UfnGh+ist0RdlvOp+JZ7ePJ6KQONCFQv/gKYSU1ZzbVdFSUCKZOltjmpFAGGv5MdYA==" + "version": "11.11.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.3.tgz", + "integrity": "sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg==" }, "@types/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", - "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" }, "@types/tapable": { "version": "1.0.2", @@ -1816,9 +1816,9 @@ } }, "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", + "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==" }, "async-foreach": { "version": "0.1.3", @@ -1841,12 +1841,12 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autoprefixer": { - "version": "9.4.10", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.10.tgz", - "integrity": "sha512-XR8XZ09tUrrSzgSlys4+hy5r2/z4Jp7Ag3pHm31U4g/CTccYPOVe19AkaJ4ey/vRd1sfj+5TtuD6I0PXtutjvQ==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.0.tgz", + "integrity": "sha512-hMKcyHsZn5+qL6AUeP3c8OyuteZ4VaUlg+fWbyl8z7PqsKHF/Bf8/px3K6AT8aMzDkBo8Bc11245MM+itDBOxQ==", "requires": { "browserslist": "^4.4.2", - "caniuse-lite": "^1.0.30000940", + "caniuse-lite": "^1.0.30000947", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", "postcss": "^7.0.14", @@ -2644,13 +2644,13 @@ } }, "browserslist": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.2.tgz", - "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.0.tgz", + "integrity": "sha512-92IS3knByY3wF7DDozdKwLxkvp23Ydn2O5L0qVwR1p/ioN7oIDl7d/eyPMc11rTVofT/6IbcdwP9eTId7orGZQ==", "requires": { - "caniuse-lite": "^1.0.30000939", - "electron-to-chromium": "^1.3.113", - "node-releases": "^1.1.8" + "caniuse-lite": "^1.0.30000948", + "electron-to-chromium": "^1.3.116", + "node-releases": "^1.1.10" } }, "bser": { @@ -2814,9 +2814,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000942", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000942.tgz", - "integrity": "sha512-wLf+IhZUy2rfz48tc40OH7jHjXjnvDFEYqBHluINs/6MgzoNLPf25zhE4NOVzqxLKndf+hau81sAW0RcGHIaBQ==" + "version": "1.0.30000949", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000949.tgz", + "integrity": "sha512-jIF/jphmuJ7oAWmfYO0qAxRAvCa0zNquALO6Ykfe6qo8qwh882Cgcs+OWmm21L3x6nu4TVLFeEZ9/q6VuKCfSg==" }, "capture-exit": { "version": "1.2.0", @@ -2859,9 +2859,9 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "chartist": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/chartist/-/chartist-0.11.0.tgz", - "integrity": "sha1-hLpeBUkNCW2T3PqTQ+vDHvajvSg=" + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/chartist/-/chartist-0.10.1.tgz", + "integrity": "sha1-PdUT1THfymt453f+BQDZx+ZAaTE=" }, "check-types": { "version": "7.4.0", @@ -5004,9 +5004,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.113", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", - "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==" + "version": "1.3.116", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz", + "integrity": "sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA==" }, "elliptic": { "version": "6.4.1", @@ -5214,9 +5214,9 @@ } }, "eslint-scope": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.2.tgz", - "integrity": "sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -6231,12 +6231,12 @@ } }, "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "requires": { "commondir": "^1.0.1", - "make-dir": "^1.0.0", + "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" } }, @@ -9312,9 +9312,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -10190,17 +10190,18 @@ } }, "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "requires": { - "pify": "^3.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "dependencies": { "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" } } }, @@ -10530,9 +10531,9 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", + "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==" }, "nanomatch": { "version": "1.2.13", @@ -10683,9 +10684,9 @@ } }, "node-releases": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.9.tgz", - "integrity": "sha512-oic3GT4OtbWWKfRolz5Syw0Xus0KRFxeorLNj0s93ofX6PWyuzKjsiGxsCtWktBwwmTF6DdRRf2KreGqeOk5KA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.11.tgz", + "integrity": "sha512-8v1j5KfP+s5WOTa1spNUAOfreajQPN12JXbRR0oDE+YrJBQCXBnNqUDj27EKpPLOoSiU3tKi3xGPB+JaOdUEQQ==", "requires": { "semver": "^5.3.0" } @@ -15633,15 +15634,6 @@ "prop-types": "^15.5.8" } }, - "react-chartjs-2": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.7.4.tgz", - "integrity": "sha512-lXTpBaDlk9rIMjRONjZd76dIUhEm3vOp2jOrJrsFG/UpFI5VqX8Xw83apVHTnUGJ968f8i/i/syLddls4NHy2g==", - "requires": { - "lodash": "^4.17.4", - "prop-types": "^15.5.8" - } - }, "react-dev-utils": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-7.0.5.tgz", @@ -16379,9 +16371,9 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regenerate-unicode-properties": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.1.tgz", - "integrity": "sha512-HTjMafphaH5d5QDHuwW8Me6Hbc/GhXg8luNqTkPVwZ/oCZhnoifjWhGYsu2BzepMELTlbnoVcXvV0f+2uDDvoQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", + "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", "requires": { "regenerate": "^1.4.0" } @@ -16427,12 +16419,12 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" }, "regexpu-core": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.3.tgz", - "integrity": "sha512-LON8666bTAlViVEPXMv65ZqiaR3rMNLz36PIaQ7D+er5snu93k0peR7FSvO0QteYbZ3GOkvfHKbGr/B1xDu9FA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.1", + "regenerate-unicode-properties": "^8.0.2", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", @@ -18044,29 +18036,24 @@ } }, "terser": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz", - "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", "requires": { - "commander": "~2.17.1", + "commander": "^2.19.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.9" + "source-map-support": "~0.5.10" }, "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -18327,19 +18314,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", "requires": { - "commander": "~2.17.1", + "commander": "~2.19.0", "source-map": "~0.6.1" }, "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -18501,9 +18483,9 @@ } }, "upath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.1.tgz", - "integrity": "sha512-D0yetkpIOKiZQquxjM2Syvy48Y1DbZ0SWxgsZiwd9GCWRpc75vN8ytzem14WDSg+oiX6+Qt31FpiS/ExODCrLg==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==" }, "upper-case": { "version": "1.1.3", @@ -18799,9 +18781,9 @@ } }, "eslint-scope": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.2.tgz", - "integrity": "sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -19207,15 +19189,20 @@ } }, "mem": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", - "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", "requires": { "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", + "mimic-fn": "^2.0.0", "p-is-promise": "^2.0.0" } }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==" + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", diff --git a/client/package.json b/client/package.json index d50eba7..368e502 100644 --- a/client/package.json +++ b/client/package.json @@ -3,14 +3,13 @@ "version": "0.1.0", "private": true, "dependencies": { - "chartist": "^0.11.0", + "chartist": "^0.10.1", "director": "^1.2.8", "lodash": "^4.17.11", "moment": "^2.24.0", "node-sass": "^4.11.0", "react": "^16.8.2", "react-chartist": "^0.13.3", - "react-chartjs-2": "^2.7.4", "react-dom": "^16.8.2", "react-modal": "^3.8.1", "react-scripts": "2.1.5", diff --git a/client/src/app.js b/client/src/app.js index 820c069..abae90a 100755 --- a/client/src/app.js +++ b/client/src/app.js @@ -8,7 +8,7 @@ import log from './utils/log'; const genericError = (
- ; +
); diff --git a/client/src/components/containersPanel.js b/client/src/components/containersPanel.js index cad675b..ccc1b6d 100644 --- a/client/src/components/containersPanel.js +++ b/client/src/components/containersPanel.js @@ -1,9 +1,10 @@ +import _ from 'lodash'; import React from 'react'; import Field from './field'; const ContainersPanel = ({spec}) => ( <> - {spec && spec.containers && spec.containers.map(item => ( + {spec && _.map(spec.containers, item => (
{item.name} {item.image} @@ -24,15 +25,15 @@ const ContainersPanel = ({spec}) => ( {item.resources && item.resources.requests && ( <> - {item.resources.requests && item.resources.requests.cpu} - {item.resources.requests && item.resources.requests.memory} + {item.resources.requests.cpu} + {item.resources.requests.memory} )} {item.resources && item.resources.limits && ( <> - {item.resources.limits && item.resources.limits.cpu} - {item.resources.limits && item.resources.limits.memory} + {item.resources.limits.cpu} + {item.resources.limits.memory} )} diff --git a/client/src/components/menu.js b/client/src/components/menu.js index e14ef86..1a07f7e 100644 --- a/client/src/components/menu.js +++ b/client/src/components/menu.js @@ -41,8 +41,8 @@ export default class Menu extends Base { {/* Security */} - - + + diff --git a/client/src/components/podsPanel.js b/client/src/components/podsPanel.js index df5abb0..27bf44c 100644 --- a/client/src/components/podsPanel.js +++ b/client/src/components/podsPanel.js @@ -46,7 +46,7 @@ export default class PodsPanel extends Base { /> {!skipNodeName && {x.spec.nodeName}} {x.status.phase} - {x.spec.containers.length} + {(x.spec.containers || []).length} {_.sumBy(x.status.containerStatuses, 'restartCount')} diff --git a/client/src/services/api.js b/client/src/services/api.js index 3d1bdf7..76e7a69 100644 --- a/client/src/services/api.js +++ b/client/src/services/api.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import {request, stream, streamResult, streamResults} from './apiProxy'; +import {request, stream, streamResult, streamResults, getToken} from './apiProxy'; import log from '../utils/log'; const JSON_HEADERS = {Accept: 'application/json', 'Content-Type': 'application/json'}; @@ -39,7 +39,14 @@ const apis = { }; function testAuth() { - return request('/api/v1/namespaces', null, false); + const token = getToken(); + const body = { + apiVerstion: 'authentication.k8s.io/v1', + kind: 'TokenReview', + spec: {token}, + }; + + return post('/apis/authentication.k8s.io/v1/tokenreviews', body, false); } async function apply(body) { @@ -151,16 +158,16 @@ function logs(namespace, name, container, cb) { } } -function post(url, json) { +function post(url, json, autoLogoutOnAuthError = true) { const body = JSON.stringify(json); const opts = {method: 'POST', body, headers: JSON_HEADERS}; - return request(url, opts); + return request(url, opts, autoLogoutOnAuthError); } -function put(url, json) { +function put(url, json, autoLogoutOnAuthError = true) { const body = JSON.stringify(json); const opts = {method: 'PUT', body, headers: JSON_HEADERS}; - return request(url, opts); + return request(url, opts, autoLogoutOnAuthError); } function del(url) { diff --git a/client/src/services/apiProxy.js b/client/src/services/apiProxy.js index 577e88c..9c90cd8 100644 --- a/client/src/services/apiProxy.js +++ b/client/src/services/apiProxy.js @@ -5,7 +5,7 @@ const nonHashedUrl = href.replace(hash, '').replace(search, ''); const BASE_HTTP_URL = host === 'localhost:4653' ? 'http://localhost:4654' : nonHashedUrl; const BASE_WS_URL = BASE_HTTP_URL.replace('http', 'ws'); -function getToken() { +export function getToken() { return localStorage.authToken; } diff --git a/client/src/views/ingress.js b/client/src/views/ingress.js index 2a5be28..f42e241 100644 --- a/client/src/views/ingress.js +++ b/client/src/views/ingress.js @@ -65,8 +65,8 @@ export default class Ingress extends Base { {rule.host} {path.path} - {path.backend.serviceName} - {path.backend.servicePort} + {path.backend && path.backend.serviceName} + {path.backend && path.backend.servicePort} ))} diff --git a/client/src/views/ingresses.js b/client/src/views/ingresses.js index 647683e..082ce80 100644 --- a/client/src/views/ingresses.js +++ b/client/src/views/ingresses.js @@ -1,3 +1,4 @@ +import _ from 'lodash'; import React from 'react'; import Base from '../components/base'; import Filter from '../components/filter'; @@ -45,8 +46,8 @@ export default class Ingresses extends Base { includeNamespace={true} href={`#/ingress/${x.metadata.namespace}/${x.metadata.name}`} /> - {x.spec.rules.map(y => y.host).join(' • ')} - {x.spec.rules.flatMap(y => y.http.paths).map(y => y.path).join(' • ')} + {_.map(x.spec.rules, y => y.host).join(' • ')} + {_.flatMap(x.spec.rules, y => y.http.paths).map(y => y.path).join(' • ')} )) : ( diff --git a/client/src/views/nodes.js b/client/src/views/nodes.js index 437c710..0874684 100644 --- a/client/src/views/nodes.js +++ b/client/src/views/nodes.js @@ -75,7 +75,7 @@ export default class Nodes extends Base { {objectMap(x.metadata.labels)} - {x.status.conditions.find(y => y.type === 'Ready').status} + {x.status.conditions && (x.status.conditions.find(y => y.type === 'Ready') || {}).status} diff --git a/client/src/views/persistentVolume.js b/client/src/views/persistentVolume.js index cc8433c..d59c7f1 100644 --- a/client/src/views/persistentVolume.js +++ b/client/src/views/persistentVolume.js @@ -49,14 +49,16 @@ export default class PersistentVolume extends Base { - - {`${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`} - + {item.spec.claimRef && ( + + {`${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`} + + )} - - + + - +
)} diff --git a/client/src/views/persistentVolumeClaim.js b/client/src/views/persistentVolumeClaim.js index ce9d0e1..8e9b1a2 100644 --- a/client/src/views/persistentVolumeClaim.js +++ b/client/src/views/persistentVolumeClaim.js @@ -54,7 +54,7 @@ export default class PersistentVolumeClaim extends Base { - + )} diff --git a/client/src/views/persistentVolumeClaims.js b/client/src/views/persistentVolumeClaims.js index 830ad79..dc3a0eb 100644 --- a/client/src/views/persistentVolumeClaims.js +++ b/client/src/views/persistentVolumeClaims.js @@ -52,7 +52,7 @@ export default class PersistentVolumeClaims extends Base { {x.spec.storageClassName} {x.spec.accessModes.join(' • ')} {x.spec.volumeName} - {x.status.capacity.storage} + {x.status.capacity && x.status.capacity.storage} )) : ( diff --git a/client/src/views/persistentVolumes.js b/client/src/views/persistentVolumes.js index c4a225c..85bb047 100644 --- a/client/src/views/persistentVolumes.js +++ b/client/src/views/persistentVolumes.js @@ -44,7 +44,7 @@ export default class PersistentVolumes extends Base { href={`#/persistentvolume/${x.metadata.name}`} /> {x.status.phase} - {x.spec.capacity.storage} + {x.spec.capacity && x.spec.capacity.storage} )) : ( diff --git a/client/src/views/pod.js b/client/src/views/pod.js index 5562762..d1f2c6e 100644 --- a/client/src/views/pod.js +++ b/client/src/views/pod.js @@ -36,9 +36,7 @@ export default class Pod extends Base { const {namespace, name} = this.props; const {item, metrics, events} = this.state || {}; - const errors = item && item.status.conditions - .filter(x => !!x.message) - .map(x => x.message); + const errors = getErrors(item); const filteredEvents = filterByOwner(events, item); @@ -62,7 +60,7 @@ export default class Pod extends Base { - {errors && } + {errors && !!errors.length && }
@@ -99,7 +97,7 @@ export default class Pod extends Base { {_.map(item.status.conditions, x => (
- {x.type}{x.status} + {x.type}{x.status}{x.message}
))}
@@ -164,3 +162,11 @@ function Ram({item, metrics}) { /> ); } + +function getErrors(item) { + if (!item) return []; + if (item.status.message) return [item.status.message]; + if (item.status.conditions) return item.status.conditions.map(x => x.message).filter(x => !!x); + + return null; +} diff --git a/client/src/views/service.js b/client/src/views/service.js index d7bed62..297f61c 100644 --- a/client/src/views/service.js +++ b/client/src/views/service.js @@ -1,3 +1,4 @@ +import _ from 'lodash'; import React from 'react'; import api from '../services/api'; import EventsPanel from '../components/eventsPanel'; @@ -65,7 +66,7 @@ export default class Service extends Base { - {hasResults(ports) ? item.spec.ports.map(x => ( + {hasResults(ports) ? _.map(item.spec.ports, x => ( {x.name} {x.port} diff --git a/client/src/views/serviceAccount.js b/client/src/views/serviceAccount.js index f25a07e..3a199cc 100644 --- a/client/src/views/serviceAccount.js +++ b/client/src/views/serviceAccount.js @@ -1,3 +1,4 @@ +import _ from 'lodash'; import React from 'react'; import Base from '../components/base'; import api from '../services/api'; @@ -43,7 +44,7 @@ export default class ServiceAccount extends Base {
- {item.secrets.map(x => ( + {_.map(item.secrets, x => ( diff --git a/client/src/views/workloads.js b/client/src/views/workloads.js index cb3d56d..89e3201 100644 --- a/client/src/views/workloads.js +++ b/client/src/views/workloads.js @@ -35,8 +35,7 @@ export default class Workloads extends Base { const {cronJobs, daemonSets, deployments, jobs, statefulSets, filter = '', sortBy, sortDirection} = this.state || {}; const items = [cronJobs, daemonSets, deployments, jobs, statefulSets]; - let filtered = filterControllers(filter, items); - filtered = _.orderBy(filtered, [sortBy], [sortDirection]); + const filtered = filterControllers(filter, items, sortBy, sortDirection); const controllerCount = filtered && filtered.length; const pendingControllerCount = getPendingControllerCount(filtered); @@ -133,14 +132,14 @@ function getExpectedCount({spec, status}) { return spec.replicas || status.currentNumberScheduled || 0; } -function filterControllers(filter, items) { +function filterControllers(filter, items, sortBy, sortDirection) { const results = items.flat(); if (results.length && items.some(x => !x)) return null; return _(results) .flatten() - .sortBy('metadata.name') + .orderBy([sortBy], [sortDirection]) .filter(x => test(filter, x.metadata.name)) .value(); } diff --git a/server/index.js b/server/index.js index b4336bf..9c29136 100644 --- a/server/index.js +++ b/server/index.js @@ -47,15 +47,23 @@ function logging(req, res, next) { } async function getOidc(req, res) { - const authEndpoint = await getOidcEndpoint(); - res.json({authEndpoint}); + try { + const authEndpoint = await getOidcEndpoint(); + res.json({authEndpoint}); + } catch (err) { + next(err); + } } -async function postOidc(req, res) { - const body = await toString(req); - const {code, redirectUri} = JSON.parse(body); - const token = await oidcAuthenticate(code, redirectUri); - res.json({token}); +async function postOidc(req, res, next) { + try { + const body = await toString(req); + const {code, redirectUri} = JSON.parse(body); + const token = await oidcAuthenticate(code, redirectUri); + res.json({token}); + } catch (err) { + next(err); + } } function onError(err, req, res) {