mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 09:42:25 +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>
|
||||
|
||||
{{#if this.model.seal.canUpdate}}
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<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>
|
||||
<SealAction @onSeal={{action "seal"}} />
|
||||
{{else}}
|
||||
<EmptyState @title="This token does not have sufficient capabilities to seal this vault" />
|
||||
{{/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