diff --git a/addons/api/addon/models/host-catalog.js b/addons/api/addon/models/host-catalog.js
index 8a0a64bd5..ec34b50e3 100644
--- a/addons/api/addon/models/host-catalog.js
+++ b/addons/api/addon/models/host-catalog.js
@@ -1,8 +1,12 @@
import GeneratedHostCatalogModel from '../generated/models/host-catalog';
+export const types = ['aws', 'azure'];
+
export default class HostCatalogModel extends GeneratedHostCatalogModel {
+ // =attributes
+
/**
- * Returns if the host-catalog is static type or not.
+ * True if the host catalog is static.
* @type {boolean}
*/
get isStatic() {
@@ -10,7 +14,7 @@ export default class HostCatalogModel extends GeneratedHostCatalogModel {
}
/**
- * Returns if the host-catalog is a plugin or not.
+ * True if the host catalog is a plugin.
* @type {boolean}
*/
get isPlugin() {
@@ -18,7 +22,15 @@ export default class HostCatalogModel extends GeneratedHostCatalogModel {
}
/**
- * Returns if host-catalog plugin is AWS or not
+ * True if the host catalog is an unknown type.
+ * @type {boolean}
+ */
+ get isUnknown() {
+ return this.isPlugin && !types.includes(this.plugin.name);
+ }
+
+ /**
+ * True if host catalog plugin type is AWS.
* @type {boolean}
*/
get isAWS() {
@@ -26,23 +38,27 @@ export default class HostCatalogModel extends GeneratedHostCatalogModel {
}
/**
- * Return if host-catalog plugin is Azure or not.
+ * True if host catalog plugin type is Azure.
* @type {boolean}
*/
get isAzure() {
return this.compositeType === 'azure';
}
- /** If host-catalog is a plugins returns its name,
- * otherwise returns the host-catalog type
+ /**
+ * If host catalog is a plugin return `plugin.name`,
+ * otherwise return the host catalog type.
* @type {string}
*/
get compositeType() {
- return this.isPlugin ? this.plugin.name : this.type;
+ if (this.isUnknown) return 'unknown';
+ if (this.isPlugin) return this.plugin.name;
+ return 'static';
}
/**
- * Sets type, if type is different than static, sets plugin name to type
+ * Sets `type`. If type is different than `static`, sets `type` to `plugin`
+ * and `plugin.name` to the specified type.
*/
set compositeType(type) {
if (type === 'static') {
diff --git a/addons/api/mirage/factories/host-catalog.js b/addons/api/mirage/factories/host-catalog.js
index 3179f2c99..4cd7423ae 100644
--- a/addons/api/mirage/factories/host-catalog.js
+++ b/addons/api/mirage/factories/host-catalog.js
@@ -1,7 +1,14 @@
import factory from '../generated/factories/host-catalog';
import { trait } from 'ember-cli-mirage';
import permissions from '../helpers/permissions';
-import { datatype, address } from 'faker';
+import { datatype, address, random } from 'faker';
+
+const types = ['static', 'plugin'];
+// Represents known plugin types, except "foobar" which models the possibility
+// of receiving an _unknown_ type, which the UI must handle gracefully.
+const pluginTypes = ['aws', 'azure', 'foobar'];
+
+let pluginTypeCounter = 1;
export default factory.extend({
authorized_actions: () =>
@@ -17,6 +24,22 @@ export default factory.extend({
'host-sets': ['create', 'list'],
};
},
+
+ id: (i) => `host-catalog-id-${i}`,
+
+ // Cycle through available types
+ type: (i) => types[i % types.length],
+
+ plugin: function (i) {
+ if (this.type === 'plugin') {
+ return {
+ id: `plugin-id-${i}`,
+ name: pluginTypes[pluginTypeCounter++ % pluginTypes.length],
+ description: random.words(),
+ };
+ }
+ },
+
attributes() {
switch (this.plugin?.name) {
case 'aws':
diff --git a/addons/api/mirage/generated/factories/host-catalog.js b/addons/api/mirage/generated/factories/host-catalog.js
index fa8135226..36d5e64c6 100644
--- a/addons/api/mirage/generated/factories/host-catalog.js
+++ b/addons/api/mirage/generated/factories/host-catalog.js
@@ -5,19 +5,10 @@ import { random, date, datatype } from 'faker';
* GeneratedHostCatalogModelFactory
*/
export default Factory.extend({
- type: () => random.arrayElement(['static', 'plugin']),
+ type: 'static',
name: () => random.words(),
description: () => random.words(),
created_time: () => date.recent(),
updated_time: () => date.recent(),
disabled: () => datatype.boolean(),
- plugin: function (i) {
- if (this.type == 'plugin') {
- return {
- id: `pl_${datatype.hexaDecimal(5)}`,
- name: i % 2 ? 'aws' : 'azure',
- description: random.words(),
- };
- }
- },
});
diff --git a/addons/api/mirage/scenarios/default.js b/addons/api/mirage/scenarios/default.js
index 51175f672..ceb61b566 100644
--- a/addons/api/mirage/scenarios/default.js
+++ b/addons/api/mirage/scenarios/default.js
@@ -46,7 +46,7 @@ export default function (server) {
// Other resources
server.schema.scopes.where({ type: 'project' }).models.forEach((scope) => {
- server.createList('host-catalog', 4, { scope }, 'withChildren');
+ server.createList('host-catalog', 8, { scope }, 'withChildren');
server.createList('credential-store', 3, { scope }, 'withAssociations');
server.createList('target', 2, { scope }, 'withAssociations');
// Sessions have target data. Create it after targets.
diff --git a/addons/api/tests/unit/models/host-catalog-test.js b/addons/api/tests/unit/models/host-catalog-test.js
index 7a8a77147..fb2c2cf51 100644
--- a/addons/api/tests/unit/models/host-catalog-test.js
+++ b/addons/api/tests/unit/models/host-catalog-test.js
@@ -10,29 +10,52 @@ module('Unit | Model | host catalog', function (hooks) {
assert.ok(model);
});
- test('it has isStatic function and returns the expected values', async function (assert) {
+ test('it has isStatic property and returns the expected values', async function (assert) {
assert.expect(3);
const store = this.owner.lookup('service:store');
- const modelA = store.createRecord('host-catalog', { type: 'static' });
- const modelB = store.createRecord('host-catalog', { type: 'plugin' });
- assert.equal(typeof modelA.isStatic, 'boolean');
- assert.true(modelA.isStatic);
+ const modelA = store.createRecord('host-catalog', { compositeType: 'aws' });
+ const modelB = store.createRecord('host-catalog', {
+ compositeType: 'foobar',
+ });
+ const modelC = store.createRecord('host-catalog', {
+ compositeType: 'static',
+ });
+ assert.false(modelA.isStatic);
assert.false(modelB.isStatic);
+ assert.true(modelC.isStatic);
});
- test('it has isPlugin function and returns the expected values', async function (assert) {
- assert.expect(3);
+ test('it has isPlugin property and returns the expected values', async function (assert) {
+ assert.expect(2);
const store = this.owner.lookup('service:store');
- const modelPlugin = store.createRecord('host-catalog', { type: 'plugin' });
- const modelStatic = store.createRecord('host-catalog', { type: 'static' });
- assert.equal(typeof modelPlugin.isPlugin, 'boolean');
+ const modelPlugin = store.createRecord('host-catalog', {
+ compositeType: 'aws',
+ });
+ const modelStatic = store.createRecord('host-catalog', {
+ compositeType: 'static',
+ });
assert.true(modelPlugin.isPlugin);
assert.false(modelStatic.isPlugin);
});
- test('it has isAWS function and returns the expected values', async function (assert) {
+ test('it has isUnknown property and returns the expected values', async function (assert) {
assert.expect(3);
const store = this.owner.lookup('service:store');
+ const modelA = store.createRecord('host-catalog', {
+ compositeType: 'static',
+ });
+ const modelB = store.createRecord('host-catalog', { compositeType: 'aws' });
+ const modelC = store.createRecord('host-catalog', {
+ compositeType: 'no-such-type',
+ });
+ assert.false(modelA.isUnknown);
+ assert.false(modelB.isUnknown);
+ assert.true(modelC.isUnknown);
+ });
+
+ test('it has isAWS property and returns the expected values', async function (assert) {
+ assert.expect(2);
+ const store = this.owner.lookup('service:store');
const modelAws = store.createRecord('host-catalog', {
type: 'plugin',
plugin: { name: 'aws' },
@@ -40,13 +63,12 @@ module('Unit | Model | host catalog', function (hooks) {
const modelRandom = store.createRecord('host-catalog', {
plugin: { name: 'random' },
});
- assert.equal(typeof modelAws.isAWS, 'boolean');
assert.true(modelAws.isAWS);
assert.false(modelRandom.isAWS);
});
- test('it has isAzure function and return the expected values', async function (assert) {
- assert.expect(3);
+ test('it has isAzure property and return the expected values', async function (assert) {
+ assert.expect(2);
const store = this.owner.lookup('service:store');
const modelAzure = store.createRecord('host-catalog', {
type: 'plugin',
@@ -55,7 +77,6 @@ module('Unit | Model | host catalog', function (hooks) {
const modelRandom = store.createRecord('host-catalog', {
plugin: { name: 'random' },
});
- assert.equal(typeof modelAzure.isAzure, 'boolean');
assert.true(modelAzure.isAzure);
assert.false(modelRandom.isAzure);
});
@@ -63,16 +84,20 @@ module('Unit | Model | host catalog', function (hooks) {
test('get compositeType returns expected values', async function (assert) {
assert.expect(3);
const store = this.owner.lookup('service:store');
- const modelPlugin = store.createRecord('host-catalog', {
- type: 'plugin',
- plugin: { name: 'Test name' },
- });
- const modelStatic = store.createRecord('host-catalog', {
+ const modelA = store.createRecord('host-catalog', {
type: 'static',
});
- assert.equal(typeof modelPlugin.compositeType, 'string');
- assert.equal(modelPlugin.compositeType, 'Test name');
- assert.equal(modelStatic.compositeType, 'static');
+ const modelB = store.createRecord('host-catalog', {
+ type: 'plugin',
+ plugin: { name: 'aws' },
+ });
+ const modelC = store.createRecord('host-catalog', {
+ type: 'plugin',
+ plugin: { name: 'no-such-type' },
+ });
+ assert.equal(modelA.compositeType, 'static');
+ assert.equal(modelB.compositeType, 'aws');
+ assert.equal(modelC.compositeType, 'unknown');
});
test('set compositeType sets expected values', async function (assert) {
@@ -84,7 +109,6 @@ module('Unit | Model | host catalog', function (hooks) {
const modelStatic = store.createRecord('host-catalog', {
compositeType: 'static',
});
-
assert.equal(modelPlugin.type, 'plugin');
assert.equal(modelPlugin.plugin.name, 'aws');
assert.equal(modelStatic.type, 'static');
diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml
index f787cf133..d1de853d6 100644
--- a/addons/core/translations/resources/en-us.yaml
+++ b/addons/core/translations/resources/en-us.yaml
@@ -85,6 +85,7 @@ host-catalog:
delete: Delete Host Catalog
types:
static: Static
+ unknown: Unknown
host-set:
title: Host Set
title_plural: Host Sets
@@ -111,6 +112,7 @@ host-set:
description: No hosts available for selection.
types:
static: Static
+ unknown: Unknown
host:
title: Host
title_plural: Hosts
@@ -130,6 +132,7 @@ host:
delete: Delete Host
types:
static: Static
+ unknown: Unknown
session:
title: Session
title_plural: Sessions
diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
index 7765915cd..b2280bc1a 100644
--- a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs
@@ -59,7 +59,19 @@
{{#if hostCatalog.isStatic}}
{{t
- (concat 'resources.host-catalog.types.' hostCatalog.type)
+ (concat
+ 'resources.host-catalog.types.'
+ hostCatalog.compositeType
+ )
+ }}
+
+ {{else if hostCatalog.isUnknown}}
+
+ {{t
+ (concat
+ 'resources.host-catalog.types.'
+ hostCatalog.compositeType
+ )
}}
{{else}}