mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 18:17:55 +00:00
UI: Show error when seal fails (#23921)
* Show error when seal fails * cleanup, add headers * add changelog * Fix test
This commit is contained in:
3
changelog/23921.txt
Normal file
3
changelog/23921.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
ui: show error from API when seal fails
|
||||||
|
```
|
||||||
34
ui/app/components/seal-action.hbs
Normal file
34
ui/app/components/seal-action.hbs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{{!
|
||||||
|
Copyright (c) HashiCorp, Inc.
|
||||||
|
SPDX-License-Identifier: BUSL-1.1
|
||||||
|
~}}
|
||||||
|
|
||||||
|
<div class="box is-sideless is-fullwidth is-marginless">
|
||||||
|
{{#if this.error}}
|
||||||
|
<Hds::Alert @type="inline" @color="critical" class="has-bottom-margin-m" data-test-seal-error as |A|>
|
||||||
|
<A.Title>Error</A.Title>
|
||||||
|
<A.Description>
|
||||||
|
{{this.error}}
|
||||||
|
</A.Description>
|
||||||
|
</Hds::Alert>
|
||||||
|
{{/if}}
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field is-grouped box is-fullwidth is-bottomless">
|
||||||
|
<ConfirmAction
|
||||||
|
@buttonClasses="button is-primary"
|
||||||
|
@confirmTitle="Seal this cluster?"
|
||||||
|
@confirmMessage="You will not be able to read or write any data until the cluster is unsealed again."
|
||||||
|
@confirmButtonText="Seal"
|
||||||
|
@horizontalPosition="auto-left"
|
||||||
|
@onConfirmAction={{this.handleSeal}}
|
||||||
|
data-test-seal
|
||||||
|
>
|
||||||
|
Seal
|
||||||
|
</ConfirmAction>
|
||||||
|
</div>
|
||||||
22
ui/app/components/seal-action.js
Normal file
22
ui/app/components/seal-action.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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';
|
||||||
|
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.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,26 +12,7 @@
|
|||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
{{#if this.model.seal.canUpdate}}
|
{{#if this.model.seal.canUpdate}}
|
||||||
<div class="box is-sideless is-fullwidth is-marginless">
|
<SealAction @onSeal={{action "seal"}} />
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="field is-grouped box is-fullwidth is-bottomless">
|
|
||||||
<ConfirmAction
|
|
||||||
@buttonClasses="button is-primary"
|
|
||||||
@confirmTitle="Seal this cluster?"
|
|
||||||
@confirmMessage="You will not be able to read or write any data until the cluster is unsealed again."
|
|
||||||
@confirmButtonText="Seal"
|
|
||||||
@horizontalPosition="auto-left"
|
|
||||||
@onConfirmAction={{action "seal"}}
|
|
||||||
data-test-seal="true"
|
|
||||||
>
|
|
||||||
Seal
|
|
||||||
</ConfirmAction>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<EmptyState @title="This token does not have sufficient capabilities to seal this vault" />
|
<EmptyState @title="This token does not have sufficient capabilities to seal this vault" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
45
ui/tests/integration/components/seal-action-test.js
Normal file
45
ui/tests/integration/components/seal-action-test.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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';
|
||||||
|
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`<SealAction @onSeal={{action this.handleSeal}} />`);
|
||||||
|
|
||||||
|
// 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`<SealAction @onSeal={{action this.handleSeal}} />`);
|
||||||
|
|
||||||
|
// attempt seal
|
||||||
|
await click('[data-test-seal] button');
|
||||||
|
await click('[data-test-confirm-button]');
|
||||||
|
|
||||||
|
assert.ok(this.sealError.calledOnce, 'called onSeal action');
|
||||||
|
assert.dom('[data-test-seal-error]').includesText(SEAL_WHEN_STANDBY_MSG, 'Shows error returned from API');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user