From 94b64a37e34665c392042a138427c36034bd7998 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> Date: Wed, 10 Apr 2024 09:44:57 -0500 Subject: [PATCH] UI: Replication page navigation fix (#26325) * Add replication mirage handler * Add test with skipped failed assertion * Use component-calculated attrsForCurrentMode instead of cluster.replicationAttrs which wasn't triggering component updates * assert previously-skipped assertion * Add changelog --- changelog/26325.txt | 3 + .../addon/components/replication-summary.js | 6 +- .../components/replication-summary.hbs | 14 +-- ui/mirage/handlers/index.js | 2 + ui/mirage/handlers/replication.js | 107 ++++++++++++++++++ ui/tests/acceptance/replication-nav-test.js | 49 ++++++++ 6 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 changelog/26325.txt create mode 100644 ui/mirage/handlers/replication.js create mode 100644 ui/tests/acceptance/replication-nav-test.js diff --git a/changelog/26325.txt b/changelog/26325.txt new file mode 100644 index 0000000000..cbfc6c1f9c --- /dev/null +++ b/changelog/26325.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: fixed a bug where the replication pages did not update display when navigating between DR and performance +``` diff --git a/ui/lib/replication/addon/components/replication-summary.js b/ui/lib/replication/addon/components/replication-summary.js index 046d9f0f93..5a0bb0b4b9 100644 --- a/ui/lib/replication/addon/components/replication-summary.js +++ b/ui/lib/replication/addon/components/replication-summary.js @@ -4,7 +4,6 @@ */ import { service } from '@ember/service'; -import { alias } from '@ember/object/computed'; import { computed } from '@ember/object'; import Component from '@ember/component'; import decodeConfigFromJWT from 'replication/utils/decode-config-from-jwt'; @@ -27,6 +26,7 @@ export default Component.extend(ReplicationActions, DEFAULTS, { replicationMode: 'dr', mode: 'primary', version: service(), + rm: service('replication-mode'), didReceiveAttrs() { this._super(...arguments); const initialReplicationMode = this.initialReplicationMode; @@ -38,7 +38,9 @@ export default Component.extend(ReplicationActions, DEFAULTS, { initialReplicationMode: null, cluster: null, - replicationAttrs: alias('cluster.replicationAttrs'), + attrsForCurrentMode: computed('cluster', 'rm.mode', function () { + return this.cluster[this.rm.mode]; + }), tokenIncludesAPIAddr: computed('token', function () { const config = decodeConfigFromJWT(this.token); diff --git a/ui/lib/replication/addon/templates/components/replication-summary.hbs b/ui/lib/replication/addon/templates/components/replication-summary.hbs index 7fa582ffcb..963cef0199 100644 --- a/ui/lib/replication/addon/templates/components/replication-summary.hbs +++ b/ui/lib/replication/addon/templates/components/replication-summary.hbs @@ -334,7 +334,7 @@ {{/if}} {{/if}} {{else}} - {{#if (eq this.replicationAttrs.mode "initializing")}} + {{#if (eq this.attrsForCurrentMode.mode "initializing")}} The cluster is initializing replication. This may take some time. {{else}}

{{this.cluster.replicationModeStatus.cluster_id}}

@@ -343,28 +343,28 @@ - {{#if (eq this.replicationAttrs.mode "secondary")}} + {{#if (eq this.attrsForCurrentMode.mode "secondary")}} {{else}} - + {{/if}} diff --git a/ui/mirage/handlers/index.js b/ui/mirage/handlers/index.js index 1c1e0d3b06..f7c290efc1 100644 --- a/ui/mirage/handlers/index.js +++ b/ui/mirage/handlers/index.js @@ -19,6 +19,7 @@ import mfaLogin from './mfa-login'; import oidcConfig from './oidc-config'; import reducedDisclosure from './reduced-disclosure'; import sync from './sync'; +import replication from './replication'; export { base, @@ -35,4 +36,5 @@ export { reducedDisclosure, customMessages, sync, + replication, }; diff --git a/ui/mirage/handlers/replication.js b/ui/mirage/handlers/replication.js new file mode 100644 index 0000000000..4a1d2ff6c5 --- /dev/null +++ b/ui/mirage/handlers/replication.js @@ -0,0 +1,107 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +export default function (server) { + server.get('sys/replication/status', function () { + return { + data: { + dr: { + cluster_id: 'dr-cluster-id', + corrupted_merkle_tree: false, + known_secondaries: ['foobar'], + last_corruption_check_epoch: '-62135596800', + last_dr_wal: 98, + last_reindex_epoch: '0', + last_wal: 98, + merkle_root: 'ad721f32ed6789a1e5824841f358a517340a4585', + mode: 'primary', + primary_cluster_addr: 'dr-foobar', + secondaries: [ + { + api_address: 'http://127.0.0.1:8202', + cluster_address: 'https://127.0.0.1:8203', + connection_status: 'disconnected', + last_heartbeat: '2024-04-09T09:04:22-05:00', + node_id: 'foobar', + }, + ], + ssct_generation_counter: 0, + state: 'running', + }, + performance: { + cluster_id: 'perf-cluster-id', + corrupted_merkle_tree: false, + known_secondaries: [], + last_corruption_check_epoch: '-62135596800', + last_performance_wal: 98, + last_reindex_epoch: '0', + last_wal: 98, + merkle_root: '618c9136bb443aa584f5d6b90755d42888c9c54a', + mode: 'primary', + primary_cluster_addr: 'perf-foobar', + secondaries: [], + ssct_generation_counter: 0, + state: 'running', + }, + }, + }; + }); + + server.get('sys/replication/performance/status', function () { + return { + data: { + cluster_id: 'perf-cluster-id', + corrupted_merkle_tree: false, + known_secondaries: ['foobar'], + last_corruption_check_epoch: '-62135596800', + last_dr_wal: 98, + last_reindex_epoch: '0', + last_wal: 98, + merkle_root: 'ad721f32ed6789a1e5824841f358a517340a4585', + mode: 'primary', + primary_cluster_addr: 'perf-foobar', + secondaries: [ + { + api_address: 'http://127.0.0.1:8202', + cluster_address: 'https://127.0.0.1:8203', + connection_status: 'disconnected', + last_heartbeat: '2024-04-09T09:04:22-05:00', + node_id: 'foobar', + }, + ], + ssct_generation_counter: 0, + state: 'running', + }, + }; + }); + + server.get('sys/replication/dr/status', function () { + return { + data: { + cluster_id: 'dr-cluster-id', + corrupted_merkle_tree: false, + known_secondaries: ['foobar'], + last_corruption_check_epoch: '-62135596800', + last_dr_wal: 98, + last_reindex_epoch: '0', + last_wal: 98, + merkle_root: 'ad721f32ed6789a1e5824841f358a517340a4585', + mode: 'primary', + primary_cluster_addr: 'dr-foobar', + secondaries: [ + { + api_address: 'http://127.0.0.1:8202', + cluster_address: 'https://127.0.0.1:8203', + connection_status: 'disconnected', + last_heartbeat: '2024-04-09T09:04:22-05:00', + node_id: 'foobar', + }, + ], + ssct_generation_counter: 0, + state: 'running', + }, + }; + }); +} diff --git a/ui/tests/acceptance/replication-nav-test.js b/ui/tests/acceptance/replication-nav-test.js new file mode 100644 index 0000000000..fc5bcfa3cd --- /dev/null +++ b/ui/tests/acceptance/replication-nav-test.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupApplicationTest } from 'ember-qunit'; +import { setupMirage } from 'ember-cli-mirage/test-support'; +import authPage from 'vault/tests/pages/auth'; +import replicationHandlers from 'vault/mirage/handlers/replication'; +import { click } from '@ember/test-helpers'; + +const SELECTORS = { + navReplication: '[data-test-sidebar-nav-link="Replication"]', + navPerformance: '[data-test-sidebar-nav-link="Performance"]', + navDR: '[data-test-sidebar-nav-link="Disaster Recovery"]', + title: '[data-test-replication-title]', + primaryCluster: '[data-test-value-div="primary_cluster_addr"]', + replicationSet: '[data-test-row-value="Replication set"]', + knownSecondariesTitle: '.known-secondaries-card h3', +}; +module('Acceptance | Enterprise | replication navigation', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + hooks.beforeEach(function () { + replicationHandlers(this.server); + return authPage.login(); + }); + + test('navigate between replication types updates page', async function (assert) { + await click(SELECTORS.navReplication); + assert.dom(SELECTORS.title).hasText('Disaster Recovery & Performance primary'); + await click(SELECTORS.navPerformance); + + // Ensure data is expected for performance + assert.dom(SELECTORS.title).hasText('Performance primary'); + assert.dom(SELECTORS.primaryCluster).hasText('perf-foobar'); + assert.dom(SELECTORS.replicationSet).hasText('perf-cluster-id'); + assert.dom(SELECTORS.knownSecondariesTitle).hasText('0 Known secondaries'); + + // Nav to DR and see updated data + await click(SELECTORS.navDR); + assert.dom(SELECTORS.title).hasText('Disaster Recovery primary'); + assert.dom(SELECTORS.primaryCluster).hasText('dr-foobar'); + assert.dom(SELECTORS.replicationSet).hasText('dr-cluster-id'); + assert.dom(SELECTORS.knownSecondariesTitle).hasText('1 Known secondaries'); + }); +});