From 74a7fbeee5095bba02f580c809abe961b7ed55ca Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 20 Apr 2020 16:48:04 -0700 Subject: [PATCH 01/23] use h3 instead of code elements --- .../addon/templates/components/known-secondaries-card.hbs | 2 +- .../addon/templates/components/replication-primary-card.hbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/replication/addon/templates/components/known-secondaries-card.hbs b/ui/lib/replication/addon/templates/components/known-secondaries-card.hbs index b2588c0911da..10b09a7338d0 100644 --- a/ui/lib/replication/addon/templates/components/known-secondaries-card.hbs +++ b/ui/lib/replication/addon/templates/components/known-secondaries-card.hbs @@ -1,6 +1,6 @@
- Known Secondaries +

Known Secondaries

Manage diff --git a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs index 26a180cfd367..5633c5a704c7 100644 --- a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs +++ b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs @@ -1,5 +1,5 @@
- {{title}} +

{{title}}

{{description}} From b23c1b411c25f5000c9b459f5e1ad3b3ff54db3f Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 20 Apr 2020 17:11:19 -0700 Subject: [PATCH 02/23] use correct property names for StateDisplay --- .../addon/templates/components/replication-mode-summary.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs index 399efe065415..f910e3b1ae71 100644 --- a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs +++ b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs @@ -105,9 +105,9 @@ Enable {{/link-to}} {{else if (eq mode 'dr')}} - {{cluster.drReplicationStateDisplay}} + {{cluster.drStateDisplay}} {{else if (eq mode 'performance')}} - {{cluster.perfReplicationStateDisplay}} + {{cluster.performanceStateDisplay}} {{/if}}
{{/if}} From 4553a300c7edba218a4dfbba8d948046b7e48b6d Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 20 Apr 2020 17:24:02 -0700 Subject: [PATCH 03/23] WIP --- .../addon/components/replication-primary-card.js | 11 +++++++++++ .../templates/components/replication-primary-card.hbs | 3 +++ 2 files changed, 14 insertions(+) diff --git a/ui/lib/replication/addon/components/replication-primary-card.js b/ui/lib/replication/addon/components/replication-primary-card.js index 15be77c7a711..d2d0cc83bf46 100644 --- a/ui/lib/replication/addon/components/replication-primary-card.js +++ b/ui/lib/replication/addon/components/replication-primary-card.js @@ -1,4 +1,5 @@ import Component from '@ember/component'; +import { computed } from '@ember/object'; /** * @module ReplicationPrimaryCard @@ -24,4 +25,14 @@ export default Component.extend({ description: null, metric: null, glyph: null, + hasError: computed('title', 'metric', function() { + // TODO: can we make a map somewhere in the cluster that keeps track of all the good and bad states + // as well as their glyphs? this could replace the cluster StateDiplay and StateGlyph + // TODO: then add tests to ensure we show the correct error msg + return this.title === 'State' && this.metric !== 'running'; + }), + errorMessage: computed('hasError', function() { + // TODO figure out if we need another error message + return this.hasError ? 'Check server logs!' : false; + }), }); diff --git a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs index 5633c5a704c7..bfa4a6e565d3 100644 --- a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs +++ b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs @@ -1,6 +1,9 @@

{{title}}

+ {{#if hasError}} + + {{/if}} {{description}} From 0e39b9c1de181c1a0959cc47c6fc7714fcc2779b Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Tue, 21 Apr 2020 13:33:10 -0700 Subject: [PATCH 04/23] remove todo --- .../addon/templates/components/replication-summary.hbs | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index d04d708422d3..394c5619c778 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -345,7 +345,6 @@
- {{!-- TODO: there are 2 attributes for both state and lastWAL. which one do I use? --}} Date: Tue, 21 Apr 2020 17:32:01 -0700 Subject: [PATCH 05/23] move cluster states into a map; make status menu icon match cluster state --- ui/app/models/cluster.js | 39 ++++++++++++------- .../components/replication-mode-summary.hbs | 2 +- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index f7542c1ce2e9..7a64175d061a 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -5,6 +5,17 @@ import DS from 'ember-data'; import { fragment } from 'ember-data-model-fragments/attributes'; const { hasMany, attr } = DS; +const STATES = { + running: { glyph: 'check-circle-outline', isOk: true }, + 'stream-wals': { glyph: 'android-sync', display: 'Streaming', isOk: true }, + 'merkle-diff': { glyph: 'android-sync', display: 'Determining sync status', isOk: true }, + connecting: { glyph: 'android-sync', display: 'Streaming', isOk: true }, + 'merkle-sync': { glyph: 'android-sync', display: 'Syncing', isOk: true }, + idle: { glyph: 'cancel-circle-fill', isOk: false }, + 'transient-failure': { glyph: 'cancel-circle-fill', isOk: false }, + shutdown: { glyph: 'cancel-circle-fill', isOk: false }, +}; + export default DS.Model.extend({ version: service(), @@ -54,13 +65,8 @@ export default DS.Model.extend({ return null; } const defaultDisp = 'Synced'; - const displays = { - 'stream-wals': 'Streaming', - 'merkle-diff': 'Determining sync status', - 'merkle-sync': 'Syncing', - }; - return displays[state] || defaultDisp; + return STATES[state].display || defaultDisp; }, drStateDisplay: computed('dr.state', function() { @@ -73,14 +79,7 @@ export default DS.Model.extend({ stateGlyph(state) { const glyph = 'check-circle-outline'; - - const glyphs = { - 'stream-wals': 'android-sync', - 'merkle-diff': 'android-sync', - 'merkle-sync': null, - }; - - return glyphs[state] || glyph; + return STATES[state].glyph || glyph; }, drStateGlyph: computed('dr.state', function() { @@ -91,6 +90,18 @@ export default DS.Model.extend({ return this.stateGlyph(this.get('performance.state')); }), + hasOkState(state) { + return STATES[state].isOk || false; + }, + + drHasOkState: computed('dr.state', function() { + return this.hasOkState(this.get('dr.state')); + }), + + performanceHasOkState: computed('performance.state', function() { + return this.hasOkState(this.get('performance.state')); + }), + dr: fragment('replication-attributes'), performance: fragment('replication-attributes'), // this service exposes what mode the UI is currently viewing diff --git a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs index f910e3b1ae71..6b44951f29d4 100644 --- a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs +++ b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs @@ -32,7 +32,7 @@
{{#if replicationEnabled}} {{#if (get cluster (concat mode 'StateGlyph'))}} - +

{{metric}} - {{#if glyph}} + {{#if (and glyph (not hasError))}} {{/if}}

diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index 394c5619c778..f4e64ca06851 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -349,6 +349,7 @@ @title='State' @description='Updated every ten seconds.' @glyph={{get cluster (concat replicationMode 'StateGlyph')}} + @hasOkState={{get cluster (concat replicationMode 'HasOkState')}} @metric={{replicationAttrs.state}}/> Date: Wed, 22 Apr 2020 09:44:13 -0700 Subject: [PATCH 07/23] whitespace --- .../vault/cluster/replication-dr-promote/details.hbs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/templates/vault/cluster/replication-dr-promote/details.hbs b/ui/app/templates/vault/cluster/replication-dr-promote/details.hbs index d1dd67dbab41..50178b8b1475 100644 --- a/ui/app/templates/vault/cluster/replication-dr-promote/details.hbs +++ b/ui/app/templates/vault/cluster/replication-dr-promote/details.hbs @@ -2,11 +2,11 @@
{{!-- ARG TODO setup error state and return --}} - - {{#if Dashboard.isSyncing }} - Date: Wed, 22 Apr 2020 09:44:54 -0700 Subject: [PATCH 08/23] move cluster-states into a helper and update usage --- ui/app/models/cluster.js | 18 ++----- .../addon/components/replication-dashboard.js | 7 +-- ui/lib/core/addon/helpers/cluster-states.js | 54 +++++++++++++++++++ ui/lib/core/app/helpers/cluster-states.js | 1 + 4 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 ui/lib/core/addon/helpers/cluster-states.js create mode 100644 ui/lib/core/app/helpers/cluster-states.js diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index 7a64175d061a..234a2534ca12 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -4,17 +4,7 @@ import { get, computed } from '@ember/object'; import DS from 'ember-data'; import { fragment } from 'ember-data-model-fragments/attributes'; const { hasMany, attr } = DS; - -const STATES = { - running: { glyph: 'check-circle-outline', isOk: true }, - 'stream-wals': { glyph: 'android-sync', display: 'Streaming', isOk: true }, - 'merkle-diff': { glyph: 'android-sync', display: 'Determining sync status', isOk: true }, - connecting: { glyph: 'android-sync', display: 'Streaming', isOk: true }, - 'merkle-sync': { glyph: 'android-sync', display: 'Syncing', isOk: true }, - idle: { glyph: 'cancel-circle-fill', isOk: false }, - 'transient-failure': { glyph: 'cancel-circle-fill', isOk: false }, - shutdown: { glyph: 'cancel-circle-fill', isOk: false }, -}; +import { clusterStates } from 'core/helpers/cluster-states'; export default DS.Model.extend({ version: service(), @@ -66,7 +56,7 @@ export default DS.Model.extend({ } const defaultDisp = 'Synced'; - return STATES[state].display || defaultDisp; + return clusterStates([state]).display || defaultDisp; }, drStateDisplay: computed('dr.state', function() { @@ -79,7 +69,7 @@ export default DS.Model.extend({ stateGlyph(state) { const glyph = 'check-circle-outline'; - return STATES[state].glyph || glyph; + return clusterStates([state]).glyph || glyph; }, drStateGlyph: computed('dr.state', function() { @@ -91,7 +81,7 @@ export default DS.Model.extend({ }), hasOkState(state) { - return STATES[state].isOk || false; + return clusterStates([state]).isOk || false; }, drHasOkState: computed('dr.state', function() { diff --git a/ui/lib/core/addon/components/replication-dashboard.js b/ui/lib/core/addon/components/replication-dashboard.js index 2ab5c687baca..aae230a52506 100644 --- a/ui/lib/core/addon/components/replication-dashboard.js +++ b/ui/lib/core/addon/components/replication-dashboard.js @@ -1,9 +1,8 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; +import { clusterStates } from 'core/helpers/cluster-states'; import layout from '../templates/components/replication-dashboard'; -const MERKLE_STATES = { sync: 'merkle-sync', diff: 'merkle-diff' }; - export default Component.extend({ layout, data: null, @@ -15,8 +14,6 @@ export default Component.extend({ return dr; }), isSyncing: computed('data', function() { - if (this.dr.state === MERKLE_STATES.sync || this.dr.state === MERKLE_STATES.diff) { - return true; - } + return clusterStates([this.dr.state]).isSyncing; }), }); diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js new file mode 100644 index 000000000000..8dcfb1b2e9cf --- /dev/null +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -0,0 +1,54 @@ +import { helper as buildHelper } from '@ember/component/helper'; + +export const CLUSTER_STATES = { + running: { + glyph: 'check-circle-outline', + isOk: true, + isSyncing: false, + }, + 'stream-wals': { + glyph: 'android-sync', + display: 'Streaming', + isOk: true, + isSyncing: false, + }, + 'merkle-diff': { + glyph: 'android-sync', + display: 'Determining sync status', + isOk: true, + isSyncing: true, + }, + connecting: { + glyph: 'android-sync', + display: 'Streaming', + isOk: true, + isSyncing: true, + }, + 'merkle-sync': { + glyph: 'android-sync', + display: 'Syncing', + isOk: true, + isSyncing: true, + }, + idle: { + glyph: 'cancel-circle-fill', + isOk: false, + isSyncing: false, + }, + 'transient-failure': { + glyph: 'cancel-circle-fill', + isOk: false, + isSyncing: false, + }, + shutdown: { + glyph: 'cancel-circle-fill', + isOk: false, + isSyncing: false, + }, +}; + +export function clusterStates([state]) { + return CLUSTER_STATES[state]; +} + +export default buildHelper(clusterStates); diff --git a/ui/lib/core/app/helpers/cluster-states.js b/ui/lib/core/app/helpers/cluster-states.js new file mode 100644 index 000000000000..97887155aee5 --- /dev/null +++ b/ui/lib/core/app/helpers/cluster-states.js @@ -0,0 +1 @@ +export { default, clusterStates, CLUSTER_STATES } from 'core/helpers/cluster-states'; From 92fb5130130a0fcc2332a13e53667e12e5b6d6a0 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 22 Apr 2020 10:02:07 -0700 Subject: [PATCH 09/23] use circle success icon for stream-wals because that is the ideal state --- ui/lib/core/addon/helpers/cluster-states.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js index 8dcfb1b2e9cf..b9b3dc692300 100644 --- a/ui/lib/core/addon/helpers/cluster-states.js +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -1,5 +1,8 @@ import { helper as buildHelper } from '@ember/component/helper'; +// A hash of cluster states to ensure that the status menu and replication dashboards +// display states and glyphs consistently + export const CLUSTER_STATES = { running: { glyph: 'check-circle-outline', @@ -7,7 +10,7 @@ export const CLUSTER_STATES = { isSyncing: false, }, 'stream-wals': { - glyph: 'android-sync', + glyph: 'check-circle-outline', display: 'Streaming', isOk: true, isSyncing: false, From b25ce17704185a3ec2b0584639efe0922f5f9492 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 22 Apr 2020 10:10:38 -0700 Subject: [PATCH 10/23] more refactoring of cluster state display --- ui/app/models/cluster.js | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index 234a2534ca12..076fed4c800a 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -50,46 +50,36 @@ export default DS.Model.extend({ anyReplicationEnabled: or('{dr,performance}.replicationEnabled'), - stateDisplay(state) { + drStateDisplay: computed('dr.state', function() { if (!state) { return null; } - const defaultDisp = 'Synced'; - - return clusterStates([state]).display || defaultDisp; - }, - drStateDisplay: computed('dr.state', function() { - return this.stateDisplay(this.get('dr.state')); + return clusterStates([this.get('dr.state')]).display || 'Synced'; }), performanceStateDisplay: computed('performance.state', function() { - return this.stateDisplay(this.get('performance.state')); - }), + if (!state) { + return null; + } - stateGlyph(state) { - const glyph = 'check-circle-outline'; - return clusterStates([state]).glyph || glyph; - }, + return clusterStates([this.get('performance.state')]).display || 'Synced'; + }), drStateGlyph: computed('dr.state', function() { - return this.stateGlyph(this.get('dr.state')); + return clusterStates([this.get('dr.state')]).glyph || 'check-circle-outline'; }), performanceStateGlyph: computed('performance.state', function() { - return this.stateGlyph(this.get('performance.state')); + return clusterStates([this.get('performance.state')]).glyph || 'check-circle-outline'; }), - hasOkState(state) { - return clusterStates([state]).isOk || false; - }, - drHasOkState: computed('dr.state', function() { - return this.hasOkState(this.get('dr.state')); + return clusterStates([this.get('dr.state')]).isOk || false; }), performanceHasOkState: computed('performance.state', function() { - return this.hasOkState(this.get('performance.state')); + return clusterStates([this.get('performance.state')]).isOk || false; }), dr: fragment('replication-attributes'), From 927c5083fe8ee644d01ed0bd39a08edbe7026964 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 22 Apr 2020 15:38:06 -0700 Subject: [PATCH 11/23] use new cluster-states helper --- ui/app/models/cluster.js | 40 +++++-------------- .../components/replication-mode-summary.js | 3 ++ .../components/replication-mode-summary.hbs | 12 +++--- .../components/replication-primary-card.js | 13 ++++-- .../components/replication-summary.hbs | 16 ++++---- 5 files changed, 35 insertions(+), 49 deletions(-) diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index 076fed4c800a..9d9c946a6d81 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -50,37 +50,17 @@ export default DS.Model.extend({ anyReplicationEnabled: or('{dr,performance}.replicationEnabled'), - drStateDisplay: computed('dr.state', function() { - if (!state) { - return null; + modeState: computed( + 'dr.mode', + 'performance.mode', + 'replicationMode', + 'dr.state', + 'performance.state', + function() { + const mode = this.replicationMode; + return this.get(`${mode}.state`); } - - return clusterStates([this.get('dr.state')]).display || 'Synced'; - }), - - performanceStateDisplay: computed('performance.state', function() { - if (!state) { - return null; - } - - return clusterStates([this.get('performance.state')]).display || 'Synced'; - }), - - drStateGlyph: computed('dr.state', function() { - return clusterStates([this.get('dr.state')]).glyph || 'check-circle-outline'; - }), - - performanceStateGlyph: computed('performance.state', function() { - return clusterStates([this.get('performance.state')]).glyph || 'check-circle-outline'; - }), - - drHasOkState: computed('dr.state', function() { - return clusterStates([this.get('dr.state')]).isOk || false; - }), - - performanceHasOkState: computed('performance.state', function() { - return clusterStates([this.get('performance.state')]).isOk || false; - }), + ), dr: fragment('replication-attributes'), performance: fragment('replication-attributes'), diff --git a/ui/lib/core/addon/components/replication-mode-summary.js b/ui/lib/core/addon/components/replication-mode-summary.js index 7e19a887eeea..44ecb45fc924 100644 --- a/ui/lib/core/addon/components/replication-mode-summary.js +++ b/ui/lib/core/addon/components/replication-mode-summary.js @@ -48,4 +48,7 @@ export default Component.extend({ clusterIdDisplay: replicationAttr('clusterIdDisplay'), mode: null, cluster: null, + modeState: computed('cluster', function() { + return this.cluster.modeState; + }), }); diff --git a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs index 6b44951f29d4..2e267fbd2493 100644 --- a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs +++ b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs @@ -31,11 +31,11 @@
{{#if replicationEnabled}} - {{#if (get cluster (concat mode 'StateGlyph'))}} - + {{#if (cluster-states modeState)}} + {{else if syncProgress}} @@ -104,10 +104,8 @@ {{#link-to "vault.cluster.replication.mode.index" cluster.name mode class="button is-primary"}} Enable {{/link-to}} - {{else if (eq mode 'dr')}} - {{cluster.drStateDisplay}} - {{else if (eq mode 'performance')}} - {{cluster.performanceStateDisplay}} + {{else}} + {{get (cluster-states modeState) "display"}} {{/if}}
{{/if}} diff --git a/ui/lib/replication/addon/components/replication-primary-card.js b/ui/lib/replication/addon/components/replication-primary-card.js index 0cdc96158ab9..0b782341509e 100644 --- a/ui/lib/replication/addon/components/replication-primary-card.js +++ b/ui/lib/replication/addon/components/replication-primary-card.js @@ -1,5 +1,6 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; +import { clusterStates } from 'core/helpers/cluster-states'; /** * @module ReplicationPrimaryCard @@ -16,7 +17,6 @@ import { computed } from '@ember/object'; * @param {string} [title=null] - The title to be displayed on the top left corner of the card. * @param {string} [description=null] - Helper text to describe the metric on the card. * @param {string} [glyph=null] - The glyph to display beside the metric. - * @param {boolean} [hasOkState=true] - Whether or not the cluster is in an okay state. This comes from the cluster model. * @param {string} metric=null - The main metric to highlight on the card. */ @@ -26,9 +26,14 @@ export default Component.extend({ description: null, metric: null, glyph: null, - hasOkState: true, - hasError: computed('hasOkState', 'title', 'metric', function() { - return this.title === 'State' && !this.hasOkState; + hasError: computed('title', 'metric', function() { + const { title, metric } = this; + + // only show errors on the state card + if (title === 'State') { + return !clusterStates([metric]).isOk; + } + return false; }), errorMessage: computed('hasError', function() { // TODO figure out if we need another error message diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index f4e64ca06851..bdd906de7f04 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -348,16 +348,16 @@ - + - + @metric={{replicationAttrs.lastWAL}} /> +
- +
{{/if}} From 448b1f060e019c7f725c196b19c7d1c511f1b529 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 22 Apr 2020 15:49:57 -0700 Subject: [PATCH 12/23] whitespace --- .../components/replication-summary.hbs | 97 ++++++++----------- 1 file changed, 39 insertions(+), 58 deletions(-) diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index bdd906de7f04..194c18d78b4c 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -17,8 +17,7 @@ -
+ }}>
{{message-error errors=errors}} {{#if initialReplicationMode}} {{#if (eq initialReplicationMode 'dr')}}

-

- DR is designed to protect against catastrophic failure of entire clusters. Secondaries do not forward service requests (until they are elected and become a new primary). + DR is designed to protect against catastrophic failure of entire clusters. Secondaries do not forward + service requests (until they are elected and become a new primary).

{{else if (eq initialReplicationMode 'performance')}}

-

{{#if (not (has-feature "Performance Replication"))}} @@ -63,7 +54,8 @@

{{else}}

- Performance replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled. + Performance replication scales workloads horizontally across clusters to make requests faster. Local + secondaries handle read requests but forward writes to the primary to be handled.

{{/if}} {{/if}} @@ -72,22 +64,20 @@ - In both Performance and Disaster Recovery (DR) Replication, secondaries share the underlying configuration, policies, and supporting secrets as their primary cluster. + In both Performance and Disaster Recovery (DR) Replication, secondaries share the underlying configuration, + policies, and supporting secrets as their primary cluster.

@@ -250,11 +237,13 @@ {{input value=ca_path id="ca_path" name="ca_file" class="input"}}

- Specifies the path to a CA root directory containing PEM-format files that the secondary can use when unwrapping the token from the primary. + Specifies the path to a CA root directory containing PEM-format files that the secondary can use when + unwrapping the token from the primary.

- Note: If both CA file and CA path are not given, they default to system CA roots. + Note: If both CA file and CA path are not given, they default to system CA + roots.

{{/if}} {{else}} @@ -282,11 +271,7 @@

-

{{#if cluster.dr.replicationEnabled}} @@ -311,11 +296,7 @@

-

{{#if cluster.dr.replicationEnabled}} From 502064c9bce2a1d2c5fcd09aa27b1fd7c6a2ce75 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 22 Apr 2020 17:14:08 -0700 Subject: [PATCH 13/23] use clusterStates helper in replication secondary card --- .../components/replication-secondary-card.js | 31 ++++------ ui/lib/core/addon/helpers/cluster-states.js | 2 +- .../components/replication-secondary-card.hbs | 60 ++++++++----------- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/ui/lib/core/addon/components/replication-secondary-card.js b/ui/lib/core/addon/components/replication-secondary-card.js index 97885037fc29..472db9ee0254 100644 --- a/ui/lib/core/addon/components/replication-secondary-card.js +++ b/ui/lib/core/addon/components/replication-secondary-card.js @@ -7,13 +7,7 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from '../templates/components/replication-secondary-card'; - -const STATES = { - streamWals: 'stream-wals', - idle: 'idle', - transientFailure: 'transient-failure', - shutdown: 'shutdown', -}; +import { clusterStates } from 'core/helpers/cluster-states'; export default Component.extend({ layout, @@ -41,19 +35,20 @@ export default Component.extend({ return Math.abs(this.get('lastWAL') - this.get('lastRemoteWAL')); }), inSyncState: computed('state', function() { - if (this.state === STATES.streamWals) { - return true; - } + // if our definition of what is considered 'synced' changes, + // we should use the clusterStates helper instead + return this.state === 'stream-wals'; }), + hasErrorClass: computed('data', 'title', 'state', 'connection', function() { - if (this.title === 'States') { - if ( - this.state === STATES.idle || - this.connection === STATES.transientFailure || - this.connection === STATES.shutdown - ) { - return true; - } + const { title, state, connection } = this; + + // only show errors on the state card + if (title === 'States') { + const isOk = clusterStates([state]).isOk; + const primaryIsOk = clusterStates([connection]).isOk; + return !(isOk && primaryIsOk); } + return false; }), }); diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js index b9b3dc692300..f9bf0a26ce00 100644 --- a/ui/lib/core/addon/helpers/cluster-states.js +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -38,7 +38,7 @@ export const CLUSTER_STATES = { isOk: false, isSyncing: false, }, - 'transient-failure': { + transient_failure: { glyph: 'cancel-circle-fill', isOk: false, isSyncing: false, diff --git a/ui/lib/core/addon/templates/components/replication-secondary-card.hbs b/ui/lib/core/addon/templates/components/replication-secondary-card.hbs index a9337b822c59..97ffd54ccac6 100644 --- a/ui/lib/core/addon/templates/components/replication-secondary-card.hbs +++ b/ui/lib/core/addon/templates/components/replication-secondary-card.hbs @@ -3,49 +3,41 @@ {{#if (eq title "States")}}

{{title}}

- {{#if (eq state "idle")}} - state - - {{else}} + {{#if (get (cluster-states state) "isOk")}} state

How this cluster is communicating with others at this moment.

+ {{else}} + state + {{/if}}
- {{#if (or (eq connection "transient-failure") (eq connection "shutdown"))}} - connection_state - - {{else}} + {{#if (get (cluster-states connection) "isOk")}} connection_state -

The health of the connection between this cluster and others.

+

+ The health of the connection between this cluster and others. +

+ {{else}} + connection_state + {{/if}}
{{!-- ARG TODO connection state is likely wrong here, waiting for reply from RFC --}} -

{{state}} - {{#if inSyncState }} - - - - - -
- Everything is in sync -
-
-
- {{/if}} -

-

{{connection}}

+

{{state}} + {{#if inSyncState }} + + + + + +
+ Everything is in sync +
+
+
+ {{/if}} +

+

{{connection}}

{{else}}

{{title}} From def71a14bb8f2ef2e2658cf175a15cdb70d66852 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Thu, 23 Apr 2020 17:13:39 -0700 Subject: [PATCH 14/23] remove extra import --- ui/app/models/cluster.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index 9d9c946a6d81..193c056994a0 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -4,7 +4,6 @@ import { get, computed } from '@ember/object'; import DS from 'ember-data'; import { fragment } from 'ember-data-model-fragments/attributes'; const { hasMany, attr } = DS; -import { clusterStates } from 'core/helpers/cluster-states'; export default DS.Model.extend({ version: service(), From f672ae3f3681fa4509510344d3097ae946ef776b Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Thu, 23 Apr 2020 17:15:11 -0700 Subject: [PATCH 15/23] add default values for when state isn't recognized --- .../addon/components/replication-secondary-card.js | 4 ++-- ui/lib/core/addon/helpers/cluster-states.js | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ui/lib/core/addon/components/replication-secondary-card.js b/ui/lib/core/addon/components/replication-secondary-card.js index 472db9ee0254..84c1056ee51a 100644 --- a/ui/lib/core/addon/components/replication-secondary-card.js +++ b/ui/lib/core/addon/components/replication-secondary-card.js @@ -45,9 +45,9 @@ export default Component.extend({ // only show errors on the state card if (title === 'States') { - const isOk = clusterStates([state]).isOk; + const currentClusterisOk = clusterStates([state]).isOk; const primaryIsOk = clusterStates([connection]).isOk; - return !(isOk && primaryIsOk); + return !(currentClusterisOk && primaryIsOk); } return false; }), diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js index f9bf0a26ce00..e00b7a241af9 100644 --- a/ui/lib/core/addon/helpers/cluster-states.js +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -2,6 +2,7 @@ import { helper as buildHelper } from '@ember/component/helper'; // A hash of cluster states to ensure that the status menu and replication dashboards // display states and glyphs consistently +// this includes states for the primary vault cluster and the connection_state export const CLUSTER_STATES = { running: { @@ -9,6 +10,11 @@ export const CLUSTER_STATES = { isOk: true, isSyncing: false, }, + ready: { + glyph: 'check-circle-outline', + isOk: true, + isSyncing: false, + }, 'stream-wals': { glyph: 'check-circle-outline', display: 'Streaming', @@ -51,7 +57,13 @@ export const CLUSTER_STATES = { }; export function clusterStates([state]) { - return CLUSTER_STATES[state]; + const defaultDisplay = { + glyph: 'check-circle-outline', + display: '', + isOk: true, + isSyncing: false, + }; + return CLUSTER_STATES[state] || defaultDisplay; } export default buildHelper(clusterStates); From 246fd51cd5fe551bf51f3889efc4d276a2db5a42 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Thu, 23 Apr 2020 18:06:11 -0700 Subject: [PATCH 16/23] make sure that state exists before getting state details from clusterStates helper --- ui/lib/core/addon/components/replication-dashboard.js | 5 +++-- .../replication/addon/components/replication-primary-card.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/lib/core/addon/components/replication-dashboard.js b/ui/lib/core/addon/components/replication-dashboard.js index aae230a52506..904a80c05a15 100644 --- a/ui/lib/core/addon/components/replication-dashboard.js +++ b/ui/lib/core/addon/components/replication-dashboard.js @@ -13,7 +13,8 @@ export default Component.extend({ } return dr; }), - isSyncing: computed('data', function() { - return clusterStates([this.dr.state]).isSyncing; + isSyncing: computed('dr', function() { + const { state } = this.dr; + return state && clusterStates([state]).isSyncing; }), }); diff --git a/ui/lib/replication/addon/components/replication-primary-card.js b/ui/lib/replication/addon/components/replication-primary-card.js index 0b782341509e..0067c00cb7f3 100644 --- a/ui/lib/replication/addon/components/replication-primary-card.js +++ b/ui/lib/replication/addon/components/replication-primary-card.js @@ -29,9 +29,9 @@ export default Component.extend({ hasError: computed('title', 'metric', function() { const { title, metric } = this; - // only show errors on the state card + // only show errors on the state card if state is not ok if (title === 'State') { - return !clusterStates([metric]).isOk; + return metric && !clusterStates([metric]).isOk; } return false; }), From acb3d06fc500852cca7d64a3cd34438c8c930f37 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 24 Apr 2020 09:35:25 -0700 Subject: [PATCH 17/23] be more strict when state cannot be found --- ui/lib/core/addon/helpers/cluster-states.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js index e00b7a241af9..d135be3baf4b 100644 --- a/ui/lib/core/addon/helpers/cluster-states.js +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -58,10 +58,10 @@ export const CLUSTER_STATES = { export function clusterStates([state]) { const defaultDisplay = { - glyph: 'check-circle-outline', + glyph: '', display: '', - isOk: true, - isSyncing: false, + isOk: null, + isSyncing: null, }; return CLUSTER_STATES[state] || defaultDisplay; } From d8ddb9584218962cb69645a97330bf025ce3e7e4 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 24 Apr 2020 10:12:46 -0700 Subject: [PATCH 18/23] use brace expansion to fix linting error --- ui/app/models/cluster.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/ui/app/models/cluster.js b/ui/app/models/cluster.js index 193c056994a0..272f40a39454 100644 --- a/ui/app/models/cluster.js +++ b/ui/app/models/cluster.js @@ -49,17 +49,10 @@ export default DS.Model.extend({ anyReplicationEnabled: or('{dr,performance}.replicationEnabled'), - modeState: computed( - 'dr.mode', - 'performance.mode', - 'replicationMode', - 'dr.state', - 'performance.state', - function() { - const mode = this.replicationMode; - return this.get(`${mode}.state`); - } - ), + modeState: computed('dr.{mode,state}', 'performance.{mode,state}', 'replicationMode', function() { + const mode = this.replicationMode; + return this.get(`${mode}.state`); + }), dr: fragment('replication-attributes'), performance: fragment('replication-attributes'), From d5b07f30a6dc1b4dffe1808fa71ec78ef8248e7a Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 24 Apr 2020 10:40:49 -0700 Subject: [PATCH 19/23] add tests for error states --- .../components/replication-primary-card.hbs | 12 ++-- .../components/replication-summary.hbs | 3 +- .../replication-primary-card-test.js | 55 +++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 ui/tests/integration/components/replication-primary-card-test.js diff --git a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs index b62e7ba38b0e..f9c8974da8e3 100644 --- a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs +++ b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs @@ -1,16 +1,16 @@

{{title}}

- {{#if hasError}} - - {{/if}} - + {{#if hasError}} + + {{/if}} + {{description}} -

+

{{metric}} {{#if (and glyph (not hasError))}} - + {{/if}}

diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index 194c18d78b4c..73638ddf16d9 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -331,7 +331,8 @@ @description='Updated every ten seconds.' @glyph={{get (cluster-states replicationAttrs.state) "glyph"}} @metric={{replicationAttrs.state}} /> - `); + + assert.dom('[data-test-hasError]').doesNotExist('shows no error for non-State cards'); + + assert.dom('.last-wal').includesText(title); + assert.dom('[data-test-description]').includesText(description); + assert.dom('[data-test-metric]').includesText(metric); + }); + + Object.keys(CLUSTER_STATES).forEach(state => { + test(`it renders a card when cluster has the ${state} state`, async function(assert) { + this.set('glyph', CLUSTER_STATES[state].glyph); + this.set('state', state); + + await render(hbs` + `); + + if (CLUSTER_STATES[state].isOk) { + assert.dom('[data-test-hasError]').doesNotExist(); + assert.dom('[data-test-icon]').exists('shows an icon if state is ok'); + } else { + assert.dom('[data-test-hasError]').exists('shows an error if the cluster state is not ok'); + assert.dom('[data-test-icon]').doesNotExist('does not show an icon if state is not ok'); + } + }); + }); +}); From 83e300365581c95e1b05e227f54d97e9d0af9b3c Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 24 Apr 2020 15:41:59 -0700 Subject: [PATCH 20/23] fix text wrapping issue on secondary cards; make titles match mocks --- .../components/replication-dashboard.scss | 13 ++--- .../components/replication-secondary-card.hbs | 58 +++++++++---------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/ui/app/styles/components/replication-dashboard.scss b/ui/app/styles/components/replication-dashboard.scss index 35751ca03482..fcb03fdf51b2 100644 --- a/ui/app/styles/components/replication-dashboard.scss +++ b/ui/app/styles/components/replication-dashboard.scss @@ -5,17 +5,16 @@ &:hover { box-shadow: 0 0 0 1px rgba($grey-dark, 0.3); } - - .title-number { - font-size: $size-3; - align-self: end; - } } .helper-text { font-weight: $font-weight-normal; } + .title.is-6 { + margin-bottom: $spacing-xs; + } + .selectable-card-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); @@ -24,9 +23,10 @@ .card-container { display: grid; + grid-gap: 2rem; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr 0.8fr; - padding: $spacing-l 0 18px $spacing-l; + padding: $spacing-l; line-height: 1.5; height: 220px; @@ -38,7 +38,6 @@ .grid-item-title { grid-column: 1 / span 2; - display: flex; } .grid-item-left { diff --git a/ui/lib/core/addon/templates/components/replication-secondary-card.hbs b/ui/lib/core/addon/templates/components/replication-secondary-card.hbs index 97ffd54ccac6..48f45cdab8fa 100644 --- a/ui/lib/core/addon/templates/components/replication-secondary-card.hbs +++ b/ui/lib/core/addon/templates/components/replication-secondary-card.hbs @@ -1,29 +1,35 @@
{{!-- Check if State or WAL Card --}} {{#if (eq title "States")}} -

{{title}}

+

{{title}}

{{#if (get (cluster-states state) "isOk")}} - state +
state

How this cluster is communicating with others at this moment.

{{else}} - state - +
state
+ {{/if}}
- {{#if (get (cluster-states connection) "isOk")}} - connection_state -

- The health of the connection between this cluster and others. -

+ {{#if (eq connection "transient_failure")}} +
connection_state
+ + {{else if (eq connection "shutdown")}} +
connection_state
+ {{else}} - connection_state - +
connection_state
+

The health of the connection between this cluster and others.

{{/if}}
- {{!-- ARG TODO connection state is likely wrong here, waiting for reply from RFC --}} -

{{state}} +

{{state}} {{#if inSyncState }} @@ -37,24 +43,18 @@ {{/if}}

-

{{connection}}

+

{{connection}}

{{else}} -

{{title}} +

{{title}} - +
- There may be a difference between last remote WAL and last WAL entry from primary. If it persists over time, investigate. - + There may be a difference between last remote WAL and last WAL entry from primary. If it persists over time, + investigate. + Learn more
@@ -62,16 +62,16 @@

- Delta +
Delta

The difference between the last remote WAL and the last WAL entry from the primary.

- last_wal +
last_wal

{{lastWAL}}

-

{{format-number delta}}

+ {{format-number delta}}
- last_remote_wal +
last_remote_wal

{{lastRemoteWAL}}

{{/if}} From 3e496daba45d78be11112b3b57b6d194355c2760 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 27 Apr 2020 13:08:05 -0700 Subject: [PATCH 21/23] use unknown if metric isn't foudn --- .../addon/templates/components/replication-primary-card.hbs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs index f9c8974da8e3..5eed1d8cd9b6 100644 --- a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs +++ b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs @@ -8,7 +8,11 @@ {{description}}

- {{metric}} + {{#if metric}} + {{metric}} + {{else}} + unknown + {{/if}} {{#if (and glyph (not hasError))}} {{/if}} From 98f752765a2173cee004d40bd0edbd49909957c4 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 27 Apr 2020 13:13:40 -0700 Subject: [PATCH 22/23] remove extra border on selectable card when there is an error --- ui/app/styles/components/selectable-card.scss | 4 ++++ .../addon/templates/components/replication-primary-card.hbs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/app/styles/components/selectable-card.scss b/ui/app/styles/components/selectable-card.scss index a2939ceccd94..eb4a0a3487af 100644 --- a/ui/app/styles/components/selectable-card.scss +++ b/ui/app/styles/components/selectable-card.scss @@ -73,6 +73,10 @@ border-radius: $radius; } +.selectable-card.has-border-danger { + box-shadow: none; +} + .change-metric-icon.is-decrease { transform: rotate(135deg); } diff --git a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs index 5eed1d8cd9b6..413df111d613 100644 --- a/ui/lib/replication/addon/templates/components/replication-primary-card.hbs +++ b/ui/lib/replication/addon/templates/components/replication-primary-card.hbs @@ -1,4 +1,4 @@ -
+

{{title}}

{{#if hasError}} From d20029a324948e2b9608b8471649c60e4a2cba7d Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Mon, 27 Apr 2020 15:47:22 -0700 Subject: [PATCH 23/23] use outline square in status menu for error --- ui/lib/core/addon/helpers/cluster-states.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/lib/core/addon/helpers/cluster-states.js b/ui/lib/core/addon/helpers/cluster-states.js index d135be3baf4b..3b0c52421aa0 100644 --- a/ui/lib/core/addon/helpers/cluster-states.js +++ b/ui/lib/core/addon/helpers/cluster-states.js @@ -40,17 +40,17 @@ export const CLUSTER_STATES = { isSyncing: true, }, idle: { - glyph: 'cancel-circle-fill', + glyph: 'cancel-square-outline', isOk: false, isSyncing: false, }, transient_failure: { - glyph: 'cancel-circle-fill', + glyph: 'cancel-circle-outline', isOk: false, isSyncing: false, }, shutdown: { - glyph: 'cancel-circle-fill', + glyph: 'cancel-circle-outline', isOk: false, isSyncing: false, },