UI/ Add PostgreSQL DB (#12945)
* alphabetize DB plugin types * adds changelog * add postgres to database plugins * add statement fields * adds tests for postgres db * add delete confirm modal to db connection * fixes text for confirmation modal - transform * editing tests for delete modal * fixes tests, oracle must be last DB tested * adds test for modal and updates old modal tests
This commit is contained in:
parent
2d5a1f7ed4
commit
50372d19f8
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:feature
|
||||||
|
**Postgres in the UI**: Postgres DB is now supported by the UI
|
||||||
|
```
|
|
@ -23,7 +23,7 @@
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="toolbar-link"
|
class="toolbar-link"
|
||||||
{{on 'click' this.delete}}
|
onclick={{action (mut isDeleteModalActive) true}}
|
||||||
data-test-database-connection-delete
|
data-test-database-connection-delete
|
||||||
>
|
>
|
||||||
Delete connection
|
Delete connection
|
||||||
|
@ -367,3 +367,18 @@
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
@title="Delete connection?"
|
||||||
|
@onClose={{action (mut isDeleteModalActive) false}}
|
||||||
|
@isActive={{isDeleteModalActive}}
|
||||||
|
@confirmText={{@model.name}}
|
||||||
|
@toConfirmMsg="deleting the connection"
|
||||||
|
@onConfirm={{action "delete"}}
|
||||||
|
@testSelector="delete"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Deleting the connection means that any associated roles won't be able to generate credentials until the connection is reconfigured.
|
||||||
|
</p>
|
||||||
|
<MessageError @model={{model}} @errorMessage={{error}} />
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
@onClose={{action (mut isDeleteModalActive) false}}
|
@onClose={{action (mut isDeleteModalActive) false}}
|
||||||
@isActive={{isDeleteModalActive}}
|
@isActive={{isDeleteModalActive}}
|
||||||
@confirmText={{model.name}}
|
@confirmText={{model.name}}
|
||||||
@toConfirmMsg="Type {{model.name}} to confirm deleting the transformation."
|
@toConfirmMsg="deleting the transformation."
|
||||||
@onConfirm={{action "delete"}}
|
@onConfirm={{action "delete"}}
|
||||||
>
|
>
|
||||||
<p class="has-bottom-margin-m">
|
<p class="has-bottom-margin-m">
|
||||||
|
|
|
@ -1,4 +1,24 @@
|
||||||
export const AVAILABLE_PLUGIN_TYPES = [
|
export const AVAILABLE_PLUGIN_TYPES = [
|
||||||
|
{
|
||||||
|
value: 'elasticsearch-database-plugin',
|
||||||
|
displayName: 'Elasticsearch',
|
||||||
|
fields: [
|
||||||
|
{ attr: 'plugin_name' },
|
||||||
|
{ attr: 'name' },
|
||||||
|
{ attr: 'verify_connection' },
|
||||||
|
{ attr: 'password_policy' },
|
||||||
|
{ attr: 'url', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'password', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'ca_cert', group: 'pluginConfig' },
|
||||||
|
{ attr: 'ca_path', group: 'pluginConfig' },
|
||||||
|
{ attr: 'client_cert', group: 'pluginConfig' },
|
||||||
|
{ attr: 'client_key', group: 'pluginConfig' },
|
||||||
|
{ attr: 'tls_server_name', group: 'pluginConfig' },
|
||||||
|
{ attr: 'insecure', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username_template', group: 'pluginConfig' },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'mongodb-database-plugin',
|
value: 'mongodb-database-plugin',
|
||||||
displayName: 'MongoDB',
|
displayName: 'MongoDB',
|
||||||
|
@ -35,26 +55,6 @@ export const AVAILABLE_PLUGIN_TYPES = [
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value: 'mysql-database-plugin',
|
|
||||||
displayName: 'MySQL/MariaDB',
|
|
||||||
fields: [
|
|
||||||
{ attr: 'plugin_name' },
|
|
||||||
{ attr: 'name' },
|
|
||||||
{ attr: 'verify_connection' },
|
|
||||||
{ attr: 'password_policy' },
|
|
||||||
{ attr: 'connection_url', group: 'pluginConfig' },
|
|
||||||
{ attr: 'username', group: 'pluginConfig', show: false },
|
|
||||||
{ attr: 'password', group: 'pluginConfig', show: false },
|
|
||||||
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
|
||||||
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
|
||||||
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
|
||||||
{ attr: 'username_template', group: 'pluginConfig' },
|
|
||||||
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
|
|
||||||
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
|
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
value: 'mysql-aurora-database-plugin',
|
value: 'mysql-aurora-database-plugin',
|
||||||
displayName: 'MySQL (Aurora)',
|
displayName: 'MySQL (Aurora)',
|
||||||
|
@ -75,26 +75,6 @@ export const AVAILABLE_PLUGIN_TYPES = [
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value: 'mysql-rds-database-plugin',
|
|
||||||
displayName: 'MySQL (RDS)',
|
|
||||||
fields: [
|
|
||||||
{ attr: 'plugin_name' },
|
|
||||||
{ attr: 'name' },
|
|
||||||
{ attr: 'verify_connection' },
|
|
||||||
{ attr: 'password_policy' },
|
|
||||||
{ attr: 'connection_url', group: 'pluginConfig' },
|
|
||||||
{ attr: 'username', group: 'pluginConfig', show: false },
|
|
||||||
{ attr: 'password', group: 'pluginConfig', show: false },
|
|
||||||
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
|
||||||
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
|
||||||
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
|
||||||
{ attr: 'username_template', group: 'pluginConfig' },
|
|
||||||
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
|
|
||||||
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
|
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
value: 'mysql-legacy-database-plugin',
|
value: 'mysql-legacy-database-plugin',
|
||||||
displayName: 'MySQL (Legacy)',
|
displayName: 'MySQL (Legacy)',
|
||||||
|
@ -116,23 +96,43 @@ export const AVAILABLE_PLUGIN_TYPES = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'elasticsearch-database-plugin',
|
value: 'mysql-database-plugin',
|
||||||
displayName: 'Elasticsearch',
|
displayName: 'MySQL/MariaDB',
|
||||||
fields: [
|
fields: [
|
||||||
{ attr: 'plugin_name' },
|
{ attr: 'plugin_name' },
|
||||||
{ attr: 'name' },
|
{ attr: 'name' },
|
||||||
{ attr: 'verify_connection' },
|
{ attr: 'verify_connection' },
|
||||||
{ attr: 'password_policy' },
|
{ attr: 'password_policy' },
|
||||||
{ attr: 'url', group: 'pluginConfig' },
|
{ attr: 'connection_url', group: 'pluginConfig' },
|
||||||
{ attr: 'username', group: 'pluginConfig', show: false },
|
{ attr: 'username', group: 'pluginConfig', show: false },
|
||||||
{ attr: 'password', group: 'pluginConfig', show: false },
|
{ attr: 'password', group: 'pluginConfig', show: false },
|
||||||
{ attr: 'ca_cert', group: 'pluginConfig' },
|
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
||||||
{ attr: 'ca_path', group: 'pluginConfig' },
|
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
||||||
{ attr: 'client_cert', group: 'pluginConfig' },
|
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
||||||
{ attr: 'client_key', group: 'pluginConfig' },
|
|
||||||
{ attr: 'tls_server_name', group: 'pluginConfig' },
|
|
||||||
{ attr: 'insecure', group: 'pluginConfig' },
|
|
||||||
{ attr: 'username_template', group: 'pluginConfig' },
|
{ attr: 'username_template', group: 'pluginConfig' },
|
||||||
|
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'mysql-rds-database-plugin',
|
||||||
|
displayName: 'MySQL (RDS)',
|
||||||
|
fields: [
|
||||||
|
{ attr: 'plugin_name' },
|
||||||
|
{ attr: 'name' },
|
||||||
|
{ attr: 'verify_connection' },
|
||||||
|
{ attr: 'password_policy' },
|
||||||
|
{ attr: 'connection_url', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'password', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
||||||
|
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
||||||
|
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username_template', group: 'pluginConfig' },
|
||||||
|
{ attr: 'tls', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'tls_ca', group: 'pluginConfig', subgroup: 'TLS options' },
|
||||||
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -153,6 +153,24 @@ export const AVAILABLE_PLUGIN_TYPES = [
|
||||||
{ attr: 'root_rotation_statements', group: 'statements' },
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'postgresql-database-plugin',
|
||||||
|
displayName: 'PostgreSQL',
|
||||||
|
fields: [
|
||||||
|
{ attr: 'plugin_name' },
|
||||||
|
{ attr: 'name' },
|
||||||
|
{ attr: 'verify_connection' },
|
||||||
|
{ attr: 'password_policy' },
|
||||||
|
{ attr: 'connection_url', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'password', group: 'pluginConfig', show: false },
|
||||||
|
{ attr: 'max_open_connections', group: 'pluginConfig' },
|
||||||
|
{ attr: 'max_idle_connections', group: 'pluginConfig' },
|
||||||
|
{ attr: 'max_connection_lifetime', group: 'pluginConfig' },
|
||||||
|
{ attr: 'username_template', group: 'pluginConfig' },
|
||||||
|
{ attr: 'root_rotation_statements', group: 'statements' },
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ROLE_FIELDS = {
|
export const ROLE_FIELDS = {
|
||||||
|
@ -163,25 +181,32 @@ export const ROLE_FIELDS = {
|
||||||
export const STATEMENT_FIELDS = {
|
export const STATEMENT_FIELDS = {
|
||||||
static: {
|
static: {
|
||||||
default: ['rotation_statements'],
|
default: ['rotation_statements'],
|
||||||
|
'elasticsearch-database-plugin': [],
|
||||||
'mongodb-database-plugin': [],
|
'mongodb-database-plugin': [],
|
||||||
'mssql-database-plugin': [],
|
'mssql-database-plugin': [],
|
||||||
'mysql-database-plugin': [],
|
'mysql-database-plugin': [],
|
||||||
'mysql-aurora-database-plugin': [],
|
'mysql-aurora-database-plugin': [],
|
||||||
'mysql-rds-database-plugin': [],
|
|
||||||
'mysql-legacy-database-plugin': [],
|
'mysql-legacy-database-plugin': [],
|
||||||
'elasticsearch-database-plugin': [],
|
'mysql-rds-database-plugin': [],
|
||||||
'oracle-database-plugin': [],
|
'oracle-database-plugin': [],
|
||||||
|
'postgresql-database-plugin': [],
|
||||||
},
|
},
|
||||||
dynamic: {
|
dynamic: {
|
||||||
default: ['creation_statements', 'revocation_statements', 'rollback_statements', 'renew_statements'],
|
default: ['creation_statements', 'revocation_statements', 'rollback_statements', 'renew_statements'],
|
||||||
|
'elasticsearch-database-plugin': ['creation_statement'],
|
||||||
'mongodb-database-plugin': ['creation_statement', 'revocation_statement'],
|
'mongodb-database-plugin': ['creation_statement', 'revocation_statement'],
|
||||||
'mssql-database-plugin': ['creation_statements', 'revocation_statements'],
|
'mssql-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
'mysql-database-plugin': ['creation_statements', 'revocation_statements'],
|
'mysql-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
'mysql-aurora-database-plugin': ['creation_statements', 'revocation_statements'],
|
'mysql-aurora-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
'mysql-rds-database-plugin': ['creation_statements', 'revocation_statements'],
|
|
||||||
'mysql-legacy-database-plugin': ['creation_statements', 'revocation_statements'],
|
'mysql-legacy-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
'elasticsearch-database-plugin': ['creation_statement'],
|
'mysql-rds-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
'oracle-database-plugin': ['creation_statements', 'revocation_statements'],
|
'oracle-database-plugin': ['creation_statements', 'revocation_statements'],
|
||||||
|
'postgresql-database-plugin': [
|
||||||
|
'creation_statements',
|
||||||
|
'revocation_statements',
|
||||||
|
'rollback_statements',
|
||||||
|
'renew_statements',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
* @title="Do Dangerous Thing?"
|
* @title="Do Dangerous Thing?"
|
||||||
* @isActive={{isModalActive}}
|
* @isActive={{isModalActive}}
|
||||||
* @onClose={{action (mut isModalActive) false}}
|
* @onClose={{action (mut isModalActive) false}}
|
||||||
|
* @onConfirmMsg="deleting this thing to delete."
|
||||||
* />
|
* />
|
||||||
* ```
|
* ```
|
||||||
* @param {function} onConfirm - onConfirm is the action that happens when user clicks onConfirm after filling in the confirmation block
|
* @param {function} onConfirm - onConfirm is the action that happens when user clicks onConfirm after filling in the confirmation block
|
||||||
|
|
|
@ -185,6 +185,31 @@ const connectionTests = [
|
||||||
.exists(`Root rotation statements exists for ${name}`);
|
.exists(`Root rotation statements exists for ${name}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'postgresql-connection',
|
||||||
|
plugin: 'postgresql-database-plugin',
|
||||||
|
url: `postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable`,
|
||||||
|
requiredFields: async (assert, name) => {
|
||||||
|
assert.dom('[data-test-input="username"]').exists(`Username field exists for ${name}`);
|
||||||
|
assert.dom('[data-test-input="password"]').exists(`Password field exists for ${name}`);
|
||||||
|
assert
|
||||||
|
.dom('[data-test-input="max_open_connections"]')
|
||||||
|
.exists(`Max open connections exists for ${name}`);
|
||||||
|
assert
|
||||||
|
.dom('[data-test-input="max_idle_connections"]')
|
||||||
|
.exists(`Max idle connections exists for ${name}`);
|
||||||
|
assert
|
||||||
|
.dom('[data-test-input="max_connection_lifetime"]')
|
||||||
|
.exists(`Max connection lifetime exists for ${name}`);
|
||||||
|
assert
|
||||||
|
.dom('[data-test-input="root_rotation_statements"]')
|
||||||
|
.exists(`Root rotation statements exists for ${name}`);
|
||||||
|
assert
|
||||||
|
.dom('[data-test-toggle-input="show-username_template"]')
|
||||||
|
.exists(`Username template toggle exists for ${name}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// keep oracle as last DB because it is skipped in some tests (line 285) the UI doesn't return to empty state after
|
||||||
{
|
{
|
||||||
name: 'oracle-connection',
|
name: 'oracle-connection',
|
||||||
plugin: 'oracle-database-plugin',
|
plugin: 'oracle-database-plugin',
|
||||||
|
@ -256,7 +281,7 @@ module('Acceptance | secrets/database/*', function(hooks) {
|
||||||
} else {
|
} else {
|
||||||
await connectionPage.connectionUrl(testCase.url);
|
await connectionPage.connectionUrl(testCase.url);
|
||||||
}
|
}
|
||||||
// skip adding oracle db connection since plugin doesn't exists
|
// skip adding oracle db connection since plugin doesn't exist
|
||||||
if (testCase.plugin === 'oracle-database-plugin') {
|
if (testCase.plugin === 'oracle-database-plugin') {
|
||||||
testCase.requiredFields(assert, testCase.name);
|
testCase.requiredFields(assert, testCase.name);
|
||||||
continue;
|
continue;
|
||||||
|
@ -264,9 +289,9 @@ module('Acceptance | secrets/database/*', function(hooks) {
|
||||||
testCase.requiredFields(assert, testCase.name);
|
testCase.requiredFields(assert, testCase.name);
|
||||||
await connectionPage.toggleVerify();
|
await connectionPage.toggleVerify();
|
||||||
await connectionPage.save();
|
await connectionPage.save();
|
||||||
await connectionPage.enable();
|
await settled();
|
||||||
assert
|
assert
|
||||||
.dom('[data-test-modal-title]')
|
.dom('.modal.is-active .title')
|
||||||
.hasText('Rotate your root credentials?', 'Modal appears asking to rotate root credentials');
|
.hasText('Rotate your root credentials?', 'Modal appears asking to rotate root credentials');
|
||||||
await connectionPage.enable();
|
await connectionPage.enable();
|
||||||
assert.ok(
|
assert.ok(
|
||||||
|
@ -335,8 +360,9 @@ module('Acceptance | secrets/database/*', function(hooks) {
|
||||||
// uncheck verify for the save step to work
|
// uncheck verify for the save step to work
|
||||||
await connectionPage.toggleVerify();
|
await connectionPage.toggleVerify();
|
||||||
await connectionPage.save();
|
await connectionPage.save();
|
||||||
|
await settled();
|
||||||
assert
|
assert
|
||||||
.dom('[data-test-modal-title]')
|
.dom('.modal.is-active .title')
|
||||||
.hasText('Rotate your root credentials?', 'Modal appears asking to ');
|
.hasText('Rotate your root credentials?', 'Modal appears asking to ');
|
||||||
await connectionPage.enable();
|
await connectionPage.enable();
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -356,6 +382,13 @@ module('Acceptance | secrets/database/*', function(hooks) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await connectionPage.delete();
|
await connectionPage.delete();
|
||||||
|
assert
|
||||||
|
.dom('.modal.is-active .title')
|
||||||
|
.hasText('Delete connection?', 'Modal appears asking to confirm delete action');
|
||||||
|
await fillIn('[data-test-confirmation-modal-input="delete"]', connectionDetails.id);
|
||||||
|
await click('[data-test-confirm-button]');
|
||||||
|
await settled();
|
||||||
|
|
||||||
assert.equal(currentURL(), `/vault/secrets/${backend}/list`, 'Redirects to connection list page');
|
assert.equal(currentURL(), `/vault/secrets/${backend}/list`, 'Redirects to connection list page');
|
||||||
assert
|
assert
|
||||||
.dom('[data-test-empty-state-title')
|
.dom('[data-test-empty-state-title')
|
||||||
|
|
Loading…
Reference in New Issue