target workers UI Enterprise and HCP workflow (#1601)
adds ingress filter to target worker filter
This commit is contained in:
1 parent
de986c3df4
commit
d7f54af7e4
9 files changed
+241
-83
No files matched your search
@@ -374,27 +374,31 @@ target:
|
||||
diagram:
|
||||
client: Client
|
||||
any-worker: Any worker
|
||||
front-line-worker: Front line worker
|
||||
frontline-worker: Frontline worker
|
||||
hcp-worker: HCP worker
|
||||
egress-worker: Egress worker
|
||||
ingress-worker: Ingress worker
|
||||
host: Host
|
||||
network: Private network
|
||||
filter-explainer:
|
||||
any-worker: In this configuration, the client will attemt to connect through any client-accessible worker.
|
||||
egress-worker: In this configuration, the client will attemt to connect through any filtered egress worker.
|
||||
ingress-worker: In this configuration, the client will attempt to conect through any filtered ingress worker.
|
||||
any-worker: In this configuration, the client will attempt to connect through any client-accessible worker.
|
||||
egress-worker: In this configuration, the client will attempt to connect through any filtered egress worker.
|
||||
ingress-worker: In this configuration, the client will attempt to connect through any filtered ingress worker.
|
||||
hcp-worker: In this configuration, the client will attempt to connect through any HCP-managed worker.
|
||||
ent-dual-egress-on: In this configuration, the client will attempt to connect through any client-accessible "frontline" worker and reach the host through any filtered egress worker.
|
||||
hcp-dual-egress-on: In this configuration, the client will attempt to connect through any HC-managed worker and reach the host through any filtered egress worker.
|
||||
dual-egress-on-ingress-on: In this configuration, the client will attempt to connect through any filtered ingress worker and reach the house through any filtered egress worker.
|
||||
dual-egress-on: In this configuration, the client will attempt to connect through any client-accessible "frontline" worker and reach the host through any filtered egress worker.
|
||||
dual-egress-on-ingress-on: In this configuration, the client will attempt to connect through any filtered ingress worker and reach the host through any filtered egress worker.
|
||||
hcp-dual-egress-on: In this configuration, the client will attempt to connect through any HCP-managed worker and reach the host through any filtered egress worker.
|
||||
filter:
|
||||
title: Filter
|
||||
description: Boolean expression.
|
||||
egress_worker_filter:
|
||||
title: Egress worker filter
|
||||
description: Specify workers that have access to the target (such as within a private network).
|
||||
filter:
|
||||
title: Filter
|
||||
description: Boolean expression.
|
||||
update_filter: Update Filter
|
||||
ingress_worker_filter:
|
||||
title: Ingress worker filter
|
||||
description: Specify workers Boundary should use to start the route to this target.
|
||||
actions:
|
||||
update-filter: Update Filter
|
||||
credential-store:
|
||||
title: Credential Store
|
||||
title_plural: Credential Stores
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (feature-flag 'target-worker-filters-v2')}}
|
||||
|
||||
<Hds::Form::Fieldset
|
||||
class='target-workers'
|
||||
@layout='horizontal'
|
||||
@@ -218,9 +219,7 @@
|
||||
<F.Control>
|
||||
<Hds::Button
|
||||
class='update-filter-button'
|
||||
@text={{t
|
||||
'resources.target.workers.egress_worker_filter.filter.update_filter'
|
||||
}}
|
||||
@text={{t 'resources.target.workers.actions.update-filter'}}
|
||||
@color='secondary'
|
||||
disabled={{form.disabled}}
|
||||
{{on 'click' this.migrateWorkerFilters}}
|
||||
@@ -228,24 +227,51 @@
|
||||
</F.Control>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<F.Control>
|
||||
{{#if this.showTargetFilters}}
|
||||
{{#if this.workerDiagramHCPDualFilter}}
|
||||
<WorkerDiagram::DualFilter::Hcp
|
||||
@egressFilter={{this.egressWorkerFilterEnabled}}
|
||||
@ingressFilter={{this.ingressWorkerFilterEnabled}}
|
||||
/>
|
||||
{{else if this.workerDiagramDualFilter}}
|
||||
<WorkerDiagram::DualFilter
|
||||
@egressFilter={{this.egressWorkerFilterEnabled}}
|
||||
@ingressFilter={{this.ingressWorkerFilterEnabled}}
|
||||
/>
|
||||
{{else}}
|
||||
<WorkerDiagram::SingleFilter
|
||||
@egressFilter={{this.egressWorkerFilterEnabled}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.showEgressFilter}}
|
||||
<F.Control>
|
||||
<WorkerDiagram::SingleFilter
|
||||
@egressFilter={{this.egressWorkerFilterEnabled}}
|
||||
/>
|
||||
{{#if (feature-flag 'target-worker-filters-v2-ingress')}}
|
||||
<Form::Target::WorkerFilter
|
||||
@name='ingress_worker_filter'
|
||||
@disabled={{form.disabled}}
|
||||
@value={{@model.ingress_worker_filter}}
|
||||
@toggleAction={{this.toggleIngressFilter}}
|
||||
@toggleEnabled={{this.ingressWorkerFilterEnabled}}
|
||||
@onChange={{set-from-event @model 'ingress_worker_filter'}}
|
||||
@isInvalid={{@model.errors.ingress_worker_filter}}
|
||||
as |F|
|
||||
>
|
||||
{{#if @model.errors.ingress_worker_filter}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.ingress_worker_filter as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Form::Target::WorkerFilter>
|
||||
{{/if}}
|
||||
|
||||
</F.Control>
|
||||
<F.Control>
|
||||
<Form::Target::WorkerFilter
|
||||
@name='egress_worker_filter'
|
||||
@type='text'
|
||||
@disabled={{form.disabled}}
|
||||
@value={{@model.egress_worker_filter}}
|
||||
@toggleAction={{this.toggleEgressWorkerFilter}}
|
||||
@checked={{this.egressWorkerFilterEnabled}}
|
||||
@toggleAction={{this.toggleEgressFilter}}
|
||||
@toggleEnabled={{this.egressWorkerFilterEnabled}}
|
||||
@errors={{@model.errors.egress_worker_filter}}
|
||||
@onChange={{set-from-event @model 'egress_worker_filter'}}
|
||||
@isInvalid={{@model.errors.egress_worker_filter}}
|
||||
as |F|
|
||||
@@ -259,40 +285,8 @@
|
||||
{{/if}}
|
||||
</Form::Target::WorkerFilter>
|
||||
|
||||
</F.Control>
|
||||
{{/if}}
|
||||
|
||||
{{#if @model.isNew}}
|
||||
<F.Control>
|
||||
<WorkerDiagram::SingleFilter
|
||||
@egressFilter={{this.egressWorkerFilterEnabled}}
|
||||
/>
|
||||
</F.Control>
|
||||
<F.Control>
|
||||
<Form::Target::WorkerFilter
|
||||
@name='egress_worker_filter'
|
||||
@type='text'
|
||||
@disabled={{form.disabled}}
|
||||
@value={{@model.egress_worker_filter}}
|
||||
@toggleAction={{this.toggleEgressWorkerFilter}}
|
||||
@checked={{this.egressWorkerFilterEnabled}}
|
||||
@toggleEnabled={{this.egressWorkerFilterEnabled}}
|
||||
@errors={{@model.errors.egress_worker_filter}}
|
||||
@onChange={{set-from-event @model 'egress_worker_filter'}}
|
||||
@isInvalid={{@model.errors.egress_worker_filter}}
|
||||
as |F|
|
||||
>
|
||||
{{#if @model.errors.egress_worker_filter}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.egress_worker_filter as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Form::Target::WorkerFilter>
|
||||
</F.Control>
|
||||
{{/if}}
|
||||
|
||||
{{/if}}
|
||||
</F.Control>
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
{{else}}
|
||||
@@ -326,4 +320,5 @@
|
||||
@cancelText={{t 'actions.cancel'}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
</Rose::Form>
|
||||
@@ -2,6 +2,7 @@ import Component from '@glimmer/component';
|
||||
import { TYPES_TARGET } from 'api/models/target';
|
||||
import { action } from '@ember/object';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
// NOTE: this is all a temporary solution till we have a resource type helper.
|
||||
const types = [...TYPES_TARGET].reverse();
|
||||
@@ -9,13 +10,13 @@ const icons = {
|
||||
ssh: 'terminal-screen',
|
||||
tcp: 'network',
|
||||
};
|
||||
|
||||
export default class FormTargetComponent extends Component {
|
||||
// =properties
|
||||
@tracked egressWorkerFilterEnabled =
|
||||
this.args.model.egress_worker_filter?.length;
|
||||
@tracked egressWorkerFilterEnabled = this.args.model.egress_worker_filter;
|
||||
@tracked ingressWorkerFilterEnabled = this.args.model.ingress_worker_filter;
|
||||
|
||||
// =properties
|
||||
// =services
|
||||
@service features;
|
||||
/**
|
||||
* maps resource type with icon
|
||||
* @type {object}
|
||||
@@ -49,28 +50,56 @@ export default class FormTargetComponent extends Component {
|
||||
* @type {boolean}
|
||||
*/
|
||||
get showUpdateWorkerFilterButton() {
|
||||
return this.args.model.worker_filter?.length;
|
||||
return this.args.model.worker_filter;
|
||||
}
|
||||
|
||||
get showEgressFilter() {
|
||||
return !this.args.model.worker_filter?.length && !this.args.model.isNew;
|
||||
/**
|
||||
* determines when the filters should be shown
|
||||
* @type {boolean}
|
||||
*/
|
||||
get showTargetFilters() {
|
||||
return !this.args.model.worker_filter;
|
||||
}
|
||||
|
||||
//note: these getters will go away when we refactor worker diagram
|
||||
/**
|
||||
* determines when the enterprise dual filter diagrams should be shown
|
||||
* @type {boolean}
|
||||
*/
|
||||
get workerDiagramDualFilter() {
|
||||
return this.features.isEnabled('target-worker-filters-v2-ingress');
|
||||
}
|
||||
/**
|
||||
* determines when the hcp dual filter diagrams should be shown
|
||||
* @type {boolean}
|
||||
*/
|
||||
get workerDiagramHCPDualFilter() {
|
||||
return this.features.isEnabled('target-worker-filters-v2-hcp');
|
||||
}
|
||||
|
||||
//actions
|
||||
@action
|
||||
toggleEgressWorkerFilter() {
|
||||
toggleEgressFilter() {
|
||||
this.egressWorkerFilterEnabled = !this.egressWorkerFilterEnabled;
|
||||
if (!this.egressWorkerFilterEnabled) {
|
||||
this.args.model.egress_worker_filter = '';
|
||||
}
|
||||
}
|
||||
|
||||
// =actions
|
||||
@action
|
||||
toggleIngressFilter() {
|
||||
this.ingressWorkerFilterEnabled = !this.ingressWorkerFilterEnabled;
|
||||
if (!this.ingressWorkerFilterEnabled) {
|
||||
this.args.model.ingress_worker_filter = '';
|
||||
}
|
||||
}
|
||||
@action
|
||||
migrateWorkerFilters() {
|
||||
this.egressWorkerFilterEnabled = true;
|
||||
this.ingressWorkerFilterEnabled = true;
|
||||
// When update is clicked, copy worker filter value into egress filter and clear the worker_filter
|
||||
this.args.model.egress_worker_filter = this.args.model.worker_filter;
|
||||
this.args.model.ingress_worker_filter = this.args.model.worker_filter;
|
||||
this.args.model.worker_filter = '';
|
||||
}
|
||||
|
||||
@@ -82,7 +111,9 @@ export default class FormTargetComponent extends Component {
|
||||
cancel() {
|
||||
this.args.cancel();
|
||||
// Reset the tracked variable for toggles after rollback
|
||||
this.egressWorkerFilterEnabled =
|
||||
this.args.model.egress_worker_filter?.length;
|
||||
|
||||
this.egressWorkerFilterEnabled = this.args.model.egress_worker_filter;
|
||||
|
||||
this.ingressWorkerFilterEnabled = this.args.model.ingress_worker_filter;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class='target-worker-filter'>
|
||||
<div class='target-worker-filter' data-test-filter={{@name}}>
|
||||
|
||||
<Hds::Form::Toggle::Field
|
||||
name='target-worker-filter-toggle'
|
||||
checked={{@checked}}
|
||||
checked={{@toggleEnabled}}
|
||||
disabled={{@disabled}}
|
||||
@isRequired={{false}}
|
||||
@isOptional={{true}}
|
||||
@@ -27,12 +27,9 @@
|
||||
{{on 'input' @onChange}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t
|
||||
(concat 'resources.target.workers.' @name '.filter.title')
|
||||
}}</F.Label>
|
||||
<F.HelperText>{{t
|
||||
(concat 'resources.target.workers.' @name '.filter.description')
|
||||
}}
|
||||
<F.Label>{{t 'resources.target.workers.filter.title'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.target.workers.filter.description'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'target.worker-filters'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
</OrderedSeriesDiagram>
|
||||
<div class='target-worker-filter-explainer'>
|
||||
<Hds::Form::HelperText>
|
||||
{{t 'resources.target.workers.filter-explainer.hcp-dual-egress-on'}}
|
||||
{{t
|
||||
'resources.target.workers.filter-explainer.dual-egress-on-ingress-on'
|
||||
}}
|
||||
</Hds::Form::HelperText>
|
||||
</div>
|
||||
{{else if @ingressFilter}}
|
||||
@@ -56,7 +58,7 @@
|
||||
{{#if (feature-flag 'target-worker-filters-v2-hcp')}}
|
||||
{{t 'resources.target.workers.diagram.hcp-worker'}}
|
||||
{{else}}
|
||||
{{t 'resources.target.workers.diagram.front-line-worker'}}
|
||||
{{t 'resources.target.workers.diagram.frontline-worker'}}
|
||||
{{/if}}
|
||||
</D.Item>
|
||||
<D.Group
|
||||
@@ -73,7 +75,7 @@
|
||||
</OrderedSeriesDiagram>
|
||||
<div class='target-worker-filter-explainer'>
|
||||
<Hds::Form::HelperText>
|
||||
{{t 'resources.target.workers.filter-explainer.egress-on'}}
|
||||
{{t 'resources.target.workers.filter-explainer.hcp-dual-egress-on'}}
|
||||
</Hds::Form::HelperText>
|
||||
</div>
|
||||
{{else}}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
{{t 'resources.target.workers.diagram.client'}}
|
||||
</D.Item>
|
||||
<D.Item @icon='settings'>
|
||||
{{t 'resources.target.workers.diagram.front-line-worker'}}
|
||||
{{t 'resources.target.workers.diagram.frontline-worker'}}
|
||||
</D.Item>
|
||||
<D.Group
|
||||
@title={{t 'resources.target.workers.diagram.network'}}
|
||||
@@ -65,7 +65,7 @@
|
||||
</OrderedSeriesDiagram>
|
||||
<div class='target-worker-filter-explainer'>
|
||||
<Hds::Form::HelperText>
|
||||
{{t 'resources.target.workers.filter-explainer.egress-worker'}}
|
||||
{{t 'resources.target.workers.filter-explainer.dual-egress-on'}}
|
||||
</Hds::Form::HelperText>
|
||||
</div>
|
||||
{{else}}
|
||||
|
||||
@@ -136,6 +136,7 @@ module('Acceptance | targets | create', function (hooks) {
|
||||
'random filter'
|
||||
);
|
||||
});
|
||||
|
||||
test('can create type `tcp` when `target-worker-filters-v2` is disabled', async function (assert) {
|
||||
featuresService.disable('target-worker-filters-v2');
|
||||
assert.expect(4);
|
||||
@@ -161,6 +162,7 @@ module('Acceptance | targets | create', function (hooks) {
|
||||
'random filter'
|
||||
);
|
||||
});
|
||||
|
||||
test('can create type `tcp` when `target-worker-filters-v2` is enabled', async function (assert) {
|
||||
featuresService.enable('target-worker-filters-v2');
|
||||
assert.expect(4);
|
||||
@@ -188,6 +190,42 @@ module('Acceptance | targets | create', function (hooks) {
|
||||
'random filter'
|
||||
);
|
||||
});
|
||||
|
||||
test('can create type `tcp` when `target-worker-filters-v2` and `target-worker-filters-v2-ingress` is enabled', async function (assert) {
|
||||
featuresService.enable('target-worker-filters-v2');
|
||||
featuresService.enable('target-worker-filters-v2-ingress');
|
||||
assert.expect(4);
|
||||
const targetCount = getTargetCount();
|
||||
const tcpTargetCount = getTCPTargetCount();
|
||||
await visit(urls.targets);
|
||||
|
||||
await click(`[href="${urls.newTarget}"]`);
|
||||
await click('[value="tcp"]');
|
||||
await fillIn('[name="name"]', 'random string');
|
||||
await click(
|
||||
'[data-test-filter="egress_worker_filter"] .hds-form-toggle__control'
|
||||
);
|
||||
await fillIn('[name="egress_worker_filter"]', 'random filter');
|
||||
await click(
|
||||
'[data-test-filter="ingress_worker_filter"] .hds-form-toggle__control'
|
||||
);
|
||||
await fillIn('[name="ingress_worker_filter"]', 'random filter');
|
||||
|
||||
await click('[type="submit"]');
|
||||
|
||||
assert.strictEqual(getTargetCount(), targetCount + 1);
|
||||
assert.strictEqual(getTCPTargetCount(), tcpTargetCount + 1);
|
||||
assert.strictEqual(
|
||||
this.server.schema.targets.all().models[getTargetCount() - 1].name,
|
||||
'random string'
|
||||
);
|
||||
assert.strictEqual(
|
||||
this.server.schema.targets.all().models[getTargetCount() - 1]
|
||||
.egressWorkerFilter,
|
||||
'random filter'
|
||||
);
|
||||
});
|
||||
|
||||
test('default port is not marked required for SSH targets', async function (assert) {
|
||||
assert.expect(1);
|
||||
await visit(urls.newTarget);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, getContext } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
|
||||
module('Integration | Component | form/target/details', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupIntl(hooks);
|
||||
|
||||
let featuresService;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
const { owner } = getContext();
|
||||
featuresService = owner.lookup('service:features');
|
||||
this.model = { type: 'ssh' };
|
||||
this.submit = () => {};
|
||||
this.cancel = () => {};
|
||||
this.changeType = () => {};
|
||||
});
|
||||
|
||||
test('shows the correct worker diagram when `target-worker-filters-v2` is enabled', async function (assert) {
|
||||
featuresService.enable('target-worker-filters-v2');
|
||||
featuresService.disable('target-worker-filters-v2-ingress');
|
||||
featuresService.disable('target-worker-filters-v2-hcp');
|
||||
assert.expect(1);
|
||||
await render(
|
||||
hbs`<Form::Target::Details @model={{this.model}} @defaultPort='22' @submit={{this.submit}} @cancel={{this.cancel}} @changeType={{this.changeType}} />`
|
||||
);
|
||||
|
||||
assert.dom('[data-test-single-filter-egress-off]').isVisible();
|
||||
});
|
||||
|
||||
test('shows the correct worker diagram when `target-worker-filters-v2` and `target-worker-filters-v2-ingress` is enabled', async function (assert) {
|
||||
featuresService.enable('target-worker-filters-v2');
|
||||
featuresService.enable('target-worker-filters-v2-ingress');
|
||||
featuresService.disable('target-worker-filters-v2-hcp');
|
||||
assert.expect(1);
|
||||
await render(
|
||||
hbs`<Form::Target::Details @model={{this.model}} @defaultPort='22' @submit={{this.submit}} @cancel={{this.cancel}} @changeType={{this.changeType}} />`
|
||||
);
|
||||
|
||||
assert.dom('[data-test-dual-filters]').isVisible();
|
||||
});
|
||||
|
||||
test('shows the correct worker diagram when `target-worker-filters-v2` and `target-worker-filters-v2-ingress` and `target-worker-filters-v2-hcp` is enabled', async function (assert) {
|
||||
featuresService.enable('target-worker-filters-v2');
|
||||
featuresService.enable('target-worker-filters-v2-ingress');
|
||||
featuresService.enable('target-worker-filters-v2-hcp');
|
||||
assert.expect(1);
|
||||
await render(
|
||||
hbs`<Form::Target::Details @model={{this.model}} @defaultPort='22' @submit={{this.submit}} @cancel={{this.cancel}} @changeType={{this.changeType}} />`
|
||||
);
|
||||
|
||||
assert.dom('[data-test-dual-filters-hcp]').isVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
|
||||
module('Integration | Component | form/target/worker-filter', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupIntl(hooks);
|
||||
|
||||
test('it only renders a toggle field when "toggleEnabled" is false', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.onChange = () => {};
|
||||
this.toggleAction = () => {};
|
||||
await render(
|
||||
hbs`<Form::Target::WorkerFilter @name='egress_worker_filter' @toggleEnabled={{false}} @toggleAction={{this.toggleAction}} @onChange={{this.onChange}}/>`
|
||||
);
|
||||
|
||||
assert.dom('.hds-form-toggle').isVisible();
|
||||
assert.dom('.hds-form-text-input').doesNotExist();
|
||||
});
|
||||
|
||||
test('it renders a toggle field and text input field when "toggleEnabled" is true', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.onChange = () => {};
|
||||
this.toggleAction = () => {};
|
||||
await render(
|
||||
hbs`<Form::Target::WorkerFilter @name='egress_worker_filter' @toggleEnabled={{true}} @toggleAction={{this.toggleAction}} @onChange={{this.onChange}}/>`
|
||||
);
|
||||
|
||||
assert.dom('.hds-form-toggle').isVisible();
|
||||
assert.dom('.hds-form-text-input').isVisible();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user