Merge pull request #929 from hashicorp/chore-unknown-type
Add support for "unknown" dynamic host catalogs
This commit is contained in:
9 files changed
+144
-47
No files matched your search
@@ -0,0 +1,16 @@
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
* Provides abilities for host catalogs.
|
||||
*/
|
||||
export default class HostCatalogAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" host catalog types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -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') {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/host-catalog';
|
||||
@@ -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':
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -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.
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -85,6 +85,9 @@ host-catalog:
|
||||
delete: Delete Host Catalog
|
||||
types:
|
||||
static: Static
|
||||
unknown: Unknown
|
||||
aws: AWS
|
||||
azure: Azure
|
||||
host-set:
|
||||
title: Host Set
|
||||
title_plural: Host Sets
|
||||
@@ -111,6 +114,9 @@ host-set:
|
||||
description: No hosts available for selection.
|
||||
types:
|
||||
static: Static
|
||||
unknown: Unknown
|
||||
aws: AWS
|
||||
azure: Azure
|
||||
host:
|
||||
title: Host
|
||||
title_plural: Hosts
|
||||
@@ -130,6 +136,9 @@ host:
|
||||
delete: Delete Host
|
||||
types:
|
||||
static: Static
|
||||
unknown: Unknown
|
||||
aws: AWS
|
||||
azure: Azure
|
||||
session:
|
||||
title: Session
|
||||
title_plural: Sessions
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
{{#each @model as |hostCatalog|}}
|
||||
<body.row as |row|>
|
||||
<row.headerCell>
|
||||
{{#if (can 'read model' hostCatalog)}}
|
||||
{{#if (can 'read host-catalog' hostCatalog)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.host-catalogs.host-catalog'
|
||||
@model={{hostCatalog.id}}
|
||||
@@ -59,7 +59,19 @@
|
||||
{{#if hostCatalog.isStatic}}
|
||||
<Rose::Badge>
|
||||
{{t
|
||||
(concat 'resources.host-catalog.types.' hostCatalog.type)
|
||||
(concat
|
||||
'resources.host-catalog.types.'
|
||||
hostCatalog.compositeType
|
||||
)
|
||||
}}
|
||||
</Rose::Badge>
|
||||
{{else if hostCatalog.isUnknown}}
|
||||
<Rose::Badge>
|
||||
{{t
|
||||
(concat
|
||||
'resources.host-catalog.types.'
|
||||
hostCatalog.compositeType
|
||||
)
|
||||
}}
|
||||
</Rose::Badge>
|
||||
{{else}}
|
||||
@@ -70,7 +82,12 @@
|
||||
'-color-16'
|
||||
}}
|
||||
>
|
||||
{{hostCatalog.compositeType}}
|
||||
{{t
|
||||
(concat
|
||||
'resources.host-catalog.types.'
|
||||
hostCatalog.compositeType
|
||||
)
|
||||
}}
|
||||
</Rose::Badge>
|
||||
{{/if}}
|
||||
</row.cell>
|
||||
|
||||
Reference in new issue
Block a user