Last minute cleanup. Improving docker build process

This commit is contained in:
Eric Herbrandson
2019-03-16 14:03:15 -05:00
parent d37ecf91d1
commit d6fafd5ba6
22 changed files with 192 additions and 160 deletions
+15 -11
View File
@@ -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", "."]
ENTRYPOINT ["/sbin/tini", "--", "node", "."]
+16
View File
@@ -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)
+86 -99
View File
@@ -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",
+1 -2
View File
@@ -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",
+1 -1
View File
@@ -8,7 +8,7 @@ import log from './utils/log';
const genericError = (
<div id='content'>
<Error messages={['There was an error and this content was unable to be displayed.']} />;
<Error messages={['There was an error and this content was unable to be displayed.']} />
</div>
);
+6 -5
View File
@@ -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 => (
<div key={item.name} className='contentPanel'>
<Field name='Container'>{item.name}</Field>
<Field name='Image'>{item.image}</Field>
@@ -24,15 +25,15 @@ const ContainersPanel = ({spec}) => (
{item.resources && item.resources.requests && (
<>
<Field name='Cpu Request'>{item.resources.requests && item.resources.requests.cpu}</Field>
<Field name='Memory Request'>{item.resources.requests && item.resources.requests.memory}</Field>
<Field name='Cpu Request'>{item.resources.requests.cpu}</Field>
<Field name='Memory Request'>{item.resources.requests.memory}</Field>
</>
)}
{item.resources && item.resources.limits && (
<>
<Field name='Cpu Limit'>{item.resources.limits && item.resources.limits.cpu}</Field>
<Field name='Memory Limit'>{item.resources.limits && item.resources.limits.memory}</Field>
<Field name='Cpu Limit'>{item.resources.limits.cpu}</Field>
<Field name='Memory Limit'>{item.resources.limits.memory}</Field>
</>
)}
+2 -2
View File
@@ -41,8 +41,8 @@ export default class Menu extends Base {
{/* Security */}
<Group>
<MenuItem title='Accounts' path='serviceaccount' resource='ServiceAccount' />
<MenuItem title='Roles' path='role' resource='Role' additionalPaths={['clusterrolebinding']} />
<MenuItem title='Bindings' path='rolebinding' resource='Role' additionalPaths={['clusterrole']} />
<MenuItem title='Roles' path='role' resource='Role' additionalPaths={['clusterrole']} />
<MenuItem title='Bindings' path='rolebinding' resource='Role' additionalPaths={['clusterrolebinding']} />
<MenuItem title='Secrets' path='secret' resource='Secret' />
</Group>
+1 -1
View File
@@ -46,7 +46,7 @@ export default class PodsPanel extends Base {
/>
{!skipNodeName && <td>{x.spec.nodeName}</td>}
<td>{x.status.phase}</td>
<td>{x.spec.containers.length}</td>
<td>{(x.spec.containers || []).length}</td>
<td>{_.sumBy(x.status.containerStatuses, 'restartCount')}</td>
<td><Cpu item={x} metrics={metrics} /></td>
<td><Ram item={x} metrics={metrics} /></td>
+13 -6
View File
@@ -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) {
+1 -1
View File
@@ -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;
}
+2 -2
View File
@@ -65,8 +65,8 @@ export default class Ingress extends Base {
<tr key={`${rule.host}:${path.path}`}>
<td>{rule.host}</td>
<td>{path.path}</td>
<td>{path.backend.serviceName}</td>
<td>{path.backend.servicePort}</td>
<td>{path.backend && path.backend.serviceName}</td>
<td>{path.backend && path.backend.servicePort}</td>
</tr>
))}
</>
+3 -2
View File
@@ -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}`}
/>
<td>{x.spec.rules.map(y => y.host).join(' • ')}</td>
<td>{x.spec.rules.flatMap(y => y.http.paths).map(y => y.path).join(' • ')}</td>
<td>{_.map(x.spec.rules, y => y.host).join(' • ')}</td>
<td>{_.flatMap(x.spec.rules, y => y.http.paths).map(y => y.path).join(' • ')}</td>
</tr>
)) : (
<NoResults items={filtered} filter={filter} colSpan='6' />
+1 -1
View File
@@ -75,7 +75,7 @@ export default class Nodes extends Base {
{objectMap(x.metadata.labels)}
</td>
<td>
{x.status.conditions.find(y => y.type === 'Ready').status}
{x.status.conditions && (x.status.conditions.find(y => y.type === 'Ready') || {}).status}
</td>
<td>
<CpuChart item={x} metrics={filteredMetrics} />
+8 -6
View File
@@ -49,14 +49,16 @@ export default class PersistentVolume extends Base {
</a>
</Field>
<Field name='Claim'>
<a href={`#/persistentvolumeclaim/${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`}>
{`${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`}
</a>
{item.spec.claimRef && (
<a href={`#/persistentvolumeclaim/${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`}>
{`${item.spec.claimRef.namespace}/${item.spec.claimRef.name}`}
</a>
)}
</Field>
<Field name='Access Modes' value={item.spec.accessModes.join(' • ')} />
<Field name='Capacity' value={item.spec.capacity.storage} />
<Field name='Access Modes' value={item.spec.accessModes && item.spec.accessModes.join(' • ')} />
<Field name='Capacity' value={item.spec.capacity && item.spec.capacity.storage} />
<Field name='Reclaim Policy' value={item.spec.persistentVolumeReclaimPolicy} />
<Field name='Local Path' value={item.spec.local.path} />
<Field name='Local Path' value={item.spec.local && item.spec.local.path} />
</div>
)}
</div>
+1 -1
View File
@@ -54,7 +54,7 @@ export default class PersistentVolumeClaim extends Base {
</a>
</Field>
<Field name='Modes' value={item.spec.accessModes.join(' • ')} />
<Field name='Capacity' value={item.status.capacity.storage} />
<Field name='Capacity' value={item.status.capacity && item.status.capacity.storage} />
</div>
)}
</div>
+1 -1
View File
@@ -52,7 +52,7 @@ export default class PersistentVolumeClaims extends Base {
<td>{x.spec.storageClassName}</td>
<td>{x.spec.accessModes.join(' • ')}</td>
<td>{x.spec.volumeName}</td>
<td>{x.status.capacity.storage}</td>
<td>{x.status.capacity && x.status.capacity.storage}</td>
</tr>
)) : (
<NoResults colSpan='9' items={filtered} filter={filter} />
+1 -1
View File
@@ -44,7 +44,7 @@ export default class PersistentVolumes extends Base {
href={`#/persistentvolume/${x.metadata.name}`}
/>
<td>{x.status.phase}</td>
<td>{x.spec.capacity.storage}</td>
<td>{x.spec.capacity && x.spec.capacity.storage}</td>
</tr>
)) : (
<NoResults items={filtered} filter={filter} colSpan='5' />
+11 -5
View File
@@ -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 {
</>
</ItemHeader>
{errors && <Error messages={errors} />}
{errors && !!errors.length && <Error messages={errors} />}
<div className='charts'>
<div className='charts_item'>
@@ -99,7 +97,7 @@ export default class Pod extends Base {
<Field name='Conditions'>
{_.map(item.status.conditions, x => (
<div key={x.type}>
<span>{x.type}</span> <span>{x.status}</span>
<span>{x.type}</span> <span>{x.status}</span> <span>{x.message}</span>
</div>
))}
</Field>
@@ -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;
}
+2 -1
View File
@@ -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 {
</thead>
<tbody>
{hasResults(ports) ? item.spec.ports.map(x => (
{hasResults(ports) ? _.map(item.spec.ports, x => (
<tr key={x.port}>
<td>{x.name}</td>
<td>{x.port}</td>
+2 -1
View File
@@ -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 {
<div>
<MetadataFields item={item} />
<Field name='Secrets'>
{item.secrets.map(x => (
{_.map(item.secrets, x => (
<div key={x.name}>
<a href={`#/secret/${namespace}/${x.name}`}>{x.name}</a>
</div>
+3 -4
View File
@@ -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();
}
+15 -7
View File
@@ -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) {