From 92d4e5e9af718fdc929ace15a2b50ba390cb06ef Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Wed, 23 Jun 2021 15:15:11 +0100 Subject: [PATCH 1/4] Add grouping and more info to the explorer kube node list - Add POD stat to kube nodes table - Group kube nodes by management node pools, describe pools as per old norman node pools - Add Drain Node - Add ability to hide table columns depending on window width - hide certain stats at certain widths - Fixed an issue where RAM & CPU stats were reported strangely (multiplied over an above normal % only to be reduced to working % in formatter) --- assets/styles/base/_variables.scss | 8 +- assets/translations/en-us.yaml | 33 +++ components/SortableTable/THead.vue | 22 +- components/SortableTable/index.vue | 37 ++- components/SortableTable/selection.js | 4 +- components/dialog/DrainNode.vue | 219 +++++++++++++++++ components/form/RadioGroup.vue | 2 +- components/formatter/PercentageBar.vue | 2 +- config/product/explorer.js | 3 +- config/table-headers.js | 6 +- config/types.js | 2 + edit/node.vue | 1 - list/node.vue | 223 +++++++++++++++++- models/management.cattle.io.node.js | 14 ++ models/management.cattle.io.nodepool.js | 13 + models/management.cattle.io.nodetemplate.js | 117 +++++++++ models/{node.js => node/kube-node.js} | 125 +++++++++- .../_cluster/_product/projectsnamespaces.vue | 61 +++-- pages/home.vue | 2 +- plugins/steve/model-loader.js | 21 ++ plugins/steve/resource-instance.js | 2 + 21 files changed, 849 insertions(+), 68 deletions(-) create mode 100644 components/dialog/DrainNode.vue create mode 100644 models/management.cattle.io.node.js rename models/{node.js => node/kube-node.js} (69%) diff --git a/assets/styles/base/_variables.scss b/assets/styles/base/_variables.scss index 39e043e5f0..ec34622c78 100644 --- a/assets/styles/base/_variables.scss +++ b/assets/styles/base/_variables.scss @@ -41,8 +41,8 @@ $z-indexes: ( // @media only screen and (min-width: map-get($breakpoints, '--viewport-*')) { // } $breakpoints: ( - '--viewport-4': 480px, - '--viewport-7': 768px, - '--viewport-9': 992px, - '--viewport-12': 1281px, + '--viewport-4': 480px, // Phone + '--viewport-7': 768px, // Tablet + '--viewport-9': 992px, // Laptop/Desktop + '--viewport-12': 1281px, // Desktop ); diff --git a/assets/translations/en-us.yaml b/assets/translations/en-us.yaml index e89103dde1..b1f2aaabaa 100644 --- a/assets/translations/en-us.yaml +++ b/assets/translations/en-us.yaml @@ -475,6 +475,10 @@ asyncButton: action: Download success: Saving waiting: Downloading… + drain: + action: Drain + success: Drained + waiting: Draining… edit: action: Save success: Saved @@ -1136,6 +1140,7 @@ cluster: cluster: Cluster Configuration etcd: etcd networking: Networking + nodePools: Node Pools machinePools: Machine Pools registry: Private Registry upgrade: Upgrade Strategy @@ -1145,6 +1150,9 @@ cluster: services: Services allServices: Rotate all service certificates selectService: Rotate an individual service + nodePool: + scaleDown: Scale Pool Down + scaleUp: Scale Pool Up clusterIndexPage: hardwareResourceGauge: @@ -1223,6 +1231,27 @@ detailText: other {+ {n, number} more chars} } +drainNode: + action: 'Drain' + actionStop: 'Stop Drain' + titleOne: Drain {name} + titleMultiple: 'Drain {count} Nodes' + deleteLocalData: Delete Empty Dir Data + force: Force + safe: + label: Safe + helpText: If a node has standalone pods or ephemeral data it will be cordoned but not drained. + gracePeriod: + title: Grace period for pods to terminate themselves + default: Honor the default from each pod + placeholder: e.g. 30 + custom: "Ignore the defaults and give each pod:" + timeout: + title: "Drain timeout" + default: Keep trying forever + placeholder: e.g. 60 + custom: "Give up after:" + etcdInfoBanner: hasLeader: "Etcd has a leader:" leaderChanges: "Number of leader changes:" @@ -2110,6 +2139,9 @@ namespaceList: addLabel: Add Namespace node: + list: + pool: Pool + nodeTaint: Taints detail: detailTop: containerRuntime: Container Runtime @@ -3542,6 +3574,7 @@ tableHeaders: subType: Kind success: Success summary: Summary + taints: Taints target: Target targetKind: Target Type targetPort: Target diff --git a/components/SortableTable/THead.vue b/components/SortableTable/THead.vue index b1fa52c37e..fe4a354f8f 100644 --- a/components/SortableTable/THead.vue +++ b/components/SortableTable/THead.vue @@ -132,7 +132,7 @@ export default { :key="col.name" :align="col.align || 'left'" :width="col.width" - :class="{ sortable: col.sort }" + :class="{ sortable: col.sort, [col.breakpoint]: !!col.breakpoint}" @click.prevent="changeSort($event, col)" > @@ -180,6 +180,26 @@ export default { & A { color: var(--body-text); } + + // Aligns with COLUMN_BREAKPOINTS + @media only screen and (max-width: map-get($breakpoints, '--viewport-4')) { + // HIDE column on sizes below 480px + &.tablet, &.laptop, &.desktop { + display: none; + } + } + @media only screen and (max-width: map-get($breakpoints, '--viewport-9')) { + // HIDE column on sizes below 992px + &.laptop, &.desktop { + display: none; + } + } + @media only screen and (max-width: map-get($breakpoints, '--viewport-12')) { + // HIDE column on sizes below 1281px + &.desktop { + display: none; + } + } } .icon-stack { diff --git a/components/SortableTable/index.vue b/components/SortableTable/index.vue index 7143eb5ef0..d656320ab7 100644 --- a/components/SortableTable/index.vue +++ b/components/SortableTable/index.vue @@ -13,6 +13,21 @@ import sorting from './sorting'; import paging from './paging'; import grouping from './grouping'; +export const COLUMN_BREAKPOINTS = { + /** + * Only show column if at tablet width or wider + */ + TABLET: 'tablet', + /** + * Only show column if at laptop width or wider + */ + LAPTOP: 'laptop', + /** + * Only show column if at desktop width or wider + */ + DESKTOP: 'desktop' +}; + // @TODO: // Fixed header/scrolling @@ -598,7 +613,7 @@ export default { :key="col.name" :data-title="labelFor(col)" :align="col.align || 'left'" - :class="{['col-'+dasherize(col.formatter||'')]: !!col.formatter}" + :class="{['col-'+dasherize(col.formatter||'')]: !!col.formatter, [col.breakpoint]: !!col.breakpoint}" :width="col.width" > @@ -708,6 +723,26 @@ export default { box-shadow: none; } } + + // Aligns with COLUMN_BREAKPOINTS + @media only screen and (max-width: map-get($breakpoints, '--viewport-4')) { + // HIDE column on sizes below 480px + &.tablet, &.laptop, &.desktop { + display: none; + } + } + @media only screen and (max-width: map-get($breakpoints, '--viewport-9')) { + // HIDE column on sizes below 992px + &.laptop, &.desktop { + display: none; + } + } + @media only screen and (max-width: map-get($breakpoints, '--viewport-12')) { + // HIDE column on sizes below 1281px + &.desktop { + display: none; + } + } } diff --git a/components/SortableTable/selection.js b/components/SortableTable/selection.js index 2be65acd49..4df8fc8bfe 100644 --- a/components/SortableTable/selection.js +++ b/components/SortableTable/selection.js @@ -111,7 +111,7 @@ export default { onRowMouseEnter(e) { const tr = $(e.target).closest('TR'); - if (tr.hasClass('state-description')) { + if (tr.hasClass('sub-row')) { const trMainRow = tr.prev('TR'); trMainRow.toggleClass('sub-row-hovered', true); @@ -121,7 +121,7 @@ export default { onRowMouseLeave(e) { const tr = $(e.target).closest('TR'); - if (tr.hasClass('state-description')) { + if (tr.hasClass('sub-row')) { const trMainRow = tr.prev('TR'); trMainRow.toggleClass('sub-row-hovered', false); diff --git a/components/dialog/DrainNode.vue b/components/dialog/DrainNode.vue new file mode 100644 index 0000000000..fa538240b0 --- /dev/null +++ b/components/dialog/DrainNode.vue @@ -0,0 +1,219 @@ + + + + diff --git a/components/form/RadioGroup.vue b/components/form/RadioGroup.vue index 7b9936aabd..f9eea92318 100644 --- a/components/form/RadioGroup.vue +++ b/components/form/RadioGroup.vue @@ -121,7 +121,7 @@ export default {