Commit 24eadd26 authored by Buck Doyle's avatar Buck Doyle
Browse files

Add massaged results of class codemod

Manual interventions:
• decorators on the same line for service and controller
  injections and most computed property macros
• preserving import order when possible, both per-line
  and intra-line
• moving new imports to the bottom
• removal of classic decorator for trivial cases
• conversion of init to constructor when appropriate
parent 9ccec0af
Showing with 188 additions and 152 deletions
+188 -152
......@@ -15,6 +15,9 @@ module.exports = {
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
legacyDecorators: true,
},
},
plugins: [
'ember'
......
......@@ -2,19 +2,23 @@ import { Ability } from 'ember-can';
import { inject as service } from '@ember/service';
import { computed, get } from '@ember/object';
import { equal, not } from '@ember/object/computed';
import classic from 'ember-classic-decorator';
export default Ability.extend({
system: service(),
token: service(),
@classic
export default class Abstract extends Ability {
@service system;
@service token;
bypassAuthorization: not('token.aclEnabled'),
selfTokenIsManagement: equal('token.selfToken.type', 'management'),
@not('token.aclEnabled') bypassAuthorization;
@equal('token.selfToken.type', 'management') selfTokenIsManagement;
activeNamespace: computed('system.activeNamespace.name', function() {
@computed('system.activeNamespace.name')
get activeNamespace() {
return this.get('system.activeNamespace.name') || 'default';
}),
}
rulesForActiveNamespace: computed('activeNamespace', 'token.selfTokenPolicies.[]', function() {
@computed('activeNamespace', 'token.selfTokenPolicies.[]')
get rulesForActiveNamespace() {
let activeNamespace = this.activeNamespace;
return (this.get('token.selfTokenPolicies') || []).toArray().reduce((rules, policy) => {
......@@ -28,7 +32,7 @@ export default Ability.extend({
return rules;
}, []);
}),
}
// Chooses the closest namespace as described at the bottom here:
// https://www.nomadproject.io/guides/security/acl.html#namespace-rules
......@@ -67,5 +71,5 @@ export default Ability.extend({
} else if (namespaceNames.includes('default')) {
return 'default';
}
},
});
}
}
......@@ -2,13 +2,15 @@ import AbstractAbility from './abstract';
import { computed, get } from '@ember/object';
import { or } from '@ember/object/computed';
export default AbstractAbility.extend({
canExec: or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportExec'),
export default class Allocation extends AbstractAbility {
@or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportExec')
canExec;
policiesSupportExec: computed('rulesForActiveNamespace.@each.capabilities', function() {
@computed('rulesForActiveNamespace.@each.capabilities')
get policiesSupportExec() {
return this.rulesForActiveNamespace.some(rules => {
let capabilities = get(rules, 'Capabilities') || [];
return capabilities.includes('alloc-exec');
});
}),
});
}
}
......@@ -2,12 +2,14 @@ import AbstractAbility from './abstract';
import { computed, get } from '@ember/object';
import { or } from '@ember/object/computed';
export default AbstractAbility.extend({
export default class Client extends AbstractAbility {
// Map abilities to policy options (which are coarse for nodes)
// instead of specific behaviors.
canWrite: or('bypassAuthorization', 'selfTokenIsManagement', 'policiesIncludeNodeWrite'),
@or('bypassAuthorization', 'selfTokenIsManagement', 'policiesIncludeNodeWrite')
canWrite;
policiesIncludeNodeWrite: computed('token.selfTokenPolicies.[]', function() {
@computed('token.selfTokenPolicies.[]')
get policiesIncludeNodeWrite() {
// For each policy record, extract the Node policy
const policies = (this.get('token.selfTokenPolicies') || [])
.toArray()
......@@ -16,5 +18,5 @@ export default AbstractAbility.extend({
// Node write is allowed if any policy allows it
return policies.some(policy => policy === 'write');
}),
});
}
}
......@@ -2,13 +2,15 @@ import AbstractAbility from './abstract';
import { computed, get } from '@ember/object';
import { or } from '@ember/object/computed';
export default AbstractAbility.extend({
canRun: or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportRunning'),
export default class Job extends AbstractAbility {
@or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportRunning')
canRun;
policiesSupportRunning: computed('rulesForActiveNamespace.@each.capabilities', function() {
@computed('rulesForActiveNamespace.@each.capabilities')
get policiesSupportRunning() {
return this.rulesForActiveNamespace.some(rules => {
let capabilities = get(rules, 'Capabilities') || [];
return capabilities.includes('submit-job');
});
}),
});
}
}
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
pathForType: () => 'agent/members',
export default class Agent extends ApplicationAdapter {
pathForType = () => 'agent/members';
urlForFindRecord() {
const [, ...args] = arguments;
return this.urlForFindAll(...args);
},
});
}
}
......@@ -4,20 +4,23 @@ import RESTAdapter from 'ember-data/adapters/rest';
import codesForError from '../utils/codes-for-error';
import removeRecord from '../utils/remove-record';
import { default as NoLeaderError, NO_LEADER } from '../utils/no-leader-error';
import classic from 'ember-classic-decorator';
export const namespace = 'v1';
export default RESTAdapter.extend({
@classic
export default class Application extends RESTAdapter {
// TODO: This can be removed once jquery-integration is turned off for
// the entire app.
useFetch: true,
useFetch = true;
namespace,
namespace = namespace;
system: service(),
token: service(),
@service system;
@service token;
headers: computed('token.secret', function() {
@computed('token.secret')
get headers() {
const token = this.get('token.secret');
if (token) {
return {
......@@ -26,17 +29,17 @@ export default RESTAdapter.extend({
}
return;
}),
}
handleResponse(status, headers, payload) {
if (status === 500 && payload === NO_LEADER) {
return new NoLeaderError();
}
return this._super(...arguments);
},
return super.handleResponse(...arguments);
}
findAll() {
return this._super(...arguments).catch(error => {
return super.findAll(...arguments).catch(error => {
const errorCodes = codesForError(error);
const isNotImplemented = errorCodes.includes('501');
......@@ -48,7 +51,7 @@ export default RESTAdapter.extend({
// Rethrow to be handled downstream
throw error;
});
},
}
ajaxOptions(url, type, options = {}) {
options.data || (options.data = {});
......@@ -58,13 +61,13 @@ export default RESTAdapter.extend({
options.data.region = region;
}
}
return this._super(url, type, options);
},
return super.ajaxOptions(url, type, options);
}
// In order to remove stale records from the store, findHasMany has to unload
// all records related to the request in question.
findHasMany(store, snapshot, link, relationship) {
return this._super(...arguments).then(payload => {
return super.findHasMany(...arguments).then(payload => {
const relationshipType = relationship.type;
const inverse = snapshot.record.inverseFor(relationship.key);
if (inverse) {
......@@ -77,7 +80,7 @@ export default RESTAdapter.extend({
}
return payload;
});
},
}
// Single record requests deviate from REST practice by using
// the singular form of the resource name.
......@@ -87,9 +90,10 @@ export default RESTAdapter.extend({
//
// This is the original implementation of _buildURL
// without the pluralization of modelName
urlForFindRecord: urlForRecord,
urlForUpdateRecord: urlForRecord,
});
urlForFindRecord = urlForRecord;
urlForUpdateRecord = urlForRecord;
}
function urlForRecord(id, modelName) {
let path;
......
import Watchable from './watchable';
export default Watchable.extend({
export default class Deployment extends Watchable {
promote(deployment) {
const id = deployment.get('id');
const url = urlForAction(this.urlForFindRecord(id, 'deployment'), '/promote');
......@@ -10,8 +10,8 @@ export default Watchable.extend({
All: true,
},
});
},
});
}
}
// The deployment action API endpoints all end with the ID
// /deployment/:action/:deployment_id instead of /deployment/:deployment_id/:action
......
import Watchable from './watchable';
export default Watchable.extend({
export default class JobSummary extends Watchable {
urlForFindRecord(id, type, hash) {
const [name, namespace] = JSON.parse(id);
let url = this._super(name, 'job', hash) + '/summary';
let url = super.urlForFindRecord(name, 'job', hash) + '/summary';
if (namespace && namespace !== 'default') {
url += `?namespace=${namespace}`;
}
return url;
},
});
}
}
import ApplicationAdapter from './application';
import codesForError from '../utils/codes-for-error';
export default ApplicationAdapter.extend({
export default class Namespace extends ApplicationAdapter {
findRecord(store, modelClass, id) {
return this._super(...arguments).catch(error => {
return super.findRecord(...arguments).catch(error => {
const errorCodes = codesForError(error);
if (errorCodes.includes('501')) {
return { Name: id };
}
});
},
});
}
}
import Watchable from './watchable';
import addToPath from 'nomad-ui/utils/add-to-path';
export default Watchable.extend({
export default class Node extends Watchable {
setEligible(node) {
return this.setEligibility(node, true);
},
}
setIneligible(node) {
return this.setEligibility(node, false);
},
}
setEligibility(node, isEligible) {
const url = addToPath(this.urlForFindRecord(node.id, 'node'), '/eligibility');
......@@ -18,7 +18,7 @@ export default Watchable.extend({
Eligibility: isEligible ? 'eligible' : 'ineligible',
},
});
},
}
// Force: -1s deadline
// No Deadline: 0 deadline
......@@ -36,7 +36,7 @@ export default Watchable.extend({
),
},
});
},
}
forceDrain(node, drainSpec) {
return this.drain(
......@@ -45,7 +45,7 @@ export default Watchable.extend({
Deadline: -1,
})
);
},
}
cancelDrain(node) {
const url = addToPath(this.urlForFindRecord(node.id, 'node'), '/drain');
......@@ -55,5 +55,5 @@ export default Watchable.extend({
DrainSpec: null,
},
});
},
});
}
}
import { default as ApplicationAdapter, namespace } from './application';
export default ApplicationAdapter.extend({
namespace: namespace + '/acl',
});
export default class Policy extends ApplicationAdapter {
namespace = namespace + '/acl';
}
import { inject as service } from '@ember/service';
import { default as ApplicationAdapter, namespace } from './application';
export default ApplicationAdapter.extend({
store: service(),
export default class Token extends ApplicationAdapter {
@service store;
namespace: namespace + '/acl',
namespace = namespace + '/acl';
findSelf() {
return this.ajax(`${this.buildURL()}/token/self`, 'GET').then(token => {
......@@ -15,5 +15,5 @@ export default ApplicationAdapter.extend({
return store.peekRecord('token', store.normalize('token', token).data.id);
});
},
});
}
}
......@@ -6,9 +6,9 @@ import queryString from 'query-string';
import ApplicationAdapter from './application';
import removeRecord from '../utils/remove-record';
export default ApplicationAdapter.extend({
watchList: service(),
store: service(),
export default class Watchable extends ApplicationAdapter {
@service watchList;
@service store;
// Overriding ajax is not advised, but this is a minimal modification
// that sets off a series of events that results in query params being
......@@ -19,7 +19,7 @@ export default ApplicationAdapter.extend({
// to ajaxOptions or overriding ajax completely.
ajax(url, type, options) {
const hasParams = hasNonBlockingQueryParams(options);
if (!hasParams || type !== 'GET') return this._super(url, type, options);
if (!hasParams || type !== 'GET') return super.ajax(url, type, options);
const params = { ...options.data };
delete params.index;
......@@ -29,8 +29,8 @@ export default ApplicationAdapter.extend({
// at this point since everything else is added to the URL in advance.
options.data = options.data.index ? { index: options.data.index } : {};
return this._super(`${url}?${queryString.stringify(params)}`, type, options);
},
return super.ajax(`${url}?${queryString.stringify(params)}`, type, options);
}
findAll(store, type, sinceToken, snapshotRecordArray, additionalParams = {}) {
const params = assign(this.buildQuery(), additionalParams);
......@@ -45,7 +45,7 @@ export default ApplicationAdapter.extend({
signal,
data: params,
});
},
}
findRecord(store, type, id, snapshot, additionalParams = {}) {
let [url, params] = this.buildURL(type.modelName, id, snapshot, 'findRecord').split('?');
......@@ -65,7 +65,7 @@ export default ApplicationAdapter.extend({
}
throw error;
});
},
}
query(store, type, query, snapshotRecordArray, options, additionalParams = {}) {
const url = this.buildURL(type.modelName, null, null, 'query', query);
......@@ -107,7 +107,7 @@ export default ApplicationAdapter.extend({
return payload;
});
},
}
reloadRelationship(model, relationshipName, options = { watch: false, abortController: null }) {
const { watch, abortController } = options;
......@@ -156,7 +156,7 @@ export default ApplicationAdapter.extend({
}
);
}
},
}
handleResponse(status, headers, payload, requestData) {
// Some browsers lowercase all headers. Others keep them
......@@ -166,9 +166,9 @@ export default ApplicationAdapter.extend({
this.watchList.setIndexFor(requestData.url, newIndex);
}
return this._super(...arguments);
},
});
return super.handleResponse(...arguments);
}
}
function hasNonBlockingQueryParams(options) {
if (!options || !options.data) return false;
......
......@@ -5,11 +5,11 @@ import config from './config/environment';
let App;
App = Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver,
});
App = class AppApplication extends Application {
modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix;
Resolver = Resolver;
};
loadInitializers(App, config.modulePrefix);
......
......@@ -8,46 +8,48 @@ import { run } from '@ember/runloop';
import { task, timeout } from 'ember-concurrency';
import { lazyClick } from '../helpers/lazy-click';
import AllocationStatsTracker from 'nomad-ui/utils/classes/allocation-stats-tracker';
import classic from 'ember-classic-decorator';
import { classNames, tagName } from '@ember-decorators/component';
export default Component.extend({
store: service(),
token: service(),
@classic
@tagName('tr')
@classNames('allocation-row', 'is-interactive')
export default class AllocationRow extends Component {
@service store;
@service token;
tagName: 'tr',
classNames: ['allocation-row', 'is-interactive'],
allocation: null,
allocation = null;
// Used to determine whether the row should mention the node or the job
context: null,
context = null;
// Internal state
statsError: false,
statsError = false;
enablePolling: overridable(() => !Ember.testing),
@overridable(() => !Ember.testing) enablePolling;
stats: computed('allocation', 'allocation.isRunning', function() {
@computed('allocation', 'allocation.isRunning')
get stats() {
if (!this.get('allocation.isRunning')) return;
return AllocationStatsTracker.create({
fetch: url => this.token.authorizedRequest(url),
allocation: this.allocation,
});
}),
}
cpu: alias('stats.cpu.lastObject'),
memory: alias('stats.memory.lastObject'),
@alias('stats.cpu.lastObject') cpu;
@alias('stats.memory.lastObject') memory;
onClick() {},
onClick() {}
click(event) {
lazyClick([this.onClick, event]);
},
}
didReceiveAttrs() {
this.updateStatsTracker();
},
}
updateStatsTracker() {
const allocation = this.allocation;
......@@ -57,9 +59,9 @@ export default Component.extend({
} else {
this.fetchStats.cancelAll();
}
},
}
fetchStats: task(function*() {
@(task(function*() {
do {
if (this.stats) {
try {
......@@ -72,8 +74,9 @@ export default Component.extend({
yield timeout(500);
} while (this.enablePolling);
}).drop(),
});
}).drop())
fetchStats;
}
async function qualifyAllocation() {
const allocation = this.allocation;
......
......@@ -2,41 +2,47 @@ import Component from '@ember/component';
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { formatBytes } from 'nomad-ui/helpers/format-bytes';
export default Component.extend({
tagName: '',
allocation: null,
statsTracker: null,
isLoading: false,
error: null,
metric: 'memory', // Either memory or cpu
statClass: computed('metric', function() {
import { tagName } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
@classic
@tagName('')
export default class AllocationStat extends Component {
allocation = null;
statsTracker = null;
isLoading = false;
error = null;
metric = 'memory'; // Either memory or cpu
@computed('metric')
get statClass() {
return this.metric === 'cpu' ? 'is-info' : 'is-danger';
}),
}
cpu: alias('statsTracker.cpu.lastObject'),
memory: alias('statsTracker.memory.lastObject'),
@alias('statsTracker.cpu.lastObject') cpu;
@alias('statsTracker.memory.lastObject') memory;
stat: computed('metric', 'cpu', 'memory', function() {
@computed('metric', 'cpu', 'memory')
get stat() {
const { metric } = this;
if (metric === 'cpu' || metric === 'memory') {
return this[this.metric];
}
return;
}),
}
formattedStat: computed('metric', 'stat.used', function() {
@computed('metric', 'stat.used')
get formattedStat() {
if (!this.stat) return;
if (this.metric === 'memory') return formatBytes([this.stat.used]);
return this.stat.used;
}),
}
formattedReserved: computed('metric', 'statsTracker.{reservedMemory,reservedCPU}', function() {
@computed('metric', 'statsTracker.{reservedMemory,reservedCPU}')
get formattedReserved() {
if (this.metric === 'memory') return `${this.statsTracker.reservedMemory} MiB`;
if (this.metric === 'cpu') return `${this.statsTracker.reservedCPU} MHz`;
return;
}),
});
}
}
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { equal, or } from '@ember/object/computed';
import { tagName } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
export default Component.extend({
router: service(),
@classic
@tagName('')
export default class AllocationSubnav extends Component {
@service router;
tagName: '',
@equal('router.currentRouteName', 'allocations.allocation.fs')
fsIsActive;
fsIsActive: equal('router.currentRouteName', 'allocations.allocation.fs'),
fsRootIsActive: equal('router.currentRouteName', 'allocations.allocation.fs-root'),
@equal('router.currentRouteName', 'allocations.allocation.fs-root')
fsRootIsActive;
filesLinkActive: or('fsIsActive', 'fsRootIsActive'),
});
@or('fsIsActive', 'fsRootIsActive') filesLinkActive;
}
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { reads } from '@ember/object/computed';
import { tagName } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
export default Component.extend({
breadcrumbsService: service('breadcrumbs'),
@classic
@tagName('')
export default class AppBreadcrumbs extends Component {
@service('breadcrumbs') breadcrumbsService;
tagName: '',
breadcrumbs: reads('breadcrumbsService.breadcrumbs'),
});
@reads('breadcrumbsService.breadcrumbs') breadcrumbs;
}
import Component from '@ember/component';
import { tagName } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
export default Component.extend({
tagName: '',
});
@classic
@tagName('')
export default class AttributesSection extends Component {}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment