mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-15 19:17:02 +02:00
* Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License. Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUS-1.1 * Fix test that expected exact offset on hcl file --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Sarah Thompson <sthompson@hashicorp.com> Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
280 lines
11 KiB
JavaScript
280 lines
11 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { module, test } from 'qunit';
|
|
import { setupRenderingTest } from 'ember-qunit';
|
|
import { setupEngine } from 'ember-engines/test-support';
|
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
|
import { render, click, waitUntil, find, fillIn } from '@ember/test-helpers';
|
|
import hbs from 'htmlbars-inline-precompile';
|
|
import { Response } from 'miragejs';
|
|
import sinon from 'sinon';
|
|
|
|
module('Integration | Component | kubernetes | Page::Configure', function (hooks) {
|
|
setupRenderingTest(hooks);
|
|
setupEngine(hooks, 'kubernetes');
|
|
setupMirage(hooks);
|
|
|
|
hooks.beforeEach(function () {
|
|
this.store = this.owner.lookup('service:store');
|
|
this.newModel = this.store.createRecord('kubernetes/config', { backend: 'kubernetes-new' });
|
|
this.existingConfig = {
|
|
kubernetes_host: 'https://192.168.99.100:8443',
|
|
kubernetes_ca_cert: '-----BEGIN CERTIFICATE-----\n.....\n-----END CERTIFICATE-----',
|
|
service_account_jwt: 'test-jwt',
|
|
disable_local_ca_jwt: true,
|
|
};
|
|
this.store.pushPayload('kubernetes/config', {
|
|
modelName: 'kubernetes/config',
|
|
backend: 'kubernetes-edit',
|
|
...this.existingConfig,
|
|
});
|
|
this.editModel = this.store.peekRecord('kubernetes/config', 'kubernetes-edit');
|
|
this.breadcrumbs = [
|
|
{ label: 'secrets', route: 'secrets', linkExternal: true },
|
|
{ label: 'kubernetes', route: 'overview' },
|
|
{ label: 'configure' },
|
|
];
|
|
this.expectedInferred = {
|
|
disable_local_ca_jwt: false,
|
|
kubernetes_ca_cert: null,
|
|
kubernetes_host: null,
|
|
service_account_jwt: null,
|
|
};
|
|
});
|
|
|
|
test('it should display proper options when toggling radio cards', async function (assert) {
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
assert
|
|
.dom('[data-test-radio-card="local"] input')
|
|
.isChecked('Local cluster radio card is checked by default');
|
|
assert
|
|
.dom('[data-test-config] p')
|
|
.hasText(
|
|
'Configuration values can be inferred from the pod and your local environment variables.',
|
|
'Inferred text is displayed'
|
|
);
|
|
assert.dom('[data-test-config] button').hasText('Get config values', 'Get config button renders');
|
|
assert
|
|
.dom('[data-test-config-save]')
|
|
.isDisabled('Save button is disabled when config values have not been inferred');
|
|
assert.dom('[data-test-config-cancel]').hasText('Back', 'Back button renders');
|
|
|
|
await click('[data-test-radio-card="manual"]');
|
|
assert.dom('[data-test-field]').exists({ count: 3 }, 'Form fields render');
|
|
assert.dom('[data-test-config-save]').isNotDisabled('Save button is enabled');
|
|
assert.dom('[data-test-config-cancel]').hasText('Back', 'Back button renders');
|
|
});
|
|
|
|
test('it should check for inferred config variables', async function (assert) {
|
|
assert.expect(8);
|
|
|
|
let status = 404;
|
|
this.server.get('/:path/check', () => {
|
|
assert.ok(
|
|
waitUntil(() => find('[data-test-config] button').disabled),
|
|
'Button is disabled while request is in flight'
|
|
);
|
|
return new Response(status, {});
|
|
});
|
|
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
await click('[data-test-config] button');
|
|
assert
|
|
.dom('[data-test-icon="x-square-fill"]')
|
|
.hasClass('has-text-danger', 'Icon is displayed for error state with correct styling');
|
|
const error =
|
|
'Vault could not infer a configuration from your environment variables. Check your configuration file to edit or delete them, or configure manually.';
|
|
assert.dom('[data-test-config] span').hasText(error, 'Error text is displayed');
|
|
assert.dom('[data-test-config-save]').isDisabled('Save button is disabled in error state');
|
|
|
|
status = 204;
|
|
await click('[data-test-radio-card="manual"]');
|
|
await click('[data-test-radio-card="local"]');
|
|
await click('[data-test-config] button');
|
|
assert
|
|
.dom('[data-test-icon="check-circle-fill"]')
|
|
.hasClass('has-text-success', 'Icon is displayed for success state with correct styling');
|
|
assert
|
|
.dom('[data-test-config] span')
|
|
.hasText('Configuration values were inferred successfully.', 'Success text is displayed');
|
|
assert.dom('[data-test-config-save]').isNotDisabled('Save button is enabled in success state');
|
|
});
|
|
|
|
test('it should create new manual config', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
this.server.post('/:path/config', (schema, req) => {
|
|
const json = JSON.parse(req.requestBody);
|
|
assert.deepEqual(json, this.existingConfig, 'Values are passed to create endpoint');
|
|
return new Response(204, {});
|
|
});
|
|
|
|
const stub = sinon.stub(this.owner.lookup('service:router'), 'transitionTo');
|
|
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
await click('[data-test-radio-card="manual"]');
|
|
await fillIn('[data-test-input="kubernetesHost"]', this.existingConfig.kubernetes_host);
|
|
await fillIn('[data-test-input="serviceAccountJwt"]', this.existingConfig.service_account_jwt);
|
|
await fillIn('[data-test-input="kubernetesCaCert"]', this.existingConfig.kubernetes_ca_cert);
|
|
await click('[data-test-config-save]');
|
|
assert.ok(
|
|
stub.calledWith('vault.cluster.secrets.backend.kubernetes.configuration'),
|
|
'Transitions to configuration route on save success'
|
|
);
|
|
});
|
|
|
|
test('it should edit existing manual config', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
const stub = sinon.stub(this.owner.lookup('service:router'), 'transitionTo');
|
|
|
|
await render(hbs`<Page::Configure @model={{this.editModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
assert.dom('[data-test-radio-card="manual"] input').isChecked('Manual config radio card is checked');
|
|
assert
|
|
.dom('[data-test-input="kubernetesHost"]')
|
|
.hasValue(this.existingConfig.kubernetes_host, 'Host field is populated');
|
|
assert
|
|
.dom('[data-test-input="serviceAccountJwt"]')
|
|
.hasValue(this.existingConfig.service_account_jwt, 'JWT field is populated');
|
|
assert
|
|
.dom('[data-test-input="kubernetesCaCert"]')
|
|
.hasValue(this.existingConfig.kubernetes_ca_cert, 'Cert field is populated');
|
|
|
|
await fillIn('[data-test-input="kubernetesHost"]', 'http://localhost:1212');
|
|
await click('[data-test-config-cancel]');
|
|
|
|
assert.ok(
|
|
stub.calledWith('vault.cluster.secrets.backend.kubernetes.configuration'),
|
|
'Transitions to configuration route when cancelling edit'
|
|
);
|
|
assert.strictEqual(
|
|
this.editModel.kubernetesHost,
|
|
this.existingConfig.kubernetes_host,
|
|
'Model values are rolled back on cancel'
|
|
);
|
|
});
|
|
|
|
test('it should display inferred success message when editing model using local values', async function (assert) {
|
|
this.store.pushPayload('kubernetes/config', {
|
|
modelName: 'kubernetes/config',
|
|
backend: 'kubernetes-edit-2',
|
|
disable_local_ca_jwt: false,
|
|
});
|
|
this.model = this.store.peekRecord('kubernetes/config', 'kubernetes-edit-2');
|
|
|
|
await render(hbs`<Page::Configure @model={{this.model}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
assert.dom('[data-test-radio-card="local"] input').isChecked('Local cluster radio card is checked');
|
|
assert
|
|
.dom('[data-test-icon="check-circle-fill"]')
|
|
.hasClass('has-text-success', 'Icon is displayed for success state with correct styling');
|
|
assert
|
|
.dom('[data-test-config] span')
|
|
.hasText('Configuration values were inferred successfully.', 'Success text is displayed');
|
|
});
|
|
|
|
test('it should show confirmation modal when saving edits', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
this.server.post('/:path/config', () => {
|
|
assert.ok(true, 'Save request made after confirmation');
|
|
return new Response(204, {});
|
|
});
|
|
|
|
await render(
|
|
hbs`
|
|
<div id="modal-wormhole"></div>
|
|
<Page::Configure @model={{this.editModel}} @breadcrumbs={{this.breadcrumbs}} />
|
|
`,
|
|
{ owner: this.engine }
|
|
);
|
|
await click('[data-test-config-save]');
|
|
assert
|
|
.dom('.modal-card-body')
|
|
.hasText(
|
|
'Making changes to your configuration may affect how Vault will reach the Kubernetes API and authenticate with it. Are you sure?',
|
|
'Confirm modal renders'
|
|
);
|
|
await click('[data-test-config-confirm]');
|
|
});
|
|
|
|
test('it should validate form and show errors', async function (assert) {
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
await click('[data-test-radio-card="manual"]');
|
|
await click('[data-test-config-save]');
|
|
|
|
assert
|
|
.dom('[data-test-inline-error-message]')
|
|
.hasText('Kubernetes host is required', 'Error renders for required field');
|
|
assert.dom('[data-test-alert] p').hasText('There is an error with this form.', 'Alert renders');
|
|
});
|
|
|
|
test('it should save inferred config', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
this.server.get('/:path/check', () => new Response(204, {}));
|
|
this.server.post('/:path/config', (schema, req) => {
|
|
const json = JSON.parse(req.requestBody);
|
|
assert.deepEqual(json, this.expectedInferred, 'Values are passed to create endpoint');
|
|
return new Response(204, {});
|
|
});
|
|
|
|
const stub = sinon.stub(this.owner.lookup('service:router'), 'transitionTo');
|
|
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
await click('[data-test-config] button');
|
|
await click('[data-test-config-save]');
|
|
|
|
assert.ok(
|
|
stub.calledWith('vault.cluster.secrets.backend.kubernetes.configuration'),
|
|
'Transitions to configuration route on save success'
|
|
);
|
|
});
|
|
|
|
test('it should unset manual config values when saving local cluster option', async function (assert) {
|
|
assert.expect(1);
|
|
|
|
this.server.get('/:path/check', () => new Response(204, {}));
|
|
this.server.post('/:path/config', (schema, req) => {
|
|
const json = JSON.parse(req.requestBody);
|
|
assert.deepEqual(json, this.expectedInferred, 'Manual config values are unset in server payload');
|
|
return new Response(204, {});
|
|
});
|
|
|
|
await render(hbs`<Page::Configure @model={{this.newModel}} @breadcrumbs={{this.breadcrumbs}} />`, {
|
|
owner: this.engine,
|
|
});
|
|
|
|
await click('[data-test-radio-card="manual"]');
|
|
await fillIn('[data-test-input="kubernetesHost"]', this.existingConfig.kubernetes_host);
|
|
await fillIn('[data-test-input="serviceAccountJwt"]', this.existingConfig.service_account_jwt);
|
|
await fillIn('[data-test-input="kubernetesCaCert"]', this.existingConfig.kubernetes_ca_cert);
|
|
|
|
await click('[data-test-radio-card="local"]');
|
|
await click('[data-test-config] button');
|
|
await click('[data-test-config-save]');
|
|
});
|
|
});
|