diff --git a/ui/app/components/secret-engine/list.hbs b/ui/app/components/secret-engine/list.hbs
index 0c5b77413e..8534ffa6f1 100644
--- a/ui/app/components/secret-engine/list.hbs
+++ b/ui/app/components/secret-engine/list.hbs
@@ -48,21 +48,7 @@
{{#if backend.icon}}
-
+
{{/if}}
@@ -99,13 +85,15 @@
@hasChevron={{false}}
data-test-popup-menu-trigger
/>
-
- View configuration
-
+ {{#if (not-eq (get (engines-display-data backend.type) "type") "generic")}}
+
+ View configuration
+
+ {{/if}}
{{#if (not-eq backend.type "cubbyhole")}}
{
return sortedBackends;
}
+ generateToolTipText = (backend: SecretsEngineResource) => {
+ const displayData = engineDisplayData(backend.type);
+
+ if (!displayData) {
+ return;
+ } else if (backend.isSupportedBackend) {
+ if (backend.type === 'kv') {
+ // If the backend is a KV engine, include the version in the tooltip.
+ return `${displayData.displayName} version ${backend.version}`;
+ } else {
+ return `${displayData.displayName}`;
+ }
+ } else if (displayData.type === 'generic') {
+ // If a mounted engine type doesn't match any known type, the type is returned as 'generic' and set this tooltip.
+ // Handles issue when a user externally mounts an engine that doesn't follow the expected naming conventions for what's in the binary, despite being a valid engine.
+ return 'This plugin is not supported by the UI. Please use the CLI to manage this engine.';
+ } else {
+ // If the engine type is recognized but not supported, we only show configuration view and set this tooltip.
+ return 'The UI only supports configuration views for these secret engines. The CLI must be used to manage other engine resources.';
+ }
+ };
+
// Filtering & searching
get secretEngineArrayByType() {
const arrayOfAllEngineTypes = this.sortedDisplayableBackends.map((modelObject) => modelObject.engineType);
diff --git a/ui/app/helpers/engines-display-data.ts b/ui/app/helpers/engines-display-data.ts
index 2de527e49a..a1548804e4 100644
--- a/ui/app/helpers/engines-display-data.ts
+++ b/ui/app/helpers/engines-display-data.ts
@@ -23,5 +23,15 @@ import { ALL_ENGINES } from 'vault/utils/all-engines-metadata';
*/
export default function engineDisplayData(methodType: string) {
const engine = ALL_ENGINES?.find((t) => t.type === methodType);
+ if (!engine && methodType) {
+ // Fallback to a generic engine if no match found but type is provided
+ return {
+ displayName: 'Generic plugin',
+ type: 'generic',
+ glyph: 'lock',
+ mountCategory: ['secret', 'auth'],
+ };
+ }
+
return engine;
}
diff --git a/ui/tests/acceptance/secret-engine-list-view-test.js b/ui/tests/acceptance/secret-engine-list-view-test.js
index 3a28b768fb..04e906a6cd 100644
--- a/ui/tests/acceptance/secret-engine-list-view-test.js
+++ b/ui/tests/acceptance/secret-engine-list-view-test.js
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: BUSL-1.1
*/
-import { click, fillIn, currentRouteName, visit, currentURL, triggerEvent } from '@ember/test-helpers';
+import { click, fillIn, currentRouteName, visit, currentURL } from '@ember/test-helpers';
import { selectChoose } from 'ember-power-select/test-support';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -86,57 +86,6 @@ module('Acceptance | secret-engine list view', function (hooks) {
await runCmd(deleteEngineCmd('aws'));
});
- test('hovering over the icon of an unsupported engine shows unsupported tooltip', async function (assert) {
- await visit('/vault/secrets');
- await page.enableEngine();
- await click(MOUNT_BACKEND_FORM.mountType('nomad'));
- await click(GENERAL.submitButton);
-
- await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-type'), 'nomad');
-
- await triggerEvent('.hds-tooltip-button', 'mouseenter');
- assert
- .dom('.hds-tooltip-container')
- .hasText(
- 'The UI only supports configuration views for these secret engines. The CLI must be used to manage other engine resources.',
- 'shows tooltip text for unsupported engine'
- );
- // cleanup
- await runCmd(deleteEngineCmd('nomad'));
- });
-
- test('hovering over the icon of a supported engine shows engine name', async function (assert) {
- await visit('/vault/secrets');
- await page.enableEngine();
- await click(MOUNT_BACKEND_FORM.mountType('ssh'));
- await click(GENERAL.submitButton);
- await click(GENERAL.breadcrumbLink('Secrets'));
-
- await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-type'), 'ssh');
- await triggerEvent('.hds-tooltip-button', 'mouseenter');
- assert.dom('.hds-tooltip-container').hasText('SSH', 'shows tooltip for SSH without version');
-
- // cleanup
- await runCmd(deleteEngineCmd('ssh'));
- });
-
- test('hovering over the icon of a kv engine shows engine name and version', async function (assert) {
- await visit('/vault/secrets');
-
- await page.enableEngine();
- await click(MOUNT_BACKEND_FORM.mountType('kv'));
- await fillIn(GENERAL.inputByAttr('path'), `kv-${this.uid}`);
- await click(GENERAL.submitButton);
- await click(GENERAL.breadcrumbLink('Secrets'));
-
- await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), `kv-${this.uid}`);
- await triggerEvent('.hds-tooltip-button', 'mouseenter');
- assert.dom('.hds-tooltip-container').hasText('KV version 2', 'shows tooltip for kv version 2');
-
- // cleanup
- await runCmd(deleteEngineCmd('kv'));
- });
-
test('enterprise: cannot view list without permissions inside a namespace', async function (assert) {
this.namespace = `ns-${this.uid}`;
const enginePath1 = `kv-t1-${this.uid}`;
diff --git a/ui/tests/integration/components/list-test.js b/ui/tests/integration/components/list-test.js
index b1debf2426..107ed8ab49 100644
--- a/ui/tests/integration/components/list-test.js
+++ b/ui/tests/integration/components/list-test.js
@@ -5,14 +5,14 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'vault/tests/helpers';
-import { render, click, find, findAll } from '@ember/test-helpers';
+import { render, click, find, findAll, triggerEvent } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { v4 as uuidv4 } from 'uuid';
import sinon from 'sinon';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { overrideResponse } from 'vault/tests/helpers/stubs';
import { clickTrigger } from 'ember-power-select/test-support/helpers';
-
+import { selectChoose } from 'ember-power-select/test-support';
import { createSecretsEngine } from 'vault/tests/helpers/secret-engine/secret-engine-helpers';
import { SECRET_ENGINE_SELECTORS as SES } from 'vault/tests/helpers/secret-engine/secret-engine-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
@@ -33,18 +33,19 @@ module('Integration | Component | secret-engine/list', function (hooks) {
this.flashSuccessSpy = sinon.spy(this.flashMessages, 'success');
this.flashDangerSpy = sinon.spy(this.flashMessages, 'danger');
this.uid = uuidv4();
- // generate a model of cubbyhole, kv2, and nomad
+ // generate a model of cubbyhole, kv, and nomad
this.secretEngineModels = [
createSecretsEngine(undefined, 'cubbyhole', 'cubbyhole-test'),
- createSecretsEngine(undefined, 'kv', 'kv2-test'),
+ createSecretsEngine(undefined, 'kv', 'kv-test'),
createSecretsEngine(undefined, 'aws', 'aws-1'),
createSecretsEngine(undefined, 'aws', 'aws-2'),
createSecretsEngine(undefined, 'nomad', 'nomad-test'),
+ createSecretsEngine(undefined, 'badType', 'external-test'),
];
});
test('it allows you to disable an engine', async function (assert) {
- const enginePath = 'kv2-test';
+ const enginePath = 'kv-test';
this.server.delete(`sys/mounts/${enginePath}`, () => {
assert.true(true, 'Request is made to delete engine');
return overrideResponse(204);
@@ -63,6 +64,54 @@ module('Integration | Component | secret-engine/list', function (hooks) {
);
});
+ test('hovering over the icon of an external unrecognized engine type sets unrecognized tooltip text', async function (assert) {
+ await render(hbs``);
+
+ await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), 'external-test');
+ await triggerEvent('.hds-tooltip-button', 'mouseenter');
+
+ assert
+ .dom('.hds-tooltip-container')
+ .hasText(
+ 'This plugin is not supported by the UI. Please use the CLI to manage this engine.',
+ 'shows tooltip text for unsupported engine'
+ );
+ });
+
+ test('hovering over the icon of an unsupported engine sets unsupported tooltip text', async function (assert) {
+ await render(hbs``);
+
+ await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-type'), 'nomad');
+ await triggerEvent('.hds-tooltip-button', 'mouseenter');
+
+ assert
+ .dom('.hds-tooltip-container')
+ .hasText(
+ 'The UI only supports configuration views for these secret engines. The CLI must be used to manage other engine resources.',
+ 'shows tooltip text for unsupported engine'
+ );
+ });
+
+ test('hovering over the icon of a supported engine sets engine name as tooltip', async function (assert) {
+ await render(hbs``);
+ await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), 'aws-1');
+
+ await triggerEvent('.hds-tooltip-button', 'mouseenter');
+
+ assert.dom('.hds-tooltip-container').hasText('AWS', 'shows tooltip text for supported engine with name');
+ });
+
+ test('hovering over the icon of a kv engine shows engine name and version', async function (assert) {
+ await render(hbs``);
+
+ await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), `kv-test`);
+
+ await triggerEvent('.hds-tooltip-button', 'mouseenter');
+ assert
+ .dom('.hds-tooltip-container')
+ .hasText('KV version 1', 'shows tooltip text for kv engine with version');
+ });
+
test('it adds disabled css styling to unsupported secret engines', async function (assert) {
await render(hbs``);
assert