Refactor host set fragment arrays (#1464)
* refactor: 💡 change host_ids to a simple attribute * refactor: 💡 manually manage host set array model attributes * refactor: 💡 Fix host set IDs usage * style: 💄 Fix comment and add braces for if statements * refactor: 💡 Add back in empty array for normalizer * refactor: 💡 Move attributes to generated model * refactor: 💡 Update array actions when creating new host sets * test: 💍 Add a few create tests for azure and aws host sets * test: 💍 Add update tests for azure and aws host sets Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
This commit is contained in:
1 parent
e3d44eb813
commit
f7c1523adb
17 files changed
+260
-84
No files matched your search
@@ -63,6 +63,28 @@ export default class GeneratedHostSetModel extends BaseModel {
|
|||||||
})
|
})
|
||||||
sync_interval_seconds;
|
sync_interval_seconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host IDs are read-only under normal circumstances. But these can
|
||||||
|
* be persisted via a dedicated call to `addHosts()`.
|
||||||
|
*/
|
||||||
|
@attr({
|
||||||
|
readOnly: true,
|
||||||
|
emptyArrayIfMissing: true,
|
||||||
|
})
|
||||||
|
host_ids;
|
||||||
|
|
||||||
|
@attr('string-array', {
|
||||||
|
emptyArrayIfMissing: true,
|
||||||
|
})
|
||||||
|
preferred_endpoints;
|
||||||
|
|
||||||
|
// AWS specific
|
||||||
|
@attr('string-array', {
|
||||||
|
isNestedAttribute: true,
|
||||||
|
emptyArrayIfMissing: true,
|
||||||
|
})
|
||||||
|
filters;
|
||||||
|
|
||||||
// Azure specific
|
// Azure specific
|
||||||
@attr('string', {
|
@attr('string', {
|
||||||
description: '',
|
description: '',
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import GeneratedHostSetModel from '../generated/models/host-set';
|
import GeneratedHostSetModel from '../generated/models/host-set';
|
||||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
|
||||||
import { types } from './host-catalog';
|
import { types } from './host-catalog';
|
||||||
|
|
||||||
export default class HostSetModel extends GeneratedHostSetModel {
|
export default class HostSetModel extends GeneratedHostSetModel {
|
||||||
@@ -67,28 +66,6 @@ export default class HostSetModel extends GeneratedHostSetModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Host IDs are read-only under normal circumstances. But these can
|
|
||||||
* be persisted via a dedicated call to `addHosts()`.
|
|
||||||
*/
|
|
||||||
@fragmentArray('fragment-string', {
|
|
||||||
readOnly: true,
|
|
||||||
emptyArrayIfMissing: true,
|
|
||||||
})
|
|
||||||
host_ids;
|
|
||||||
|
|
||||||
@fragmentArray('fragment-string', {
|
|
||||||
emptyArrayIfMissing: true,
|
|
||||||
})
|
|
||||||
preferred_endpoints;
|
|
||||||
|
|
||||||
// AWS specific
|
|
||||||
@fragmentArray('fragment-string', {
|
|
||||||
emptyArrayIfMissing: true,
|
|
||||||
isNestedAttribute: true,
|
|
||||||
})
|
|
||||||
filters;
|
|
||||||
|
|
||||||
// =methods
|
// =methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ module('Unit | Model | host set', function (hooks) {
|
|||||||
attributes: {
|
attributes: {
|
||||||
name: 'Host Set',
|
name: 'Host Set',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
host_ids: [{ value: '1' }, { value: '3' }],
|
host_ids: ['1', '2'],
|
||||||
version: 1,
|
version: 1,
|
||||||
scope: {
|
scope: {
|
||||||
scope_id: 'o_1',
|
scope_id: 'o_1',
|
||||||
@@ -55,7 +55,7 @@ module('Unit | Model | host set', function (hooks) {
|
|||||||
attributes: {
|
attributes: {
|
||||||
name: 'Host Set',
|
name: 'Host Set',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
host_ids: [{ value: '1' }, { value: '3' }],
|
host_ids: ['1', '3'],
|
||||||
version: 1,
|
version: 1,
|
||||||
scope: {
|
scope: {
|
||||||
scope_id: 'o_1',
|
scope_id: 'o_1',
|
||||||
@@ -86,7 +86,7 @@ module('Unit | Model | host set', function (hooks) {
|
|||||||
attributes: {
|
attributes: {
|
||||||
name: 'Host Set',
|
name: 'Host Set',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
host_ids: [{ value: '1' }, { value: '3' }],
|
host_ids: ['1', '3'],
|
||||||
version: 1,
|
version: 1,
|
||||||
scope: {
|
scope: {
|
||||||
scope_id: 'o_1',
|
scope_id: 'o_1',
|
||||||
@@ -117,7 +117,7 @@ module('Unit | Model | host set', function (hooks) {
|
|||||||
attributes: {
|
attributes: {
|
||||||
name: 'Host Set',
|
name: 'Host Set',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
host_ids: [{ value: '1' }, { value: '3' }],
|
host_ids: ['1', '3'],
|
||||||
version: 1,
|
version: 1,
|
||||||
scope: {
|
scope: {
|
||||||
scope_id: 'o_1',
|
scope_id: 'o_1',
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ module('Unit | Serializer | host set', function (hooks) {
|
|||||||
type: 'static',
|
type: 'static',
|
||||||
authorized_actions: [],
|
authorized_actions: [],
|
||||||
name: 'Host Set 1',
|
name: 'Host Set 1',
|
||||||
host_ids: [{ value: '1' }, { value: '2' }, { value: '3' }],
|
host_ids: ['1', '2', '3'],
|
||||||
preferred_endpoints: [
|
preferred_endpoints: [
|
||||||
{ value: 'endpoint 1' },
|
{ value: 'endpoint 1' },
|
||||||
{ value: 'endpoint 2' },
|
{ value: 'endpoint 2' },
|
||||||
@@ -135,39 +135,6 @@ module('Unit | Serializer | host set', function (hooks) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it normalizes missing host_ids to empty array', function (assert) {
|
|
||||||
assert.expect(1);
|
|
||||||
const store = this.owner.lookup('service:store');
|
|
||||||
const serializer = store.serializerFor('host-set');
|
|
||||||
const hostSet = store.createRecord('host-set').constructor;
|
|
||||||
const payload = {
|
|
||||||
id: '1',
|
|
||||||
name: 'Host Set 1',
|
|
||||||
scope: { id: 'o_123' },
|
|
||||||
};
|
|
||||||
const normalized = serializer.normalizeSingleResponse(
|
|
||||||
store,
|
|
||||||
hostSet,
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
assert.deepEqual(normalized, {
|
|
||||||
included: [],
|
|
||||||
data: {
|
|
||||||
id: '1',
|
|
||||||
type: 'host-set',
|
|
||||||
attributes: {
|
|
||||||
authorized_actions: [],
|
|
||||||
name: 'Host Set 1',
|
|
||||||
scope: { id: 'o_123', scope_id: 'o_123' },
|
|
||||||
host_ids: [],
|
|
||||||
preferred_endpoints: [],
|
|
||||||
filters: [],
|
|
||||||
},
|
|
||||||
relationships: {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('it normalizes missing array fields to empty array', function (assert) {
|
test('it normalizes missing array fields to empty array', function (assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
const store = this.owner.lookup('service:store');
|
const store = this.owner.lookup('service:store');
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ module('Unit | Transform | string array', function (hooks) {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it deserializes null to an empty array', function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
const transform = this.owner.lookup('transform:string-array');
|
||||||
|
const deserialized = transform.deserialize(null);
|
||||||
|
assert.deepEqual(deserialized, []);
|
||||||
|
});
|
||||||
|
|
||||||
test('it serializes an array of `{value}` to an array of strings', function (assert) {
|
test('it serializes an array of `{value}` to an array of strings', function (assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
const transform = this.owner.lookup('transform:string-array');
|
const transform = this.owner.lookup('transform:string-array');
|
||||||
@@ -25,4 +32,11 @@ module('Unit | Transform | string array', function (hooks) {
|
|||||||
]);
|
]);
|
||||||
assert.deepEqual(serialized, ['a', 'bee', 'Hello World']);
|
assert.deepEqual(serialized, ['a', 'bee', 'Hello World']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it serializes null to an empty array', function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
const transform = this.owner.lookup('transform:string-array');
|
||||||
|
const serialized = transform.serialize(null);
|
||||||
|
assert.deepEqual(serialized, []);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -77,6 +77,7 @@ export default class RoseFormComponent extends Component {
|
|||||||
@action
|
@action
|
||||||
enableEdit() {
|
enableEdit() {
|
||||||
this.isEditable = true;
|
this.isEditable = true;
|
||||||
|
if (this.args.edit) this.args.edit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
import { computed, action } from '@ember/object';
|
import { action, computed } from '@ember/object';
|
||||||
import { A } from '@ember/array';
|
import { A } from '@ember/array';
|
||||||
|
|
||||||
export default class FormHostSetAddHostsIndexComponent extends Component {
|
export default class FormHostSetAddHostsIndexComponent extends Component {
|
||||||
@@ -27,8 +27,9 @@ export default class FormHostSetAddHostsIndexComponent extends Component {
|
|||||||
*/
|
*/
|
||||||
@computed('args.{model,model.host_ids,hosts}')
|
@computed('args.{model,model.host_ids,hosts}')
|
||||||
get filteredHosts() {
|
get filteredHosts() {
|
||||||
const currentHostIDs = this.args.model.host_ids.map((host) => host.value);
|
return this.args.hosts.filter(
|
||||||
return this.args.hosts.filter(({ id }) => !currentHostIDs.includes(id));
|
({ id }) => !this.args.model.host_ids.includes(id)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// =actions
|
// =actions
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<Rose::Form
|
<Rose::Form
|
||||||
|
@edit={{@edit}}
|
||||||
@onSubmit={{@submit}}
|
@onSubmit={{@submit}}
|
||||||
@cancel={{@cancel}}
|
@cancel={{@cancel}}
|
||||||
@disabled={{@model.isSaving}}
|
@disabled={{@model.isSaving}}
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input
|
<form.input
|
||||||
@type='text'
|
@type='text'
|
||||||
|
@name='preferred_endpoints'
|
||||||
@value={{endpoint.value}}
|
@value={{endpoint.value}}
|
||||||
@error={{@model.errors.preferred_endpoints}}
|
@error={{@model.errors.preferred_endpoints}}
|
||||||
@contextual={{true}}
|
@contextual={{true}}
|
||||||
@@ -131,6 +133,7 @@
|
|||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input
|
<form.input
|
||||||
@type='text'
|
@type='text'
|
||||||
|
@name='preferred_endpoints'
|
||||||
@value={{@model.preferred_endpoint}}
|
@value={{@model.preferred_endpoint}}
|
||||||
placeholder='cidr:2001:4860:4860::8888/32'
|
placeholder='cidr:2001:4860:4860::8888/32'
|
||||||
/>
|
/>
|
||||||
@@ -186,6 +189,7 @@
|
|||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input
|
<form.input
|
||||||
@type='text'
|
@type='text'
|
||||||
|
@name='filters'
|
||||||
@value={{filter.value}}
|
@value={{filter.value}}
|
||||||
@error={{@model.errors.filters}}
|
@error={{@model.errors.filters}}
|
||||||
@contextual={{true}}
|
@contextual={{true}}
|
||||||
@@ -214,7 +218,11 @@
|
|||||||
|
|
||||||
<body.row as |row|>
|
<body.row as |row|>
|
||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input @type='text' @value={{@model.filter}} />
|
<form.input
|
||||||
|
@type='text'
|
||||||
|
@name='filters'
|
||||||
|
@value={{@model.filter}}
|
||||||
|
/>
|
||||||
</row.cell>
|
</row.cell>
|
||||||
<row.cell @shrink={{true}}>
|
<row.cell @shrink={{true}}>
|
||||||
<Rose::Button
|
<Rose::Button
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<Rose::Form
|
<Rose::Form
|
||||||
|
@edit={{@edit}}
|
||||||
@onSubmit={{@submit}}
|
@onSubmit={{@submit}}
|
||||||
@cancel={{@cancel}}
|
@cancel={{@cancel}}
|
||||||
@disabled={{@model.isSaving}}
|
@disabled={{@model.isSaving}}
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input
|
<form.input
|
||||||
@type='text'
|
@type='text'
|
||||||
|
@name='preferred_endpoints'
|
||||||
@value={{endpoint.value}}
|
@value={{endpoint.value}}
|
||||||
@error={{@model.errors.preferred_endpoints}}
|
@error={{@model.errors.preferred_endpoints}}
|
||||||
@contextual={{true}}
|
@contextual={{true}}
|
||||||
@@ -131,6 +133,7 @@
|
|||||||
<row.cell>
|
<row.cell>
|
||||||
<form.input
|
<form.input
|
||||||
@type='text'
|
@type='text'
|
||||||
|
@name='preferred_endpoints'
|
||||||
@value={{@model.preferred_endpoint}}
|
@value={{@model.preferred_endpoint}}
|
||||||
placeholder='cidr:2001:4860:4860::8888/32'
|
placeholder='cidr:2001:4860:4860::8888/32'
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{{component
|
{{component
|
||||||
(concat 'form/host-set/' @model.compositeType)
|
(concat 'form/host-set/' @model.compositeType)
|
||||||
model=@model
|
model=@model
|
||||||
|
edit=@edit
|
||||||
submit=@submit
|
submit=@submit
|
||||||
cancel=@cancel
|
cancel=@cancel
|
||||||
removeItemByIndex=@removeItemByIndex
|
removeItemByIndex=@removeItemByIndex
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
import { action } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
|
import { copy } from 'ember-copy';
|
||||||
|
|
||||||
export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute extends Route {
|
export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute extends Route {
|
||||||
// =services
|
// =services
|
||||||
@@ -20,16 +21,35 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a string item to array `property` on the passed `filter`.
|
* Copies the contents of string array fields in order to force the instance
|
||||||
|
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||||
|
* to the original expected array.
|
||||||
|
*
|
||||||
|
* The deep copy implemented here is required to ensure that both the
|
||||||
|
* array itself as well as its members are all new.
|
||||||
|
*
|
||||||
|
* @param {hostSetModel} hostSet
|
||||||
|
*/
|
||||||
|
@action
|
||||||
|
edit(hostSet) {
|
||||||
|
if (hostSet.preferred_endpoints) {
|
||||||
|
hostSet.preferred_endpoints = copy(hostSet.preferred_endpoints, true);
|
||||||
|
}
|
||||||
|
if (hostSet.filters) {
|
||||||
|
hostSet.filters = copy(hostSet.filters, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a string item `{ value }` to array `property` on passed `hostSet`.
|
||||||
* @param {hostSetModel} hostSet
|
* @param {hostSetModel} hostSet
|
||||||
* @param {string} property
|
* @param {string} property
|
||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
async addStringItem(hostSet, property, value) {
|
async addStringItem(hostSet, property, value) {
|
||||||
const array = hostSet.get(property);
|
const array = [...hostSet.get(property), { value }];
|
||||||
array.addObject({ value });
|
hostSet.set(property, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +61,7 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute exte
|
|||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
async removeItemByIndex(hostSet, property, index) {
|
async removeItemByIndex(hostSet, property, index) {
|
||||||
const array = hostSet.get(property);
|
const array = hostSet.get(property).filter((item, i) => i !== index);
|
||||||
array.removeAt(index);
|
hostSet.set(property, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -25,8 +25,8 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetHostsRoute
|
|||||||
return hash({
|
return hash({
|
||||||
hostSet,
|
hostSet,
|
||||||
hosts: all(
|
hosts: all(
|
||||||
hostSet.host_ids.map((host) =>
|
hostSet.host_ids.map((hostID) =>
|
||||||
this.store.findRecord('host', host.value, { reload: true })
|
this.store.findRecord('host', hostID, { reload: true })
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsNewRoute extends
|
|||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
async addStringItem(hostSet, property, value) {
|
async addStringItem(hostSet, property, value) {
|
||||||
const array = hostSet.get(property);
|
const array = [...(hostSet.get(property) ?? []), { value }];
|
||||||
array.addObject({ value });
|
hostSet.set(property, array);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Removes an item from array `property` at `index` on the
|
* Removes an item from array `property` at `index` on the
|
||||||
@@ -44,7 +44,7 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsNewRoute extends
|
|||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
async removeItemByIndex(hostSet, property, index) {
|
async removeItemByIndex(hostSet, property, index) {
|
||||||
const array = hostSet.get(property);
|
const array = hostSet.get(property).filter((item, i) => i !== index);
|
||||||
array.removeAt(index);
|
hostSet.set(property, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
@@ -20,6 +20,7 @@
|
|||||||
<page.body>
|
<page.body>
|
||||||
<Form::HostSet
|
<Form::HostSet
|
||||||
@model={{@model}}
|
@model={{@model}}
|
||||||
|
@edit={{route-action 'edit' @model}}
|
||||||
@submit={{route-action 'save' @model}}
|
@submit={{route-action 'save' @model}}
|
||||||
@cancel={{route-action 'cancel' @model}}
|
@cancel={{route-action 'cancel' @model}}
|
||||||
@removeItemByIndex={{route-action 'removeItemByIndex' @model}}
|
@removeItemByIndex={{route-action 'removeItemByIndex' @model}}
|
||||||
|
|||||||
@@ -79,6 +79,67 @@ module('Acceptance | host-catalogs | host sets | create', function (hooks) {
|
|||||||
assert.strictEqual(getHostSetCount(), count + 1);
|
assert.strictEqual(getHostSetCount(), count + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can create new aws host set', async function (assert) {
|
||||||
|
assert.expect(4);
|
||||||
|
instances.hostCatalog = this.server.create('host-catalog', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
type: 'plugin',
|
||||||
|
plugin: {
|
||||||
|
id: `plugin-id-1`,
|
||||||
|
name: 'aws',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const count = getHostSetCount();
|
||||||
|
await visit(
|
||||||
|
`${urls.hostCatalogs}/${instances.hostCatalog.id}/host-sets/new`
|
||||||
|
);
|
||||||
|
const name = 'aws host set';
|
||||||
|
await fillIn('[name="name"]', name);
|
||||||
|
await fillIn('[name="preferred_endpoints"]', 'endpoint');
|
||||||
|
await click('form fieldset:nth-of-type(2) [title="Add"]');
|
||||||
|
await fillIn('[name="filters"]', 'filter');
|
||||||
|
await click('form fieldset:nth-of-type(3) [title="Add"]');
|
||||||
|
await fillIn('[name="sync_interval_seconds"]', 10);
|
||||||
|
await click('[type="submit"]');
|
||||||
|
|
||||||
|
assert.strictEqual(getHostSetCount(), count + 1);
|
||||||
|
const hostSet = this.server.schema.hostSets.findBy({ name });
|
||||||
|
assert.deepEqual(hostSet.preferredEndpoints, ['endpoint']);
|
||||||
|
assert.deepEqual(hostSet.attributes.filters, ['filter']);
|
||||||
|
assert.deepEqual(hostSet.syncIntervalSeconds, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can create new azure host set', async function (assert) {
|
||||||
|
assert.expect(4);
|
||||||
|
instances.hostCatalog = this.server.create('host-catalog', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
type: 'plugin',
|
||||||
|
plugin: {
|
||||||
|
id: `plugin-id-1`,
|
||||||
|
name: 'azure',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const count = getHostSetCount();
|
||||||
|
await visit(
|
||||||
|
`${urls.hostCatalogs}/${instances.hostCatalog.id}/host-sets/new`
|
||||||
|
);
|
||||||
|
const name = 'azure host set';
|
||||||
|
await fillIn('[name="name"]', name);
|
||||||
|
await fillIn('[name="preferred_endpoints"]', 'endpoint');
|
||||||
|
await click('form fieldset:nth-of-type(2) [title="Add"]');
|
||||||
|
await fillIn('[name="filter"]', 'filter');
|
||||||
|
await fillIn('[name="sync_interval_seconds"]', 10);
|
||||||
|
await click('[type="submit"]');
|
||||||
|
|
||||||
|
assert.strictEqual(getHostSetCount(), count + 1);
|
||||||
|
const hostSet = this.server.schema.hostSets.findBy({ name });
|
||||||
|
assert.deepEqual(hostSet.preferredEndpoints, ['endpoint']);
|
||||||
|
assert.deepEqual(hostSet.attributes.filter, 'filter');
|
||||||
|
assert.deepEqual(hostSet.syncIntervalSeconds, 10);
|
||||||
|
});
|
||||||
|
|
||||||
test('Users cannot create a new host set without proper authorization', async function (assert) {
|
test('Users cannot create a new host set without proper authorization', async function (assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
instances.hostCatalog.authorized_collection_actions['host-sets'] = [];
|
instances.hostCatalog.authorized_collection_actions['host-sets'] = [];
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
import { visit, currentURL, find, click, fillIn } from '@ember/test-helpers';
|
import {
|
||||||
|
visit,
|
||||||
|
currentURL,
|
||||||
|
find,
|
||||||
|
findAll,
|
||||||
|
click,
|
||||||
|
fillIn,
|
||||||
|
} from '@ember/test-helpers';
|
||||||
import { setupApplicationTest } from 'ember-qunit';
|
import { setupApplicationTest } from 'ember-qunit';
|
||||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||||
import { Response } from 'miragejs';
|
import { Response } from 'miragejs';
|
||||||
@@ -100,7 +107,7 @@ module('Acceptance | host-catalogs | host sets | update', function (hooks) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can save changes to existing host', async function (assert) {
|
test('can save changes to existing host-set', async function (assert) {
|
||||||
assert.expect(3);
|
assert.expect(3);
|
||||||
assert.notEqual(instances.hostSet.name, 'random string');
|
assert.notEqual(instances.hostSet.name, 'random string');
|
||||||
await visit(urls.hostSet);
|
await visit(urls.hostSet);
|
||||||
@@ -109,11 +116,106 @@ module('Acceptance | host-catalogs | host sets | update', function (hooks) {
|
|||||||
await click('.rose-form-actions [type="submit"]');
|
await click('.rose-form-actions [type="submit"]');
|
||||||
assert.strictEqual(currentURL(), urls.hostSet);
|
assert.strictEqual(currentURL(), urls.hostSet);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
this.server.schema.hostSets.all().models[0].name,
|
this.server.schema.hostSets.first().name,
|
||||||
'random string'
|
'random string'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can save changes to an existing aws host-set', async function (assert) {
|
||||||
|
assert.expect(5);
|
||||||
|
instances.hostCatalog = this.server.create('host-catalog', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
type: 'plugin',
|
||||||
|
plugin: {
|
||||||
|
id: `plugin-id-1`,
|
||||||
|
name: 'aws',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
instances.hostSet = this.server.create('host-set', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
hostCatalog: instances.hostCatalog,
|
||||||
|
});
|
||||||
|
urls.hostSet = `${urls.hostCatalogs}/${instances.hostCatalog.id}/host-sets/${instances.hostSet.id}`;
|
||||||
|
await visit(urls.hostSet);
|
||||||
|
|
||||||
|
await click(
|
||||||
|
'form .rose-form-actions [type="button"]',
|
||||||
|
'Activate edit mode'
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = 'aws host set';
|
||||||
|
await fillIn('[name="name"]', name);
|
||||||
|
// Remove all the preferred endpoints
|
||||||
|
await Promise.all(
|
||||||
|
findAll('form fieldset:nth-of-type(2) [title="Remove"]').map((element) =>
|
||||||
|
click(element)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await fillIn('[name="preferred_endpoints"]', 'endpoint');
|
||||||
|
await click('form fieldset:nth-of-type(2) [title="Add"]');
|
||||||
|
// Remove all the filters
|
||||||
|
await Promise.all(
|
||||||
|
findAll('form fieldset:nth-of-type(3) [title="Remove"]').map((element) =>
|
||||||
|
click(element)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await fillIn('[name="filters"]', 'filter');
|
||||||
|
await click('form fieldset:nth-of-type(3) [title="Add"]');
|
||||||
|
await fillIn('[name="sync_interval_seconds"]', 10);
|
||||||
|
await click('.rose-form-actions [type="submit"]');
|
||||||
|
|
||||||
|
assert.strictEqual(currentURL(), urls.hostSet);
|
||||||
|
const hostSet = this.server.schema.hostSets.findBy({ name });
|
||||||
|
assert.strictEqual(hostSet.name, name);
|
||||||
|
assert.deepEqual(hostSet.preferredEndpoints, ['endpoint']);
|
||||||
|
assert.deepEqual(hostSet.attributes.filters, ['filter']);
|
||||||
|
assert.deepEqual(hostSet.syncIntervalSeconds, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can save changes to an existing azure host-set', async function (assert) {
|
||||||
|
assert.expect(5);
|
||||||
|
instances.hostCatalog = this.server.create('host-catalog', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
type: 'plugin',
|
||||||
|
plugin: {
|
||||||
|
id: `plugin-id-1`,
|
||||||
|
name: 'azure',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
instances.hostSet = this.server.create('host-set', {
|
||||||
|
scope: instances.scopes.project,
|
||||||
|
hostCatalog: instances.hostCatalog,
|
||||||
|
});
|
||||||
|
urls.hostSet = `${urls.hostCatalogs}/${instances.hostCatalog.id}/host-sets/${instances.hostSet.id}`;
|
||||||
|
await visit(urls.hostSet);
|
||||||
|
|
||||||
|
await click(
|
||||||
|
'form .rose-form-actions [type="button"]',
|
||||||
|
'Activate edit mode'
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = 'azure host set';
|
||||||
|
await fillIn('[name="name"]', name);
|
||||||
|
// Remove all the preferred endpoints
|
||||||
|
await Promise.all(
|
||||||
|
findAll('form fieldset:nth-of-type(2) [title="Remove"]').map((element) =>
|
||||||
|
click(element)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await fillIn('[name="preferred_endpoints"]', 'endpoint');
|
||||||
|
await click('form fieldset:nth-of-type(2) [title="Add"]');
|
||||||
|
await fillIn('[name="filter"]', 'filter');
|
||||||
|
await fillIn('[name="sync_interval_seconds"]', 10);
|
||||||
|
await click('.rose-form-actions [type="submit"]');
|
||||||
|
|
||||||
|
assert.strictEqual(currentURL(), urls.hostSet);
|
||||||
|
const hostSet = this.server.schema.hostSets.findBy({ name });
|
||||||
|
assert.strictEqual(hostSet.name, name);
|
||||||
|
assert.deepEqual(hostSet.preferredEndpoints, ['endpoint']);
|
||||||
|
assert.deepEqual(hostSet.attributes.filter, 'filter');
|
||||||
|
assert.deepEqual(hostSet.syncIntervalSeconds, 10);
|
||||||
|
});
|
||||||
|
|
||||||
test('cannot make changes to an existing host without proper authorization', async function (assert) {
|
test('cannot make changes to an existing host without proper authorization', async function (assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
instances.hostSet.authorized_actions =
|
instances.hostSet.authorized_actions =
|
||||||
@@ -122,7 +224,7 @@ module('Acceptance | host-catalogs | host sets | update', function (hooks) {
|
|||||||
assert.notOk(find('.rose-layout-page-actions .rose-button-secondary'));
|
assert.notOk(find('.rose-layout-page-actions .rose-button-secondary'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can cancel changes to existing host', async function (assert) {
|
test('can cancel changes to existing host-set', async function (assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
await visit(urls.hostSet);
|
await visit(urls.hostSet);
|
||||||
await click('form [type="button"]', 'Activate edit mode');
|
await click('form [type="button"]', 'Activate edit mode');
|
||||||
@@ -183,7 +285,7 @@ module('Acceptance | host-catalogs | host sets | update', function (hooks) {
|
|||||||
await click('.rose-dialog-footer button:first-child');
|
await click('.rose-dialog-footer button:first-child');
|
||||||
assert.strictEqual(currentURL(), urls.hostSets);
|
assert.strictEqual(currentURL(), urls.hostSets);
|
||||||
assert.notEqual(
|
assert.notEqual(
|
||||||
this.server.schema.hostSets.all().models[0].name,
|
this.server.schema.hostSets.first().name,
|
||||||
'random string'
|
'random string'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ export default class ScopesScopeProjectsTargetsTargetHostsRoute extends Route {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Extract host ids from all host sets
|
// Extract host ids from all host sets
|
||||||
const hostIds = hostSets.map(({ host_ids }) =>
|
const hostIds = hostSets.map(({ host_ids }) => host_ids);
|
||||||
host_ids.content.map((hostId) => hostId.value)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load unique hosts
|
// Load unique hosts
|
||||||
const uniqueHostIds = new Set(hostIds.flat());
|
const uniqueHostIds = new Set(hostIds.flat());
|
||||||
|
|||||||
Reference in new issue
Block a user