From 0675ef7991523d849327d91caa8f880cefe57cd4 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 31 Oct 2023 13:44:51 -0500 Subject: [PATCH 1/4] Show error when seal fails --- ui/app/components/seal-action.hbs | 29 ++++++++++++++ ui/app/components/seal-action.js | 17 ++++++++ .../templates/vault/cluster/settings/seal.hbs | 21 +--------- .../components/seal-action-test.js | 40 +++++++++++++++++++ 4 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 ui/app/components/seal-action.hbs create mode 100644 ui/app/components/seal-action.js create mode 100644 ui/tests/integration/components/seal-action-test.js diff --git a/ui/app/components/seal-action.hbs b/ui/app/components/seal-action.hbs new file mode 100644 index 000000000000..7be49d8e6bc4 --- /dev/null +++ b/ui/app/components/seal-action.hbs @@ -0,0 +1,29 @@ +
+ {{#if this.error}} + + Error + + {{this.error}} + + + {{/if}} +

+ Sealing a vault tells the Vault server to stop responding to any access operations until it is unsealed again. A sealed + vault throws away its root key to unlock the data, so it physically is blocked from responding to operations again until + the Vault is unsealed again with the "unseal" command or via the API. +

+
+ +
+ + Seal + +
\ No newline at end of file diff --git a/ui/app/components/seal-action.js b/ui/app/components/seal-action.js new file mode 100644 index 000000000000..41b37976eb1a --- /dev/null +++ b/ui/app/components/seal-action.js @@ -0,0 +1,17 @@ +import { action } from '@ember/object'; +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import errorMessage from 'vault/utils/error-message'; + +export default class SealActionComponent extends Component { + @tracked error; + + @action + async handleSeal() { + try { + await this.args.onSeal(); + } catch (e) { + this.error = errorMessage(e, 'Seal attempt failed. Check Vault logs for details.'); + } + } +} diff --git a/ui/app/templates/vault/cluster/settings/seal.hbs b/ui/app/templates/vault/cluster/settings/seal.hbs index 972f9a72cf85..0b6d738e3f08 100644 --- a/ui/app/templates/vault/cluster/settings/seal.hbs +++ b/ui/app/templates/vault/cluster/settings/seal.hbs @@ -12,26 +12,7 @@ {{#if this.model.seal.canUpdate}} -
-

- Sealing a vault tells the Vault server to stop responding to any access operations until it is unsealed again. A sealed - vault throws away its root key to unlock the data, so it physically is blocked from responding to operations again - until the Vault is unsealed again with the "unseal" command or via the API. -

-
-
- - Seal - -
+ {{else}} {{/if}} \ No newline at end of file diff --git a/ui/tests/integration/components/seal-action-test.js b/ui/tests/integration/components/seal-action-test.js new file mode 100644 index 000000000000..6e8808bd166d --- /dev/null +++ b/ui/tests/integration/components/seal-action-test.js @@ -0,0 +1,40 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'vault/tests/helpers'; +import { click, render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import sinon from 'sinon'; + +const SEAL_WHEN_STANDBY_MSG = 'vault cannot seal when in standby mode; please restart instead'; + +module('Integration | Component | seal-action', function (hooks) { + setupRenderingTest(hooks); + + hooks.beforeEach(function () { + this.sealSuccess = sinon.spy(() => new Promise((resolve) => resolve({}))); + this.sealError = sinon.stub().throws({ message: SEAL_WHEN_STANDBY_MSG }); + }); + + test('it handles success', async function (assert) { + this.set('handleSeal', this.sealSuccess); + await render(hbs``); + + // attempt seal + await click('[data-test-seal] button'); + await click('[data-test-confirm-button]'); + + assert.ok(this.sealSuccess.calledOnce, 'called onSeal action'); + assert.dom('[data-test-seal-error]').doesNotExist('Does not show error when successful'); + }); + + test('it handles error', async function (assert) { + this.set('handleSeal', this.sealError); + await render(hbs``); + + // attempt seal + await click('[data-test-seal] button'); + await click('[data-test-confirm-button]'); + + assert.ok(this.sealSuccess.calledOnce, 'called onSeal action'); + assert.dom('[data-test-seal-error]').includesText(SEAL_WHEN_STANDBY_MSG, 'Shows error returned from API'); + }); +}); From 0787c88e23116602320cbe4240c5e9e4632eae9a Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 31 Oct 2023 14:11:04 -0500 Subject: [PATCH 2/4] cleanup, add headers --- ui/app/components/seal-action.hbs | 7 ++++++- ui/app/components/seal-action.js | 5 +++++ ui/tests/integration/components/seal-action-test.js | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ui/app/components/seal-action.hbs b/ui/app/components/seal-action.hbs index 7be49d8e6bc4..ae966e676f6f 100644 --- a/ui/app/components/seal-action.hbs +++ b/ui/app/components/seal-action.hbs @@ -1,3 +1,8 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +~}} +
{{#if this.error}} @@ -22,7 +27,7 @@ @confirmButtonText="Seal" @horizontalPosition="auto-left" @onConfirmAction={{this.handleSeal}} - data-test-seal="true" + data-test-seal > Seal diff --git a/ui/app/components/seal-action.js b/ui/app/components/seal-action.js index 41b37976eb1a..4a2fd873ae47 100644 --- a/ui/app/components/seal-action.js +++ b/ui/app/components/seal-action.js @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + import { action } from '@ember/object'; import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; diff --git a/ui/tests/integration/components/seal-action-test.js b/ui/tests/integration/components/seal-action-test.js index 6e8808bd166d..4baa280afd53 100644 --- a/ui/tests/integration/components/seal-action-test.js +++ b/ui/tests/integration/components/seal-action-test.js @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + import { module, test } from 'qunit'; import { setupRenderingTest } from 'vault/tests/helpers'; import { click, render } from '@ember/test-helpers'; From 2f432e763e5f966f52b622b10fa6a89e6a5b1e40 Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 31 Oct 2023 14:12:01 -0500 Subject: [PATCH 3/4] add changelog --- changelog/23921.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/23921.txt diff --git a/changelog/23921.txt b/changelog/23921.txt new file mode 100644 index 000000000000..cd03142227d0 --- /dev/null +++ b/changelog/23921.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: show error from API when seal fails +``` From dbc48001c308400c8342eef49d434b7a9897a25e Mon Sep 17 00:00:00 2001 From: Chelsea Shaw Date: Tue, 31 Oct 2023 15:02:53 -0500 Subject: [PATCH 4/4] Fix test --- ui/tests/integration/components/seal-action-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/integration/components/seal-action-test.js b/ui/tests/integration/components/seal-action-test.js index 4baa280afd53..19bcf382048c 100644 --- a/ui/tests/integration/components/seal-action-test.js +++ b/ui/tests/integration/components/seal-action-test.js @@ -39,7 +39,7 @@ module('Integration | Component | seal-action', function (hooks) { await click('[data-test-seal] button'); await click('[data-test-confirm-button]'); - assert.ok(this.sealSuccess.calledOnce, 'called onSeal action'); + assert.ok(this.sealError.calledOnce, 'called onSeal action'); assert.dom('[data-test-seal-error]').includesText(SEAL_WHEN_STANDBY_MSG, 'Shows error returned from API'); }); });