diff --git a/addons/api/addon/adapters/host-catalog.js b/addons/api/addon/adapters/host-catalog.js
new file mode 100644
index 000000000..78c1d9a03
--- /dev/null
+++ b/addons/api/addon/adapters/host-catalog.js
@@ -0,0 +1,13 @@
+import ApplicationAdapter from './application';
+
+export default class HostCatalogAdapter extends ApplicationAdapter {
+
+ // =attributes
+
+ /**
+ * Host catalogs use the new, unprefixed pathing style.
+ * @override
+ */
+ hasScopePrefix = false;
+
+}
diff --git a/addons/api/addon/adapters/host-set.js b/addons/api/addon/adapters/host-set.js
index fbbe11495..d237c63d9 100644
--- a/addons/api/addon/adapters/host-set.js
+++ b/addons/api/addon/adapters/host-set.js
@@ -7,32 +7,12 @@ export default class HostSetAdapter extends ApplicationAdapter {
@service store;
- // =methods
+ // =attributes
/**
- * Append a host catalog URL ahead of the host sets path if `hostCatalogID` is
- * passed via adapter options. Otherwise, generate the prefix as normal.
- *
- * TODO: generalize the interface to resource-prefixed URLs by accepting
- * a modelName and an ID, rather than looking for a known key.
- *
+ * Host sets use the new, unprefixed pathing style.
* @override
- * @param {string} path
- * @param {string} parentURL
- * @param {string} modelName
- * @param {string} id
- * @param {object} snapshot
- * @return {string} urlPrefix
*/
- urlPrefix(path, parentURL, modelName, id, snapshot) {
- const hostCatalogID = snapshot?.adapterOptions?.hostCatalogID;
- if (hostCatalogID) {
- const hostCatalogAdapter = this.store.adapterFor('host-catalog');
- return hostCatalogAdapter
- ._buildPrefixedURL('host-catalog', hostCatalogID, snapshot);
- } else {
- return super.urlPrefix(...arguments);
- }
- }
+ hasScopePrefix = false;
}
diff --git a/addons/api/addon/adapters/host.js b/addons/api/addon/adapters/host.js
index ae1747b06..d6b6ea5eb 100644
--- a/addons/api/addon/adapters/host.js
+++ b/addons/api/addon/adapters/host.js
@@ -7,32 +7,12 @@ export default class HostAdapter extends ApplicationAdapter {
@service store;
- // =methods
+ // =attributes
/**
- * Append a host catalog URL ahead of the host path if `hostCatalogID` is
- * passed via adapter options. Otherwise, generate the prefix as normal.
- *
- * TODO: generalize the interface to resource-prefixed URLs by accepting
- * a modelName and an ID, rather than looking for a known key.
- *
+ * Hosts use the new, unprefixed pathing style.
* @override
- * @param {string} path
- * @param {string} parentURL
- * @param {string} modelName
- * @param {string} id
- * @param {object} snapshot
- * @return {string} urlPrefix
*/
- urlPrefix(path, parentURL, modelName, id, snapshot) {
- const hostCatalogID = snapshot?.adapterOptions?.hostCatalogID;
- if (hostCatalogID) {
- const hostCatalogAdapter = this.store.adapterFor('host-catalog');
- return hostCatalogAdapter
- ._buildPrefixedURL('host-catalog', hostCatalogID, snapshot);
- } else {
- return super.urlPrefix(...arguments);
- }
- }
+ hasScopePrefix = false;
}
diff --git a/addons/api/addon/generated/models/host-set.js b/addons/api/addon/generated/models/host-set.js
index d1af3fe32..309165055 100644
--- a/addons/api/addon/generated/models/host-set.js
+++ b/addons/api/addon/generated/models/host-set.js
@@ -15,7 +15,6 @@ export default class GeneratedHostSetModel extends BaseModel {
@attr('string', {
description: 'The owning host catalog ID.',
- readOnly: true
}) host_catalog_id;
@attr('string', {
diff --git a/addons/api/addon/generated/models/host.js b/addons/api/addon/generated/models/host.js
index 0d9e0dd2d..50f1463e0 100644
--- a/addons/api/addon/generated/models/host.js
+++ b/addons/api/addon/generated/models/host.js
@@ -12,6 +12,10 @@ export default class GeneratedHostModel extends BaseModel {
description: 'The type of the resource, to help differentiate schemas'
}) type;
+ @attr('string', {
+ description: 'The owning host catalog ID.',
+ }) host_catalog_id;
+
@attr('string', {
description: 'Optional name for identification purposes'
}) name;
@@ -35,8 +39,4 @@ export default class GeneratedHostModel extends BaseModel {
})
version;
- @attr('string', {
- description: 'The address (DNS or IP name) used to reach the host'
- }) address;
-
}
diff --git a/addons/api/addon/models/fragment-host-attributes.js b/addons/api/addon/models/fragment-host-attributes.js
new file mode 100644
index 000000000..114da4bca
--- /dev/null
+++ b/addons/api/addon/models/fragment-host-attributes.js
@@ -0,0 +1,9 @@
+import Fragment from 'ember-data-model-fragments/fragment';
+import { attr } from '@ember-data/model';
+
+export default class FragmentHostAttributesModel extends Fragment {
+
+ @attr('string', {
+ description: 'The address (DNS or IP name) used to reach the host'
+ }) address;
+}
diff --git a/addons/api/addon/models/host-set.js b/addons/api/addon/models/host-set.js
index c4b93e905..ffa0f7906 100644
--- a/addons/api/addon/models/host-set.js
+++ b/addons/api/addon/models/host-set.js
@@ -1,6 +1,5 @@
import GeneratedHostSetModel from '../generated/models/host-set';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
-//import { computed } from '@ember/object';
export default class HostSetModel extends GeneratedHostSetModel {
@@ -12,18 +11,6 @@ export default class HostSetModel extends GeneratedHostSetModel {
*/
@fragmentArray('fragment-string', {readOnly: true}) host_ids;
- // TODO this is here in case we want it in the future,
- // especially for the target / add host sets workflow
- /**
- * Returns the host catalog instance associated with this host set if
- * it is already loaded into the store.
- * @type {?HostCatalogModel}
- */
- // @computed('host_catalog_id')
- // get hostCatalog() {
- // return this.store.peekRecord('host-catalog', this.host_catalog_id);
- // }
-
// =methods
/**
diff --git a/addons/api/addon/models/host.js b/addons/api/addon/models/host.js
index 451097080..a2e855084 100644
--- a/addons/api/addon/models/host.js
+++ b/addons/api/addon/models/host.js
@@ -1,3 +1,12 @@
import GeneratedHostModel from '../generated/models/host';
+import { fragment } from 'ember-data-model-fragments/attributes';
-export default class HostModel extends GeneratedHostModel {}
+export default class HostModel extends GeneratedHostModel {
+
+ /**
+ * Attributes of this resource, if any, represented as a JSON fragment.
+ * @type {FragmentHostAttributesModel}
+ */
+ @fragment('fragment-host-attributes', { defaultValue: {} }) attributes;
+
+}
diff --git a/addons/api/addon/serializers/host-catalog.js b/addons/api/addon/serializers/host-catalog.js
new file mode 100644
index 000000000..766dff5d6
--- /dev/null
+++ b/addons/api/addon/serializers/host-catalog.js
@@ -0,0 +1,13 @@
+import ApplicationSerializer from './application';
+
+export default class HostCatalogSerializer extends ApplicationSerializer {
+
+ // =attributes
+
+ /**
+ * Serialized the scope ID into the `scope_id` field.
+ * @type {boolean}
+ */
+ serializeScopeID = true;
+
+}
diff --git a/addons/api/addon/serializers/host-set.js b/addons/api/addon/serializers/host-set.js
index 3ce7c7161..697e7748d 100644
--- a/addons/api/addon/serializers/host-set.js
+++ b/addons/api/addon/serializers/host-set.js
@@ -2,6 +2,14 @@ import ApplicationSerializer from './application';
export default class HostSetSerializer extends ApplicationSerializer {
+ // =attributes
+
+ /**
+ * Serialized the scope ID into the `scope_id` field.
+ * @type {boolean}
+ */
+ serializeScopeID = true;
+
// =methods
/**
diff --git a/addons/api/addon/serializers/host.js b/addons/api/addon/serializers/host.js
new file mode 100644
index 000000000..06a7b91d3
--- /dev/null
+++ b/addons/api/addon/serializers/host.js
@@ -0,0 +1,13 @@
+import ApplicationSerializer from './application';
+
+export default class HostSerializer extends ApplicationSerializer {
+
+ // =attributes
+
+ /**
+ * Serialized the scope ID into the `scope_id` field.
+ * @type {boolean}
+ */
+ serializeScopeID = true;
+
+}
diff --git a/addons/api/app/adapters/host-catalog.js b/addons/api/app/adapters/host-catalog.js
new file mode 100644
index 000000000..00197a624
--- /dev/null
+++ b/addons/api/app/adapters/host-catalog.js
@@ -0,0 +1 @@
+export { default } from 'api/adapters/host-catalog';
diff --git a/addons/api/app/models/fragment-host-attributes.js b/addons/api/app/models/fragment-host-attributes.js
new file mode 100644
index 000000000..201efcb7a
--- /dev/null
+++ b/addons/api/app/models/fragment-host-attributes.js
@@ -0,0 +1 @@
+export { default } from 'api/models/fragment-host-attributes';
diff --git a/addons/api/app/serializers/host-catalog.js b/addons/api/app/serializers/host-catalog.js
new file mode 100644
index 000000000..e2818e2c7
--- /dev/null
+++ b/addons/api/app/serializers/host-catalog.js
@@ -0,0 +1 @@
+export { default } from 'api/serializers/host-catalog';
diff --git a/addons/api/app/serializers/host.js b/addons/api/app/serializers/host.js
new file mode 100644
index 000000000..33844fbaf
--- /dev/null
+++ b/addons/api/app/serializers/host.js
@@ -0,0 +1 @@
+export { default } from 'api/serializers/host';
diff --git a/addons/api/tests/unit/adapters/host-catalog-test.js b/addons/api/tests/unit/adapters/host-catalog-test.js
new file mode 100644
index 000000000..02fba945c
--- /dev/null
+++ b/addons/api/tests/unit/adapters/host-catalog-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Adapter | host catalog', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let adapter = this.owner.lookup('adapter:host-catalog');
+ assert.ok(adapter);
+ });
+});
diff --git a/addons/api/tests/unit/adapters/host-set-test.js b/addons/api/tests/unit/adapters/host-set-test.js
index e47c7a7d6..1ab6f7a63 100644
--- a/addons/api/tests/unit/adapters/host-set-test.js
+++ b/addons/api/tests/unit/adapters/host-set-test.js
@@ -6,23 +6,17 @@ module('Unit | Adapter | host set', function(hooks) {
test('it generates correct complete URLs', function (assert) {
assert.expect(2);
- const scopeID = 'o_1';
const hostCatalogID = 'hc_098';
const method = 'my-custom-method';
- const mockSnapshot = {
- adapterOptions: {
- scopeID,
- method
- }
- };
+ const mockSnapshot = { adapterOptions: { method } };
const adapter = this.owner.lookup('adapter:host-set');
// Without hostCatalogID...
let url = adapter.buildURL('host-set', null, mockSnapshot, 'findAll');
- assert.equal(url, '/v1/scopes/o_1/host-sets:my-custom-method');
+ assert.equal(url, '/v1/host-sets:my-custom-method');
// With hostCatalogID...
mockSnapshot.adapterOptions.hostCatalogID = hostCatalogID;
url = adapter.buildURL('host-set', null, mockSnapshot, 'findAll');
- assert.equal(url, '/v1/scopes/o_1/host-catalogs/hc_098/host-sets:my-custom-method');
+ assert.equal(url, '/v1/host-sets:my-custom-method');
});
});
diff --git a/addons/api/tests/unit/adapters/host-test.js b/addons/api/tests/unit/adapters/host-test.js
index 9e019284e..1e45bbee7 100644
--- a/addons/api/tests/unit/adapters/host-test.js
+++ b/addons/api/tests/unit/adapters/host-test.js
@@ -4,25 +4,9 @@ import { setupTest } from 'ember-qunit';
module('Unit | Adapter | host', function(hooks) {
setupTest(hooks);
- test('it generates correct complete URLs', function (assert) {
- assert.expect(2);
- const scopeID = 'o_1';
- const hostCatalogID = 'hc_098';
- const method = 'my-custom-method';
- const mockSnapshot = {
- adapterOptions: {
- scopeID,
- method
- }
- };
- const adapter = this.owner.lookup('adapter:host');
- // Without hostCatalogID...
- let url = adapter.buildURL('host', null, mockSnapshot, 'findAll');
- assert.equal(url, '/v1/scopes/o_1/hosts:my-custom-method');
- // With hostCatalogID...
- mockSnapshot.adapterOptions.hostCatalogID = hostCatalogID;
- url = adapter.buildURL('host', null, mockSnapshot, 'findAll');
- assert.equal(url, '/v1/scopes/o_1/host-catalogs/hc_098/hosts:my-custom-method');
+ test('it exists', function(assert) {
+ let adapter = this.owner.lookup('adapter:host');
+ assert.ok(adapter);
});
});
diff --git a/addons/api/tests/unit/models/host-test.js b/addons/api/tests/unit/models/host-test.js
index d19d98fc3..3cc0a3ad9 100644
--- a/addons/api/tests/unit/models/host-test.js
+++ b/addons/api/tests/unit/models/host-test.js
@@ -10,4 +10,15 @@ module('Unit | Model | host', function(hooks) {
let model = store.createRecord('host', {});
assert.ok(model);
});
+
+ test('it contains attributes', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let model = store.createRecord('host', {
+ type: 'static',
+ attributes: {
+ address: '127.0.0.1'
+ }
+ });
+ assert.equal(model.attributes.address, '127.0.0.1');
+ });
});
diff --git a/addons/api/tests/unit/serializers/host-catalog-test.js b/addons/api/tests/unit/serializers/host-catalog-test.js
new file mode 100644
index 000000000..64a20b044
--- /dev/null
+++ b/addons/api/tests/unit/serializers/host-catalog-test.js
@@ -0,0 +1,23 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Serializer | host catalog', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let serializer = store.serializerFor('host-catalog');
+
+ assert.ok(serializer);
+ });
+
+ test('it serializes records', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let record = store.createRecord('host-catalog', {});
+
+ let serializedRecord = record.serialize();
+
+ assert.ok(serializedRecord);
+ });
+});
diff --git a/addons/api/tests/unit/serializers/host-set-test.js b/addons/api/tests/unit/serializers/host-set-test.js
index 595c6f771..c10cbe915 100644
--- a/addons/api/tests/unit/serializers/host-set-test.js
+++ b/addons/api/tests/unit/serializers/host-set-test.js
@@ -11,6 +11,7 @@ module('Unit | Serializer | host set', function(hooks) {
const record = store.createRecord('host-set', {
name: 'Host Set 1',
description: 'Description',
+ host_catalog_id: '123',
version: 1
});
const snapshot = record._createSnapshot();
@@ -19,6 +20,7 @@ module('Unit | Serializer | host set', function(hooks) {
assert.deepEqual(serializedRecord, {
name: 'Host Set 1',
description: 'Description',
+ host_catalog_id: '123',
version: 1
});
});
diff --git a/addons/api/tests/unit/serializers/host-test.js b/addons/api/tests/unit/serializers/host-test.js
new file mode 100644
index 000000000..c31a5ce4e
--- /dev/null
+++ b/addons/api/tests/unit/serializers/host-test.js
@@ -0,0 +1,23 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Serializer | host', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let serializer = store.serializerFor('host');
+
+ assert.ok(serializer);
+ });
+
+ test('it serializes records', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let record = store.createRecord('host', {});
+
+ let serializedRecord = record.serialize();
+
+ assert.ok(serializedRecord);
+ });
+});
diff --git a/ui/core/app/components/form/host-set/hosts/index.hbs b/ui/core/app/components/form/host-set/hosts/index.hbs
index 1943e26aa..088270a0b 100644
--- a/ui/core/app/components/form/host-set/hosts/index.hbs
+++ b/ui/core/app/components/form/host-set/hosts/index.hbs
@@ -41,7 +41,7 @@
onChange={{fn @toggleHost option.host}} />
{{option.host.name}}
- {{option.host.address}}
+ {{option.host.attributes.address}}
{{/each}}
diff --git a/ui/core/app/components/form/host/index.hbs b/ui/core/app/components/form/host/index.hbs
index 9152b0ba0..2168b7285 100644
--- a/ui/core/app/components/form/host/index.hbs
+++ b/ui/core/app/components/form/host/index.hbs
@@ -47,6 +47,24 @@
{{/if}}
+
+ {{#if @model.errors.name}}
+
+ {{#each @model.errors.name as |error|}}
+ {{error.message}}
+ {{/each}}
+
+ {{/if}}
+
+
+
- this.store.findRecord('host', host.value, { adapterOptions: { scopeID, hostCatalogID } })
+ this.store.findRecord('host', host.value, { reload: true })
))
});
}
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js
index f0dbcc3bd..378b78c7a 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/new.js
@@ -9,10 +9,11 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsNe
* @return {HostSetModel}
*/
model() {
- const scopeModel = this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog');
+ const { id: host_catalog_id } =
+ this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog');
return this.store.createRecord('host-set', {
type: 'static',
- scopeModel
+ host_catalog_id
});
}
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js
index 805112d67..d8bfcfddc 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts.js
@@ -14,8 +14,10 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsRoute
* Loads all hosts under the current host catalog and it's parent project scope.
* @return {Promise{[HostModel]}}
*/
- async model() {
- return this.store.findAll('host', this.adapterOptions());
+ model() {
+ const { id: host_catalog_id } =
+ this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog');
+ return this.store.query('host', { host_catalog_id });
}
// =actions
@@ -40,12 +42,12 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsRoute
async save(host) {
try {
const { isNew } = host;
- await host.save(this.adapterOptions());
- this.refresh();
+ await host.save();
+ await this.transitionTo('scopes.scope.projects.project.host-catalogs.host-catalog.hosts.host', host);
+ await this.refresh();
this.notify.success(
this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
);
- this.transitionTo('scopes.scope.projects.project.host-catalogs.host-catalog.hosts.host', host);
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
@@ -59,7 +61,7 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsRoute
@action
async delete(host) {
try {
- await host.destroyRecord(this.adapterOptions());
+ await host.destroyRecord();
this.refresh();
this.notify.success(this.intl.t('notify.delete-success'));
this.transitionTo('scopes.scope.projects.project.host-catalogs.host-catalog.hosts');
@@ -68,14 +70,4 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsRoute
this.notify.error(error.message, { closeAfter: null });
}
}
-
- /**
- * Configure adapter options using current host catalog scope and it's parent project scope.
- * @return {object}
- */
- adapterOptions() {
- const scopeID = this.modelFor('scopes.scope.projects.project').id;
- const hostCatalogID = this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog').id;
- return { adapterOptions : { scopeID, hostCatalogID } };
- }
}
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js
index 907454d36..2561da8d6 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/host.js
@@ -10,11 +10,7 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsHostR
* @return {HostModel}
*/
async model({ host_id }) {
- const { id: scopeID } = this.modelFor('scopes.scope.projects.project');
- const hostCatalogID = this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog').id;
- return this.store.findRecord('host', host_id, {
- adapterOptions: { scopeID, hostCatalogID }
- });
+ return this.store.findRecord('host', host_id, { reload: true });
}
/**
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js
index 39f90d1bb..d8234bc47 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/new.js
@@ -9,10 +9,11 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostsNewRo
* @return {HostModel}
*/
model() {
- const scopeModel = this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog');
+ const { id: host_catalog_id } =
+ this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog');
return this.store.createRecord('host', {
type: 'static',
- scopeModel
+ host_catalog_id
});
}
diff --git a/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js b/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js
index f1fdc55ec..96e1cd71a 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/targets/target/add-host-sets.js
@@ -13,10 +13,9 @@ export default class ScopesScopeProjectsProjectTargetsTargetAddHostSetsRoute ext
// =methods
/**
- * Empty out any previously loaded host catalogs and host sets.
+ * Empty out any previously loaded host sets.
*/
beforeModel() {
- this.store.unloadAll('host-catalog');
this.store.unloadAll('host-set');
}
@@ -27,12 +26,10 @@ export default class ScopesScopeProjectsProjectTargetsTargetAddHostSetsRoute ext
async model() {
const target =
this.modelFor('scopes.scope.projects.project.targets.target');
- const { scopeID } = target;
- const hostCatalogs =
- await this.store.findAll('host-catalog', { adapterOptions: { scopeID } });
- await all(hostCatalogs.map(({ id: hostCatalogID }) =>
- this.store
- .findAll('host-set', { adapterOptions: { scopeID, hostCatalogID } })
+ const { id: scope_id } = this.modelFor('scopes.scope.projects.project');
+ const hostCatalogs = await this.store.query('host-catalog', { scope_id });
+ await all(hostCatalogs.map(({ id: host_catalog_id }) =>
+ this.store.query('host-set', { host_catalog_id })
));
const hostSets = this.store.peekAll('host-set');
return {
diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs
index 034f2b9a1..2cac93ee4 100644
--- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs
+++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs
@@ -6,6 +6,7 @@
{{t "form.label.name"}}
{{t "form.label.type"}}
{{t "form.label.id"}}
+ {{t "form.label.address"}}
@@ -26,6 +27,9 @@
{{host.id}}
+
+ {{host.attributes.address}}
+
{{/each}}
diff --git a/ui/core/mirage/config.js b/ui/core/mirage/config.js
index a95797a20..754e5a880 100644
--- a/ui/core/mirage/config.js
+++ b/ui/core/mirage/config.js
@@ -147,40 +147,44 @@ export default function() {
// Other resources
// host-catalog
- this.get('/scopes/:scope_id/host-catalogs');
- this.post('/scopes/:scope_id/host-catalogs');
- this.get('/scopes/:scope_id/host-catalogs/:id');
- this.patch('/scopes/:scope_id/host-catalogs/:id');
- this.del('/scopes/:scope_id/host-catalogs/:id');
+ this.get('/host-catalogs', ({ hostCatalogs }, { queryParams: { scope_id: scopeId } }) => {
+ return hostCatalogs.where({ scopeId });
+ });
+ this.post('/host-catalogs');
+ this.get('/host-catalogs/:id');
+ this.patch('/host-catalogs/:id');
+ this.del('/host-catalogs/:id');
// host
- this.get('/scopes/:scope_id/host-catalogs/:hostCatalogId/hosts', function ({ hosts }, { params: { hostCatalogId } }) {
+ this.get('/hosts', function ({ hosts }, { queryParams: { host_catalog_id: hostCatalogId } }) {
return hosts.where({ hostCatalogId });
});
- this.post('/scopes/:scope_id/host-catalogs/:hostCatalogId/hosts', function ({ hosts }, { params: { hostCatalogId } }) {
+ this.post('/hosts', function ({ hostCatalogs, hosts }) {
const attrs = this.normalizedRequestAttrs();
- attrs.hostCatalogId = hostCatalogId;
+ const hostCatalog = hostCatalogs.find(attrs.hostCatalogId);
+ attrs.scopeId = hostCatalog.scope.id;
return hosts.create(attrs);
});
- this.get('/scopes/:scope_id/host-catalogs/:hostCatalogId/hosts/:id');
- this.patch('/scopes/:scope_id/host-catalogs/:hostCatalogId/hosts/:id');
- this.del('/scopes/:scope_id/host-catalogs/:hostCatalogId/hosts/:id');
+ this.get('/hosts/:id');
+ this.patch('/hosts/:id');
+ this.del('/hosts/:id');
// host-set
- this.get('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets', function ({ hostSets }, { params: { hostCatalogId } }) {
+ this.get('/host-sets', function ({ hostSets }, { queryParams: { host_catalog_id: hostCatalogId } }) {
return hostSets.where({ hostCatalogId });
});
- this.post('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets', function ({ hostSets }, { params: { hostCatalogId } }) {
+ this.post('/host-sets', function ({ hostCatalogs, hostSets }) {
const attrs = this.normalizedRequestAttrs();
- attrs.hostCatalogId = hostCatalogId;
+ const hostCatalog = hostCatalogs.find(attrs.hostCatalogId);
+ attrs.scopeId = hostCatalog.scope.id;
return hostSets.create(attrs);
});
- this.get('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets/:id');
- this.patch('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets/:id');
- this.del('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets/:id');
- this.post('/scopes/:scope_id/host-catalogs/:hostCatalogId/host-sets/:idMethod', function ({ hostSets }, { params: { idMethod } }) {
+ this.get('/host-sets/:id');
+ this.patch('/host-sets/:id');
+ this.del('/host-sets/:id');
+ this.post('/host-sets/:idMethod', function ({ hostSets }, { params: { idMethod } }) {
const attrs = this.normalizedRequestAttrs();
const id = idMethod.split(':')[0];
const method = idMethod.split(':')[1];
diff --git a/ui/core/mirage/factories/host-catalog.js b/ui/core/mirage/factories/host-catalog.js
index b6ce98947..1eaed0433 100644
--- a/ui/core/mirage/factories/host-catalog.js
+++ b/ui/core/mirage/factories/host-catalog.js
@@ -5,7 +5,7 @@ export default factory.extend({
withChildren: trait({
afterCreate(hostCatalog, server) {
- const scope = hostCatalog.scope;
+ const { scope } = hostCatalog;
const hosts = server.createList('host', 10, { scope, hostCatalog });
server.createList('host-set', 3, { scope, hostCatalog, hosts });
}
diff --git a/ui/core/mirage/factories/target.js b/ui/core/mirage/factories/target.js
index 7c74806a6..a96e15556 100644
--- a/ui/core/mirage/factories/target.js
+++ b/ui/core/mirage/factories/target.js
@@ -13,7 +13,12 @@ export default factory.extend({
afterCreate(target, server) {
let randomlySelectedHostSets;
randomlySelectedHostSets = server.schema.hostSets
- .where(item => item.scope.id === target.scope.id).models
+ // BLERG: fun fact, for no reason at all, the element passed
+ // into a where function is not a full model instance, as you might
+ // expect at this level of abstraction, but appears to be a serialized
+ // representation of the model instance. It's very confusing since
+ // the result set of `where` _is a collection of model instances_.
+ .where(hostSet => hostSet.scopeId === target.scope.id).models
.filter(() => randomBoolean(hostSetChance));
target.update({hostSets: randomlySelectedHostSets});
}
diff --git a/ui/core/mirage/generated/factories/host.js b/ui/core/mirage/generated/factories/host.js
index 2d6925e82..e6fccf602 100644
--- a/ui/core/mirage/generated/factories/host.js
+++ b/ui/core/mirage/generated/factories/host.js
@@ -12,6 +12,6 @@ export default Factory.extend({
created_time: () => date.recent(),
updated_time: () => date.recent(),
version: () => random.number(),
- address: () => internet.ipv6(),
+ attributes: () => { return { address: internet.ipv6() } },
});
diff --git a/ui/core/mirage/models/host-catalog.js b/ui/core/mirage/models/host-catalog.js
new file mode 100644
index 000000000..08b1f5ad3
--- /dev/null
+++ b/ui/core/mirage/models/host-catalog.js
@@ -0,0 +1,7 @@
+import { Model, belongsTo } from 'ember-cli-mirage';
+
+export default Model.extend({
+
+ scope: belongsTo()
+
+});
diff --git a/ui/core/mirage/models/host-set.js b/ui/core/mirage/models/host-set.js
index 3aa8fbf7e..5a579e119 100644
--- a/ui/core/mirage/models/host-set.js
+++ b/ui/core/mirage/models/host-set.js
@@ -2,6 +2,7 @@ import { Model, belongsTo, hasMany } from 'ember-cli-mirage';
export default Model.extend({
+ scope: belongsTo(),
target: belongsTo(),
hostCatalog: belongsTo(),
hosts: hasMany()
diff --git a/ui/core/mirage/models/host.js b/ui/core/mirage/models/host.js
index 89aba81e6..b9a941a4f 100644
--- a/ui/core/mirage/models/host.js
+++ b/ui/core/mirage/models/host.js
@@ -2,6 +2,7 @@ import { Model, belongsTo } from 'ember-cli-mirage';
export default Model.extend({
+ scope: belongsTo(),
hostCatalog: belongsTo()
});
diff --git a/ui/core/mirage/scenarios/default.js b/ui/core/mirage/scenarios/default.js
index c878699ef..1524a7647 100644
--- a/ui/core/mirage/scenarios/default.js
+++ b/ui/core/mirage/scenarios/default.js
@@ -24,8 +24,7 @@ export default function(server) {
// Other resources
server.schema.scopes.where({type: 'project'}).models.forEach(scope => {
- const scopePojo = { id: scope.id, type: scope.type };
- server.createList('host-catalog', 2, { scope: scopePojo }, 'withChildren');
+ server.createList('host-catalog', 2, { scope }, 'withChildren');
server.createList('target', 2, { scope }, 'withRandomHostSets');
});
diff --git a/ui/core/mirage/serializers/host-catalog.js b/ui/core/mirage/serializers/host-catalog.js
index e7b237047..34277f96e 100644
--- a/ui/core/mirage/serializers/host-catalog.js
+++ b/ui/core/mirage/serializers/host-catalog.js
@@ -1,5 +1,22 @@
import ApplicationSerializer from './application';
+import { underscore } from '@ember/string';
export default ApplicationSerializer.extend({
- modelName: 'host-catalog'
+ modelName: 'host-catalog',
+
+ keyForRelationshipId(relationshipName) {
+ return `${this._container.inflector.singularize(
+ underscore(relationshipName)
+ )}_id`;
+ },
+
+ _hashForModel(model) {
+ const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments);
+ json.scope = {
+ id: model.scope.id,
+ type: model.scope.type
+ };
+ return json;
+ }
+
});
diff --git a/ui/core/mirage/serializers/host-set.js b/ui/core/mirage/serializers/host-set.js
index bd680326e..16d665375 100644
--- a/ui/core/mirage/serializers/host-set.js
+++ b/ui/core/mirage/serializers/host-set.js
@@ -10,10 +10,20 @@ export default ApplicationSerializer.extend({
)}_ids`;
},
+ keyForRelationshipId(relationshipName) {
+ return `${this._container.inflector.singularize(
+ underscore(relationshipName)
+ )}_id`;
+ },
+
_hashForModel(model) {
const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments);
json.host_ids = model.hostIds;
json.host_catalog_id = model.hostCatalogId;
+ json.scope = {
+ id: model.scope.id,
+ type: model.scope.type
+ };
return json;
}
diff --git a/ui/core/mirage/serializers/host.js b/ui/core/mirage/serializers/host.js
index ccd3994ca..4fb0353b4 100644
--- a/ui/core/mirage/serializers/host.js
+++ b/ui/core/mirage/serializers/host.js
@@ -1,5 +1,22 @@
import ApplicationSerializer from './application';
+import { underscore } from '@ember/string';
export default ApplicationSerializer.extend({
- modelName: 'host'
+ modelName: 'host',
+
+ keyForRelationshipId(relationshipName) {
+ return `${this._container.inflector.singularize(
+ underscore(relationshipName)
+ )}_id`;
+ },
+
+ _hashForModel(model) {
+ const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments);
+ json.scope = {
+ id: model.scope.id,
+ type: model.scope.type
+ };
+ return json;
+ }
+
});
diff --git a/ui/core/tests/acceptance/bread-crumbs-test.js b/ui/core/tests/acceptance/bread-crumbs-test.js
index 9400e9dbe..4dc48c832 100644
--- a/ui/core/tests/acceptance/bread-crumbs-test.js
+++ b/ui/core/tests/acceptance/bread-crumbs-test.js
@@ -45,12 +45,7 @@ module('Acceptance | breadcrumbs', function (hooks) {
user = this.server.create('user', { scope: orgScope });
role = this.server.create('role', { scope: orgScope });
group = this.server.create('group', { scope: orgScope });
- hostCatalog = this.server.create('host-catalog', {
- scope: {
- id: project.id,
- type: project.type
- }
- });
+ hostCatalog = this.server.create('host-catalog', { scope: getProjectScope() });
projectsURL = `/scopes/${orgScope.id}/projects`;
newProjectURL = `${projectsURL}/new`;
diff --git a/ui/core/tests/acceptance/host-catalogs-test.js b/ui/core/tests/acceptance/host-catalogs-test.js
index 3b79331c9..f88332113 100644
--- a/ui/core/tests/acceptance/host-catalogs-test.js
+++ b/ui/core/tests/acceptance/host-catalogs-test.js
@@ -36,16 +36,13 @@ module('Acceptance | host catalogs', function (hooks) {
// Setup Mirage mock resources for this test
instances.scopes.global = this.server.create('scope', { id: 'global' });
instances.scopes.org = this.server.create('scope', { type: 'org',
- scope: { id: instances.scopes.global.id, type: instances.scopes.global.type }
+ scope: { id: 'global', type: 'global' }
});
instances.scopes.project = this.server.create('scope', { type: 'project',
- scope: { id: instances.scopes.org.id, type: instances.scopes.org.type }
+ scope: { id: instances.scopes.org.id, type: 'org' }
});
instances.hostCatalog = this.server.create('host-catalog', {
- scope: {
- id: instances.scopes.project.id,
- type: instances.scopes.project.type
- }
+ scope: instances.scopes.project
});
// Generate route URLs for resources
@@ -124,7 +121,7 @@ module('Acceptance | host catalogs', function (hooks) {
test('errors are displayed when save host catalog fails', async function (assert) {
assert.expect(1);
- this.server.patch('/scopes/:scope_id/host-catalogs/:id', () => {
+ this.server.patch('/host-catalogs/:id', () => {
return new Response(
490,
{},
@@ -149,7 +146,7 @@ module('Acceptance | host catalogs', function (hooks) {
test('errors are displayed when delete host catalog fails', async function (assert) {
assert.expect(1);
- this.server.del('/scopes/:scope_id/host-catalogs/:id', () => {
+ this.server.del('/host-catalogs/:id', () => {
return new Response(
490,
{},
@@ -173,7 +170,7 @@ module('Acceptance | host catalogs', function (hooks) {
test('saving a new host catalog with invalid fields displays error messages', async function (assert) {
assert.expect(2);
- this.server.post('/scopes/:scope_id/host-catalogs', () => {
+ this.server.post('/host-catalogs', () => {
return new Response(
400,
{},
@@ -211,7 +208,7 @@ module('Acceptance | host catalogs', function (hooks) {
test('saving an existing host catalog with invalid fields displays error messages', async function (assert) {
assert.expect(2);
- this.server.patch('/scopes/:scope_id/host-catalogs/:id', () => {
+ this.server.patch('/host-catalogs/:id', () => {
return new Response(
400,
{},