diff --git a/ui/core/app/router.js b/ui/core/app/router.js
index af71f6132..91a8aceca 100644
--- a/ui/core/app/router.js
+++ b/ui/core/app/router.js
@@ -31,7 +31,9 @@ Router.map(function () {
this.route('project', { path: ':project_id' }, function() {
this.route('host-catalogs', function() {
this.route('new');
- this.route('host-catalog', { path: ':host_catalog_id' }, function() {});
+ this.route('host-catalog', { path: ':host_catalog_id' }, function() {
+ this.route('host-sets');
+ });
});
});
this.route('new');
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js
new file mode 100644
index 000000000..c4440322e
--- /dev/null
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.js
@@ -0,0 +1,13 @@
+import Route from '@ember/routing/route';
+
+export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsRoute extends Route {
+ /**
+ * Loads all host-sets under the current scope and host catalog.
+ * @return {Promise{[HostSetModel]}}
+ */
+ async model() {
+ const scopeID = this.modelFor('scopes.scope.projects.project').id;
+ const hostCatalogID = this.modelFor('scopes.scope.projects.project.host-catalogs.host-catalog').id;
+ return this.store.findAll('host-set', { adapterOptions: { scopeID, hostCatalogID } });
+ }
+}
diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs
index d66e83390..529b61a34 100644
--- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs
+++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog.hbs
@@ -1,3 +1,26 @@
-{{title @model.displayName}}
+
-{{outlet}}
+
+
+
+
+
+ {{t "resources.host-catalog"}}
+
+
+
+
+
+ {{t 'titles.details'}}
+
+
+ {{t 'titles.host-sets'}}
+
+
+
+
+
+ {{outlet}}
+
+
+
diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs
new file mode 100644
index 000000000..300abe57b
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets.hbs
@@ -0,0 +1,25 @@
+
+
+
+ {{t "form.label.name"}}
+ {{t "form.label.type"}}
+ {{t "form.label.id"}}
+
+
+
+ {{#each @model as |hostSet|}}
+
+
+ {{hostSet.displayName}}
+ {{hostSet.description}}
+
+
+ {{hostSet.type}}
+
+
+ {{hostSet.id}}
+
+
+ {{/each}}
+
+
\ No newline at end of file
diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs
index cb0a4a0cf..0a979afcf 100644
--- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs
+++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/index.hbs
@@ -1,35 +1,13 @@
-
-
-
-
-
-
-
- {{t "resources.host-catalog"}}
-
-
-
-
-
- {{t 'titles.details'}}
-
-
-
-
-
-
-
-
- {{t 'actions.delete'}}
-
-
-
-
+
+
+
+ {{t 'actions.delete'}}
+
\ No newline at end of file
diff --git a/ui/core/tests/acceptance/host-sets-test.js b/ui/core/tests/acceptance/host-sets-test.js
new file mode 100644
index 000000000..4f398902f
--- /dev/null
+++ b/ui/core/tests/acceptance/host-sets-test.js
@@ -0,0 +1,78 @@
+import { module, test } from 'qunit';
+import { visit, currentURL } from '@ember/test-helpers';
+import { setupApplicationTest } from 'ember-qunit';
+import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
+import a11yAudit from 'ember-a11y-testing/test-support/audit';
+import {
+ authenticateSession,
+ // These are left here intentionally for future reference.
+ //currentSession,
+ //invalidateSession,
+} from 'ember-simple-auth/test-support';
+
+module('Acceptance | host sets', function (hooks) {
+ setupApplicationTest(hooks);
+ setupMirage(hooks);
+
+ const instances = {
+ scopes: {
+ global: null,
+ org: null,
+ project: null,
+ hostCatalog: null
+ },
+ hostSet: null
+ };
+ const urls = {
+ orgScope: null,
+ projects: null,
+ project: null,
+ hostCatalogs: null,
+ hostCatalog: null,
+ hostSets: null
+ };
+
+ hooks.beforeEach(function () {
+ // 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 }
+ });
+ instances.scopes.project = this.server.create('scope', { type: 'project',
+ scope: { id: instances.scopes.org.id, type: instances.scopes.org.type }
+ });
+ instances.scopes.hostCatalog = this.server.create('host-catalog', {
+ scope: {
+ id: instances.scopes.project.id,
+ type: instances.scopes.project.type
+ }
+ });
+
+ instances.hostSet = this.server.create('host-set', {
+ scope: {
+ id: instances.scopes.project.id,
+ type: instances.scopes.project.type
+ },
+ hostCatalog: {
+ id: instances.scopes.hostCatalog.id,
+ type: instances.scopes.hostCatalog.type
+ }
+ });
+
+ // Generate route URLs for resources
+ urls.orgScope = `/scopes/${instances.scopes.org.id}`;
+ urls.projects = `${urls.orgScope}/projects`;
+ urls.project = `${urls.projects}/${instances.scopes.hostCatalog.scope.id}`;
+ urls.hostCatalogs = `${urls.project}/host-catalogs`;
+ urls.hostCatalog = `${urls.hostCatalogs}/${instances.scopes.hostCatalog.id}`;
+ urls.hostSets = `${urls.hostCatalog}/host-sets`;
+ });
+
+ test('visiting host sets', async function (assert) {
+ assert.expect(1);
+ authenticateSession();
+ await visit(urls.hostSets);
+ await a11yAudit();
+ assert.equal(currentURL(), urls.hostSets);
+ });
+});
diff --git a/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js
new file mode 100644
index 000000000..9cdd5b757
--- /dev/null
+++ b/ui/core/tests/unit/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets-test.js
@@ -0,0 +1,11 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | scopes/scope/projects/project/host-catalogs/host-catalog/host-sets', function(hooks) {
+ setupTest(hooks);
+
+ test('it exists', function(assert) {
+ let route = this.owner.lookup('route:scopes/scope/projects/project/host-catalogs/host-catalog/host-sets');
+ assert.ok(route);
+ });
+});
diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml
index 10e48f67c..2f2e4df01 100644
--- a/ui/core/translations/en-us.yaml
+++ b/ui/core/translations/en-us.yaml
@@ -33,6 +33,7 @@ resources:
host-catalogs: Host Catalogs
auth-method: Auth Method
auth-methods: Auth Methods
+ host-sets: Host Sets
titles:
iam: IAM
new: New
@@ -51,6 +52,7 @@ titles:
grants: Permissions
new-grant: New Grant
principals: Principals
+ host-sets: Host Sets
descriptions:
host-catalogs: Overview of collections of hosts and host sets.
empty-set: There are no items to display yet. You may be able to add items or try back later.