YARN-6402. Move 'Long Running Services' to an independent tab at top level for new Yarn UI. Contributed by Akhil PB.
This commit is contained in:
parent
74a723852d
commit
c0cf11e107
@ -23,7 +23,7 @@ export default AbstractAdapter.extend({
|
|||||||
restNameSpace: "cluster",
|
restNameSpace: "cluster",
|
||||||
serverName: "RM",
|
serverName: "RM",
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/) {
|
urlForQuery(/*query, modelName*/) {
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
url = url + '/apps';
|
url = url + '/apps';
|
||||||
return url;
|
return url;
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
content: null
|
||||||
|
});
|
@ -34,6 +34,7 @@ export default Ember.Component.extend({
|
|||||||
_selected: undefined,
|
_selected: undefined,
|
||||||
gridColumns: [],
|
gridColumns: [],
|
||||||
gridRows: [],
|
gridRows: [],
|
||||||
|
serviceName: undefined,
|
||||||
|
|
||||||
selected: function() {
|
selected: function() {
|
||||||
return this._selected;
|
return this._selected;
|
||||||
@ -290,6 +291,7 @@ export default Ember.Component.extend({
|
|||||||
setAttemptsGridColumnsAndRows: function() {
|
setAttemptsGridColumnsAndRows: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var columns = [];
|
var columns = [];
|
||||||
|
var serviceName = this.get('serviceName');
|
||||||
|
|
||||||
columns.push({
|
columns.push({
|
||||||
id: 'id',
|
id: 'id',
|
||||||
@ -298,10 +300,11 @@ export default Ember.Component.extend({
|
|||||||
cellComponentName: 'em-table-linked-cell',
|
cellComponentName: 'em-table-linked-cell',
|
||||||
minWidth: '300px',
|
minWidth: '300px',
|
||||||
getCellContent: function(row) {
|
getCellContent: function(row) {
|
||||||
|
var attemptId = row.get('id');
|
||||||
|
var query = serviceName? '?service='+serviceName : '';
|
||||||
return {
|
return {
|
||||||
displayText: row.get('id'),
|
displayText: attemptId,
|
||||||
routeName: 'yarn-app-attempt',
|
href: `#/yarn-app-attempt/${attemptId}${query}`
|
||||||
id: row.get('id')
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -326,7 +329,7 @@ export default Ember.Component.extend({
|
|||||||
id: 'appMasterContainerId',
|
id: 'appMasterContainerId',
|
||||||
headerTitle: 'AM Container ID',
|
headerTitle: 'AM Container ID',
|
||||||
contentPath: 'appMasterContainerId',
|
contentPath: 'appMasterContainerId',
|
||||||
minWidth: '300px'
|
minWidth: '350px'
|
||||||
}, {
|
}, {
|
||||||
id: 'amNodeId',
|
id: 'amNodeId',
|
||||||
headerTitle: 'AM Node ID',
|
headerTitle: 'AM Node ID',
|
||||||
@ -384,7 +387,7 @@ export default Ember.Component.extend({
|
|||||||
id: 'id',
|
id: 'id',
|
||||||
headerTitle: 'Container ID',
|
headerTitle: 'Container ID',
|
||||||
contentPath: 'id',
|
contentPath: 'id',
|
||||||
minWidth: '300px'
|
minWidth: '350px'
|
||||||
}, {
|
}, {
|
||||||
id: 'startedTime',
|
id: 'startedTime',
|
||||||
headerTitle: 'Started Time',
|
headerTitle: 'Started Time',
|
||||||
|
@ -19,80 +19,145 @@
|
|||||||
|
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import ColumnDef from 'em-table/utils/column-definition';
|
import ColumnDef from 'em-table/utils/column-definition';
|
||||||
|
import TableDef from 'em-table/utils/table-definition';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
columns: function() {
|
tableDefinition: TableDef.create({
|
||||||
var colums = [];
|
sortColumnId: 'stTime',
|
||||||
colums.push({
|
sortOrder: 'desc'
|
||||||
id: 'appId',
|
}),
|
||||||
headerTitle: 'Application ID',
|
|
||||||
contentPath: 'id',
|
columns: function() {
|
||||||
cellComponentName: 'em-table-linked-cell',
|
var colums = [];
|
||||||
getCellContent: function(row) {
|
colums.push({
|
||||||
return {
|
id: 'appId',
|
||||||
displayText: row.id,
|
headerTitle: 'Application ID',
|
||||||
routeName: 'yarn-app',
|
contentPath: 'id',
|
||||||
id: row.id
|
cellComponentName: 'em-table-linked-cell',
|
||||||
};
|
minWidth: "250px",
|
||||||
},
|
getCellContent: function(row) {
|
||||||
minWidth: "250px"
|
return {
|
||||||
}, {
|
displayText: row.id,
|
||||||
id: 'appType',
|
href: `#/yarn-app/${row.id}`
|
||||||
headerTitle: 'Application Type',
|
};
|
||||||
contentPath: 'applicationType',
|
}
|
||||||
}, {
|
}, {
|
||||||
id: 'appName',
|
id: 'appType',
|
||||||
headerTitle: 'Application Name',
|
headerTitle: 'Application Type',
|
||||||
contentPath: 'appName',
|
contentPath: 'applicationType',
|
||||||
}, {
|
}, {
|
||||||
id: 'appUsr',
|
id: 'appName',
|
||||||
headerTitle: 'User',
|
headerTitle: 'Application Name',
|
||||||
contentPath: 'user',
|
contentPath: 'appName',
|
||||||
minWidth: "50px"
|
}, {
|
||||||
}, {
|
id: 'appUsr',
|
||||||
id: 'queue',
|
headerTitle: 'User',
|
||||||
headerTitle: 'Queue',
|
contentPath: 'user',
|
||||||
contentPath: 'queue',
|
minWidth: "50px"
|
||||||
}, {
|
}, {
|
||||||
id: 'state',
|
id: 'queue',
|
||||||
headerTitle: 'State',
|
headerTitle: 'Queue',
|
||||||
contentPath: 'state',
|
contentPath: 'queue',
|
||||||
cellComponentName: 'em-table-status-cell',
|
}, {
|
||||||
minWidth: "50px"
|
id: 'state',
|
||||||
}, {
|
headerTitle: 'State',
|
||||||
id: 'progress',
|
contentPath: 'state',
|
||||||
headerTitle: 'Progress',
|
cellComponentName: 'em-table-status-cell',
|
||||||
contentPath: 'progress',
|
minWidth: "50px"
|
||||||
cellComponentName: 'em-table-progress-cell',
|
}, {
|
||||||
cellDefinition: {
|
id: 'progress',
|
||||||
valueMax: 100
|
headerTitle: 'Progress',
|
||||||
},
|
contentPath: 'progress',
|
||||||
}, {
|
cellComponentName: 'em-table-progress-cell',
|
||||||
id: 'stTime',
|
cellDefinition: {
|
||||||
headerTitle: 'Start Time',
|
valueMax: 100
|
||||||
contentPath: 'startTime',
|
}
|
||||||
}, {
|
}, {
|
||||||
id: 'elTime',
|
id: 'stTime',
|
||||||
headerTitle: 'Elapsed Time',
|
headerTitle: 'Start Time',
|
||||||
contentPath: 'elapsedTime',
|
contentPath: 'startTime',
|
||||||
cellDefinition: {
|
}, {
|
||||||
type: "duration"
|
id: 'elTime',
|
||||||
}
|
headerTitle: 'Elapsed Time',
|
||||||
}, {
|
contentPath: 'elapsedTime',
|
||||||
id: 'finishTime',
|
cellDefinition: {
|
||||||
headerTitle: 'Finished Time',
|
type: "duration"
|
||||||
contentPath: 'validatedFinishedTs',
|
}
|
||||||
observePath: true
|
}, {
|
||||||
}, {
|
id: 'finishTime',
|
||||||
id: 'priority',
|
headerTitle: 'Finished Time',
|
||||||
headerTitle: 'Priority',
|
contentPath: 'validatedFinishedTs',
|
||||||
contentPath: 'priority',
|
observePath: true
|
||||||
}, {
|
}, {
|
||||||
id: 'cluster',
|
id: 'priority',
|
||||||
headerTitle: '%Cluster',
|
headerTitle: 'Priority',
|
||||||
contentPath: 'clusterUsagePercentage',
|
contentPath: 'priority',
|
||||||
observePath: true
|
}, {
|
||||||
});
|
id: 'cluster',
|
||||||
return ColumnDef.make(colums);
|
headerTitle: '%Cluster',
|
||||||
}.property()
|
contentPath: 'clusterUsagePercentage',
|
||||||
|
observePath: true
|
||||||
|
});
|
||||||
|
return ColumnDef.make(colums);
|
||||||
|
}.property(),
|
||||||
|
|
||||||
|
serviceColumns: function() {
|
||||||
|
var colums = [];
|
||||||
|
colums.push({
|
||||||
|
id: 'appName',
|
||||||
|
headerTitle: 'Service Name',
|
||||||
|
contentPath: 'appName',
|
||||||
|
minWidth: "200px",
|
||||||
|
cellComponentName: 'em-table-linked-cell',
|
||||||
|
getCellContent: function(row) {
|
||||||
|
return {
|
||||||
|
displayText: row.get('appName'),
|
||||||
|
href: `#/yarn-app/${row.id}?service=${row.get('appName')}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
id: 'appId',
|
||||||
|
headerTitle: 'Application ID',
|
||||||
|
contentPath: 'id',
|
||||||
|
minWidth: "250px"
|
||||||
|
}, {
|
||||||
|
id: 'state',
|
||||||
|
headerTitle: 'State',
|
||||||
|
contentPath: 'state',
|
||||||
|
cellComponentName: 'em-table-status-cell',
|
||||||
|
minWidth: "50px"
|
||||||
|
}, {
|
||||||
|
id: 'cluster',
|
||||||
|
headerTitle: '%Cluster',
|
||||||
|
contentPath: 'clusterUsagePercentage',
|
||||||
|
observePath: true
|
||||||
|
}, {
|
||||||
|
id: 'elTime',
|
||||||
|
headerTitle: 'Elapsed Time',
|
||||||
|
contentPath: 'elapsedTime',
|
||||||
|
cellDefinition: {
|
||||||
|
type: "duration"
|
||||||
|
},
|
||||||
|
minWidth: "200px"
|
||||||
|
}, {
|
||||||
|
id: 'appUsr',
|
||||||
|
headerTitle: 'User',
|
||||||
|
contentPath: 'user',
|
||||||
|
minWidth: "50px"
|
||||||
|
}, {
|
||||||
|
id: 'queue',
|
||||||
|
headerTitle: 'Queue',
|
||||||
|
contentPath: 'queue',
|
||||||
|
}, {
|
||||||
|
id: 'stTime',
|
||||||
|
headerTitle: 'Started Time',
|
||||||
|
contentPath: 'startTime',
|
||||||
|
}, {
|
||||||
|
id: 'finishTime',
|
||||||
|
headerTitle: 'Finished Time',
|
||||||
|
contentPath: 'validatedFinishedTs',
|
||||||
|
observePath: true
|
||||||
|
});
|
||||||
|
return ColumnDef.make(colums);
|
||||||
|
}.property(),
|
||||||
});
|
});
|
||||||
|
@ -19,10 +19,14 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
|
queryParams: ["service"],
|
||||||
|
service: undefined,
|
||||||
|
|
||||||
breadcrumbs: Ember.computed("model.attempt.appId", function () {
|
breadcrumbs: Ember.computed("model.attempt.appId", function () {
|
||||||
var appId = this.get("model.attempt.appId");
|
var appId = this.get("model.attempt.appId");
|
||||||
return [{
|
var attemptId = this.get("model.attempt.id");
|
||||||
|
var serviceName = this.get('service');
|
||||||
|
var breadcrumbs = [{
|
||||||
text: "Home",
|
text: "Home",
|
||||||
routeName: 'application'
|
routeName: 'application'
|
||||||
},{
|
},{
|
||||||
@ -30,11 +34,31 @@ export default Ember.Controller.extend({
|
|||||||
routeName: 'yarn-apps.apps'
|
routeName: 'yarn-apps.apps'
|
||||||
}, {
|
}, {
|
||||||
text: `App [${appId}]`,
|
text: `App [${appId}]`,
|
||||||
routeName: 'yarn-app',
|
href: `#/yarn-app/${appId}`
|
||||||
model: appId
|
|
||||||
}, {
|
}, {
|
||||||
text: "Attempt",
|
text: "Attempts",
|
||||||
|
href: `#/yarn-app-attempts/${appId}`
|
||||||
|
}, {
|
||||||
|
text: `Attempt [${attemptId}]`
|
||||||
}];
|
}];
|
||||||
|
if (serviceName) {
|
||||||
|
breadcrumbs = [{
|
||||||
|
text: "Home",
|
||||||
|
routeName: 'application'
|
||||||
|
}, {
|
||||||
|
text: "Services",
|
||||||
|
routeName: 'yarn-services'
|
||||||
|
}, {
|
||||||
|
text: `${serviceName} [${appId}]`,
|
||||||
|
href: `#/yarn-app/${appId}?service=${serviceName}`
|
||||||
|
}, {
|
||||||
|
text: "Attempts",
|
||||||
|
href: `#/yarn-app-attempts/${appId}?service=${serviceName}`
|
||||||
|
}, {
|
||||||
|
text: `Attempt [${attemptId}]`
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return breadcrumbs;
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -19,10 +19,13 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
|
queryParams: ["service"],
|
||||||
|
service: undefined,
|
||||||
|
|
||||||
breadcrumbs: Ember.computed("model.appId", function () {
|
breadcrumbs: Ember.computed("model.appId", function () {
|
||||||
var appId = this.get("model.appId");
|
var appId = this.get("model.appId");
|
||||||
return [{
|
var serviceName = this.get('service');
|
||||||
|
var breadcrumbs = [{
|
||||||
text: "Home",
|
text: "Home",
|
||||||
routeName: 'application'
|
routeName: 'application'
|
||||||
},{
|
},{
|
||||||
@ -30,11 +33,25 @@ export default Ember.Controller.extend({
|
|||||||
routeName: 'yarn-apps.apps'
|
routeName: 'yarn-apps.apps'
|
||||||
}, {
|
}, {
|
||||||
text: `App [${appId}]`,
|
text: `App [${appId}]`,
|
||||||
routeName: 'yarn-app',
|
href: `#/yarn-app/${appId}`
|
||||||
model: appId
|
|
||||||
}, {
|
}, {
|
||||||
text: "Attempts",
|
text: "Attempts",
|
||||||
}];
|
}];
|
||||||
|
if (serviceName) {
|
||||||
|
breadcrumbs = [{
|
||||||
|
text: "Home",
|
||||||
|
routeName: 'application'
|
||||||
|
}, {
|
||||||
|
text: "Services",
|
||||||
|
routeName: 'yarn-services'
|
||||||
|
}, {
|
||||||
|
text: `${serviceName} [${appId}]`,
|
||||||
|
href: `#/yarn-app/${appId}?service=${serviceName}`
|
||||||
|
}, {
|
||||||
|
text: "Attempts"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return breadcrumbs;
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -19,10 +19,13 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
|
queryParams: ["service"],
|
||||||
|
service: undefined,
|
||||||
|
|
||||||
breadcrumbs: Ember.computed("model.app.id", function () {
|
breadcrumbs: Ember.computed("model.app.id", function () {
|
||||||
var appId = this.get("model.app.id");
|
var appId = this.get("model.app.id");
|
||||||
return [{
|
var serviceName = this.get('service');
|
||||||
|
var breadcrumbs = [{
|
||||||
text: "Home",
|
text: "Home",
|
||||||
routeName: 'application'
|
routeName: 'application'
|
||||||
},{
|
},{
|
||||||
@ -30,9 +33,21 @@ export default Ember.Controller.extend({
|
|||||||
routeName: 'yarn-apps.apps'
|
routeName: 'yarn-apps.apps'
|
||||||
}, {
|
}, {
|
||||||
text: `App [${appId}]`,
|
text: `App [${appId}]`,
|
||||||
routeName: 'yarn-app',
|
href: `#/yarn-app/${appId}`
|
||||||
model: appId
|
|
||||||
}];
|
}];
|
||||||
|
if (serviceName) {
|
||||||
|
breadcrumbs = [{
|
||||||
|
text: "Home",
|
||||||
|
routeName: 'application'
|
||||||
|
}, {
|
||||||
|
text: "Services",
|
||||||
|
routeName: 'yarn-services'
|
||||||
|
}, {
|
||||||
|
text: `${serviceName} [${appId}]`,
|
||||||
|
href: `#/yarn-app/${appId}?service=${serviceName}`
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return breadcrumbs;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function() {
|
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function() {
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import Ember from 'ember';
|
|
||||||
import ColumnDef from 'em-table/utils/column-definition';
|
|
||||||
import AppTableController from '../app-table-columns';
|
import AppTableController from '../app-table-columns';
|
||||||
|
|
||||||
export default AppTableController.extend({
|
export default AppTableController.extend({
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import Ember from 'ember';
|
|
||||||
import ColumnDef from 'em-table/utils/column-definition';
|
|
||||||
import AppTableController from '../app-table-columns';
|
import AppTableController from '../app-table-columns';
|
||||||
|
|
||||||
export default AppTableController.extend({
|
export default AppTableController.extend({
|
||||||
|
@ -17,18 +17,85 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import AppTableController from './app-table-columns';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
|
||||||
|
export default AppTableController.extend({
|
||||||
|
|
||||||
breadcrumbs: [{
|
breadcrumbs: [{
|
||||||
text: "Home",
|
text: "Home",
|
||||||
routeName: 'application'
|
routeName: 'application'
|
||||||
}, {
|
}, {
|
||||||
text: "Applications",
|
text: "Services",
|
||||||
routeName: 'yarn-apps.apps',
|
|
||||||
}, {
|
|
||||||
text: "Long Running Services",
|
|
||||||
routeName: 'yarn-services',
|
routeName: 'yarn-services',
|
||||||
}]
|
}],
|
||||||
|
|
||||||
|
getFinishedServicesDataForDonutChart: Ember.computed('model.apps', function() {
|
||||||
|
|
||||||
|
var finishdApps = 0;
|
||||||
|
var failedApps = 0;
|
||||||
|
var killedApps = 0;
|
||||||
|
|
||||||
|
this.get('model.apps').forEach(function(service){
|
||||||
|
if (service.get('state') === "FINISHED") {
|
||||||
|
finishdApps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service.get('state') === "FAILED") {
|
||||||
|
failedApps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service.get('state') === "KILLED") {
|
||||||
|
killedApps++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var arr = [];
|
||||||
|
arr.push({
|
||||||
|
label: "Completed",
|
||||||
|
value: finishdApps
|
||||||
|
});
|
||||||
|
arr.push({
|
||||||
|
label: "Killed",
|
||||||
|
value: killedApps
|
||||||
|
});
|
||||||
|
arr.push({
|
||||||
|
label: "Failed",
|
||||||
|
value: failedApps
|
||||||
|
});
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
getRunningServicesDataForDonutChart: Ember.computed('model.apps', function() {
|
||||||
|
var pendingApps = 0;
|
||||||
|
var runningApps = 0;
|
||||||
|
|
||||||
|
this.get('model.apps').forEach(function(service){
|
||||||
|
if (service.get('state') === "RUNNING") {
|
||||||
|
runningApps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service.get('state') === "ACCEPTED" ||
|
||||||
|
service.get('state') === "SUBMITTED" ||
|
||||||
|
service.get('state') === "NEW" ||
|
||||||
|
service.get('state') === "NEW_SAVING") {
|
||||||
|
pendingApps++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var arr = [];
|
||||||
|
arr.push({
|
||||||
|
label: "Pending",
|
||||||
|
value: pendingApps
|
||||||
|
});
|
||||||
|
arr.push({
|
||||||
|
label: "Running",
|
||||||
|
value: runningApps
|
||||||
|
});
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -59,11 +59,15 @@ export default DS.Model.extend({
|
|||||||
|
|
||||||
validatedFinishedTs: function() {
|
validatedFinishedTs: function() {
|
||||||
if (this.get("finishedTime") < this.get("startTime")) {
|
if (this.get("finishedTime") < this.get("startTime")) {
|
||||||
return "";
|
return "N/A";
|
||||||
}
|
}
|
||||||
return this.get("finishedTime");
|
return this.get("finishedTime");
|
||||||
}.property("finishedTime"),
|
}.property("finishedTime"),
|
||||||
|
|
||||||
|
formattedElapsedTime: function() {
|
||||||
|
return Converter.msToElapsedTimeUnit(this.get('elapsedTime'));
|
||||||
|
}.property('elapsedTime'),
|
||||||
|
|
||||||
allocatedResource: function() {
|
allocatedResource: function() {
|
||||||
return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores"));
|
return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores"));
|
||||||
}.property("allocatedMB", "allocatedVCores"),
|
}.property("allocatedMB", "allocatedVCores"),
|
||||||
|
@ -28,6 +28,7 @@ Router.map(function() {
|
|||||||
this.route('apps');
|
this.route('apps');
|
||||||
this.route('services');
|
this.route('services');
|
||||||
});
|
});
|
||||||
|
this.route('yarn-services');
|
||||||
this.route('yarn-nodes', function(){
|
this.route('yarn-nodes', function(){
|
||||||
this.route('table');
|
this.route('table');
|
||||||
this.route('heatmap');
|
this.route('heatmap');
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Ember from 'ember';
|
||||||
|
import AbstractRoute from './abstract';
|
||||||
|
|
||||||
|
export default AbstractRoute.extend({
|
||||||
|
model() {
|
||||||
|
return Ember.RSVP.hash({
|
||||||
|
apps: this.store.query('yarn-app', {
|
||||||
|
applicationTypes: "org-apache-slider"
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
unloadAll() {
|
||||||
|
this.store.unloadAll('yarn-app');
|
||||||
|
}
|
||||||
|
});
|
@ -305,3 +305,12 @@ li a.navigation-link.ember-view {
|
|||||||
.donut-chart svg {
|
.donut-chart svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.attempt-info-panel table {
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.attempt-info-panel table > tbody > tr > td:last-of-type {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
@ -46,13 +46,18 @@
|
|||||||
<span class="sr-only">(current)</span>
|
<span class="sr-only">(current)</span>
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#link-to 'yarn-apps.apps' tagName="li" currentWhen="yarn-apps.apps yarn-apps.services"}}
|
{{#link-to 'yarn-apps.apps' tagName="li" current-when="yarn-apps.apps yarn-apps.services"}}
|
||||||
{{#link-to 'yarn-apps.apps' class="navigation-link" currentWhen="yarn-apps.apps yarn-apps.services"}}Applications
|
{{#link-to 'yarn-apps.apps' class="navigation-link"}}Applications
|
||||||
<span class="sr-only">(current)</span>
|
<span class="sr-only">(current)</span>
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#link-to 'yarn-nodes.table' tagName="li" currentWhen="yarn-nodes.table yarn-nodes.heatmap"}}
|
{{#link-to 'yarn-services' tagName="li"}}
|
||||||
{{#link-to 'yarn-nodes.table' class="navigation-link" currentWhen="yarn-nodes.table yarn-nodes.heatmap"}}Nodes
|
{{#link-to 'yarn-services' class="navigation-link"}}Services
|
||||||
|
<span class="sr-only">(current)</span>
|
||||||
|
{{/link-to}}
|
||||||
|
{{/link-to}}
|
||||||
|
{{#link-to 'yarn-nodes.table' tagName="li" current-when="yarn-nodes.table yarn-nodes.heatmap"}}
|
||||||
|
{{#link-to 'yarn-nodes.table' class="navigation-link"}}Nodes
|
||||||
<span class="sr-only">(current)</span>
|
<span class="sr-only">(current)</span>
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Application Attempt Id</td>
|
<td>Application Attempt Id</td>
|
||||||
<td>{{attempt.id}}</td>
|
<td title="{{attempt.id}}">{{attempt.id}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Started Time</td>
|
<td>Started Time</td>
|
||||||
@ -38,11 +38,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>AM Container Id</td>
|
<td>AM Container Id</td>
|
||||||
<td>{{attempt.appMasterContainerId}}</td>
|
<td title="{{attempt.appMasterContainerId}}">{{attempt.appMasterContainerId}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>AM Node Id</td>
|
<td>AM Node Id</td>
|
||||||
<td>{{attempt.amNodeId}}</td>
|
<td title="{{attempt.amNodeId}}">{{attempt.amNodeId}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{#if attempt.attemptState}}
|
{{#if attempt.attemptState}}
|
||||||
<tr>
|
<tr>
|
||||||
@ -53,7 +53,7 @@
|
|||||||
{{#if attempt.nodeHttpAddress}}
|
{{#if attempt.nodeHttpAddress}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>AM Node Web UI</td>
|
<td>AM Node Web UI</td>
|
||||||
<td><a href="{{prepend-protocol attempt.nodeHttpAddress}}" target="_blank">{{attempt.nodeHttpAddress}}</a></td>
|
<td title="{{attempt.nodeHttpAddress}}"><a href="{{prepend-protocol attempt.nodeHttpAddress}}" target="_blank">{{attempt.nodeHttpAddress}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if attempt.logsLink}}
|
{{#if attempt.logsLink}}
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
{{#if container.nodeHttpAddress}}
|
{{#if container.nodeHttpAddress}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>NodeManager UI</td>
|
<td>NodeManager UI</td>
|
||||||
<td><a href="{{prepend-protocol container.nodeHttpAddress}}" target="_blank">{{container.nodeHttpAddress}}</a></td>
|
<td title="{{container.nodeHttpAddress}}"><a href="{{prepend-protocol container.nodeHttpAddress}}" target="_blank">{{container.nodeHttpAddress}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if container.logUrl}}
|
{{#if container.logUrl}}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
{{!
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{#if content}}
|
||||||
|
{{{content}}}
|
||||||
|
{{else}}
|
||||||
|
<span class="txt-message">Not Available!</span>
|
||||||
|
{{/if}}
|
@ -38,13 +38,13 @@
|
|||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div role="tabpanel" class="tab-pane active" id="graphViewTab">
|
<div role="tabpanel" class="tab-pane active" id="graphViewTab">
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<div class="col-md-8 container-fluid" id={{parent-id}}></div>
|
<div class="col-md-7 container-fluid" id={{parent-id}}></div>
|
||||||
<!-- diag info -->
|
<!-- diag info -->
|
||||||
<div class="col-md-4 container-fluid">
|
<div class="col-md-5 container-fluid">
|
||||||
<div class="panel panel-default add-ellipsis">
|
<div class="panel panel-default add-ellipsis attempt-info-panel">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{#if selected.link}}
|
{{#if selected.link}}
|
||||||
{{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}}
|
{{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{selected.id}}
|
{{selected.id}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -30,11 +30,11 @@
|
|||||||
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
||||||
<ul class="nav nav-pills nav-stacked collapse in">
|
<ul class="nav nav-pills nav-stacked collapse in">
|
||||||
{{#link-to 'yarn-app' tagName="li"}}
|
{{#link-to 'yarn-app' tagName="li"}}
|
||||||
{{#link-to 'yarn-app' model.appId}}Information
|
{{#link-to 'yarn-app' model.appId (query-params service=service)}}Information
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#link-to 'yarn-app-attempts' tagName="li"}}
|
{{#link-to 'yarn-app-attempts' tagName="li"}}
|
||||||
{{#link-to 'yarn-app-attempts' model.appId}}Attempts List
|
{{#link-to 'yarn-app-attempts' model.appId (query-params service=service)}}Attempts List
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</ul>
|
</ul>
|
||||||
@ -46,7 +46,7 @@
|
|||||||
<div class="col-md-10 container-fluid">
|
<div class="col-md-10 container-fluid">
|
||||||
<!-- timeline view of children -->
|
<!-- timeline view of children -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{timeline-view parent-id="attempt-timeline-div" my-id="timeline-view" height="100%" rmModel=model.attempts label="shortAppAttemptId" attemptModel=true}}
|
{{timeline-view parent-id="attempt-timeline-div" my-id="timeline-view" height="100%" rmModel=model.attempts label="shortAppAttemptId" attemptModel=true serviceName=service}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -25,17 +25,21 @@
|
|||||||
<div class="col-md-2 container-fluid">
|
<div class="col-md-2 container-fluid">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h4>Application</h4>
|
{{#if service}}
|
||||||
|
<h4>Service</h4>
|
||||||
|
{{else}}
|
||||||
|
<h4>Application</h4>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
||||||
<ul class="nav nav-pills nav-stacked collapse in">
|
<ul class="nav nav-pills nav-stacked collapse in">
|
||||||
{{#link-to 'yarn-app' tagName="li"}}
|
{{#link-to 'yarn-app' tagName="li"}}
|
||||||
{{#link-to 'yarn-app' model.app.id}}Information
|
{{#link-to 'yarn-app' model.app.id (query-params service=service)}}Information
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#link-to 'yarn-app-attempts' tagName="li"}}
|
{{#link-to 'yarn-app-attempts' tagName="li"}}
|
||||||
{{#link-to 'yarn-app-attempts' model.app.id}}Attempts List
|
{{#link-to 'yarn-app-attempts' model.app.id (query-params service=service)}}Attempts List
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</ul>
|
</ul>
|
||||||
@ -88,7 +92,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{model.app.startTime}}</td>
|
<td>{{model.app.startTime}}</td>
|
||||||
<td>{{model.app.elapsedTime}}</td>
|
<td>{{model.app.formattedElapsedTime}}</td>
|
||||||
<td>{{model.app.validatedFinishedTs}}</td>
|
<td>{{model.app.validatedFinishedTs}}</td>
|
||||||
<td>{{model.app.priority}}</td>
|
<td>{{model.app.priority}}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -33,10 +33,6 @@
|
|||||||
{{#link-to 'yarn-apps.apps'}}All Applications
|
{{#link-to 'yarn-apps.apps'}}All Applications
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#link-to 'yarn-apps.services' tagName="li"}}
|
|
||||||
{{#link-to 'yarn-apps.services'}}Long Running Services
|
|
||||||
{{/link-to}}
|
|
||||||
{{/link-to}}
|
|
||||||
</ul>
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
{{!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
--}}
|
||||||
|
|
||||||
|
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-12 container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-2 container-fluid">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4>Services</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
||||||
|
<ul class="nav nav-pills nav-stacked collapse in">
|
||||||
|
{{#link-to 'yarn-services' tagName="li"}}
|
||||||
|
{{#link-to 'yarn-services'}}Long Running Services
|
||||||
|
{{/link-to}}
|
||||||
|
{{/link-to}}
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-10 container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4 container-fluid">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
Finished Services
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid" id="finishedapps-donut-chart">
|
||||||
|
{{donut-chart data=getFinishedServicesDataForDonutChart
|
||||||
|
showLabels=true
|
||||||
|
parentId="finishedapps-donut-chart"
|
||||||
|
ratio=0.6
|
||||||
|
maxHeight=350
|
||||||
|
colorTargets="good warn error"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-4 container-fluid">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
Running Services
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid" id="runningapps-donut-chart">
|
||||||
|
{{donut-chart data=getRunningServicesDataForDonutChart
|
||||||
|
showLabels=true
|
||||||
|
parentId="runningapps-donut-chart"
|
||||||
|
ratio=0.6
|
||||||
|
maxHeight=350
|
||||||
|
colorTargets="warn good"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#if model.apps}}
|
||||||
|
{{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}}
|
||||||
|
{{else}}
|
||||||
|
<h4 align="center">Could not find any services from this cluster</h4>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -125,5 +125,29 @@ export default {
|
|||||||
unit = "PB";
|
unit = "PB";
|
||||||
}
|
}
|
||||||
return value.toFixed(1) + " " + unit;
|
return value.toFixed(1) + " " + unit;
|
||||||
|
},
|
||||||
|
msToElapsedTimeUnit: function(millisecs) {
|
||||||
|
var seconds = Math.floor(millisecs / 1000);
|
||||||
|
var days = Math.floor(seconds / (3600 * 24));
|
||||||
|
var hours = Math.floor(seconds / 3600) - (days * 24);
|
||||||
|
var mins = Math.floor((seconds - (hours * 3600) - (days * 24 * 3600)) / 60);
|
||||||
|
var secs = seconds - (days * 24 * 3600) - (hours * 3600) - (mins * 60);
|
||||||
|
var timeStrArr = [];
|
||||||
|
var pluralize = "";
|
||||||
|
if (days > 0) {
|
||||||
|
pluralize = days > 1? " Days" : " Day";
|
||||||
|
timeStrArr.push(days + pluralize);
|
||||||
|
}
|
||||||
|
if (hours > 0) {
|
||||||
|
pluralize = hours > 1? " Hrs" : " Hour";
|
||||||
|
timeStrArr.push(hours + pluralize);
|
||||||
|
}
|
||||||
|
if (mins > 0) {
|
||||||
|
pluralize = mins > 1? " Mins" : " Min";
|
||||||
|
timeStrArr.push(mins + pluralize);
|
||||||
|
}
|
||||||
|
pluralize = secs > 1? " Secs" : " Sec";
|
||||||
|
timeStrArr.push(secs + pluralize);
|
||||||
|
return timeStrArr.join(" : ");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { moduleForComponent, test } from 'ember-qunit';
|
||||||
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
|
||||||
|
moduleForComponent('em-table-html-cell', 'Integration | Component | em table html cell', {
|
||||||
|
integration: true
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it renders', function(assert) {
|
||||||
|
|
||||||
|
// Set any properties with this.set('myProperty', 'value');
|
||||||
|
// Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
|
||||||
|
|
||||||
|
this.render(hbs`{{em-table-html-cell}}`);
|
||||||
|
|
||||||
|
assert.equal(this.$().text().trim(), '');
|
||||||
|
|
||||||
|
// Template block usage:" + EOL +
|
||||||
|
this.render(hbs`
|
||||||
|
{{#em-table-html-cell}}
|
||||||
|
template block text
|
||||||
|
{{/em-table-html-cell}}
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.equal(this.$().text().trim(), 'template block text');
|
||||||
|
});
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { moduleFor, test } from 'ember-qunit';
|
||||||
|
|
||||||
|
moduleFor('route:yarn-services', 'Unit | Route | yarn services', {
|
||||||
|
// Specify the other units that are required for this test.
|
||||||
|
// needs: ['controller:foo']
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it exists', function(assert) {
|
||||||
|
let route = this.subject();
|
||||||
|
assert.ok(route);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user