YARN-6635. Refactor yarn-app pages in new YARN UI. Contributed by Akhil PB.

This commit is contained in:
Sunil G 2017-05-30 13:52:40 +05:30
parent 07e60f85d8
commit af03c33346
31 changed files with 573 additions and 437 deletions

View File

@ -38,7 +38,7 @@ export default Ember.Controller.extend({
getCellContent: function(row) {
return {
displayText: row.id,
href: `#/yarn-app/${row.id}`
href: `#/yarn-app/${row.id}/info`
};
}
}, {
@ -112,7 +112,7 @@ export default Ember.Controller.extend({
getCellContent: function(row) {
return {
displayText: row.get('appName'),
href: `#/yarn-app/${row.id}?service=${row.get('appName')}`
href: `#/yarn-app/${row.id}/info?service=${row.get('appName')}`
};
}
}, {

View File

@ -34,10 +34,10 @@ export default Ember.Controller.extend({
routeName: 'yarn-apps.apps'
}, {
text: `App [${appId}]`,
href: `#/yarn-app/${appId}`
href: `#/yarn-app/${appId}/info`
}, {
text: "Attempts",
href: `#/yarn-app-attempts/${appId}`
href: `#/yarn-app/${appId}/attempts`
}, {
text: `Attempt [${attemptId}]`
}];
@ -50,10 +50,10 @@ export default Ember.Controller.extend({
routeName: 'yarn-services'
}, {
text: `${serviceName} [${appId}]`,
href: `#/yarn-app/${appId}?service=${serviceName}`
href: `#/yarn-app/${appId}/info?service=${serviceName}`
}, {
text: "Attempts",
href: `#/yarn-app-attempts/${appId}?service=${serviceName}`
href: `#/yarn-app/${appId}/attempts?service=${serviceName}`
}, {
text: `Attempt [${attemptId}]`
}];

View File

@ -1,57 +0,0 @@
/**
* 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.Controller.extend({
queryParams: ["service"],
service: undefined,
breadcrumbs: Ember.computed("model.appId", function () {
var appId = this.get("model.appId");
var serviceName = this.get('service');
var breadcrumbs = [{
text: "Home",
routeName: 'application'
},{
text: "Applications",
routeName: 'yarn-apps.apps'
}, {
text: `App [${appId}]`,
href: `#/yarn-app/${appId}`
}, {
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;
})
});

View File

@ -19,42 +19,44 @@
import Ember from 'ember';
export default Ember.Controller.extend({
queryParams: ["service"],
service: undefined,
appId: '',
serviceName: undefined,
breadcrumbs: Ember.computed("model.app.id", function () {
var appId = this.get("model.app.id");
var serviceName = this.get('service');
breadcrumbs: [{
text: "Home",
routeName: 'application'
}, {
text: "Applications",
routeName: 'yarn-apps.apps'
}, {
text: 'App'
}],
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
var breadcrumbs = [{
text: "Home",
routeName: 'application'
},{
text: "Applications",
routeName: 'yarn-apps.apps'
}, {
text: `App [${appId}]`,
href: `#/yarn-app/${appId}`
}];
if (serviceName) {
breadcrumbs = [{
text: "Home",
routeName: 'application'
}, {
if (appId && serviceName) {
breadcrumbs.push({
text: "Services",
routeName: 'yarn-services'
}, {
text: `${serviceName} [${appId}]`,
href: `#/yarn-app/${appId}?service=${serviceName}`
}];
href: `#/yarn-app/${appId}/info?service=${serviceName}`
});
} else {
breadcrumbs.push({
text: "Applications",
routeName: 'yarn-apps.apps'
}, {
text: `App [${appId}]`,
href: `#/yarn-app/${appId}/info`
});
}
return breadcrumbs;
}),
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function() {
var amHostAddress = this.get('model.app.amHostHttpAddress');
if (amHostAddress && amHostAddress.indexOf('://') < 0) {
amHostAddress = 'http://' + amHostAddress;
if (tailCrumbs) {
breadcrumbs.pushObjects(tailCrumbs);
}
return amHostAddress;
})
this.set('breadcrumbs', breadcrumbs);
}
});

View File

@ -0,0 +1,24 @@
/**
* 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.Controller.extend({
queryParams: ["service"],
service: undefined
});

View File

@ -18,16 +18,11 @@
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
apps: this.store.query('yarn-app', {
applicationTypes: "org-apache-slider"
}),
});
},
export default Ember.Controller.extend({
queryParams: ["service"],
service: undefined,
unloadAll() {
this.store.unloadAll('yarn-app');
}
isRunningApp: Ember.computed('model.app.state', function() {
return this.get('model.app.state') === "RUNNING";
})
});

View File

@ -0,0 +1,32 @@
/**
* 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.Controller.extend({
queryParams: ["service"],
service: undefined,
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function() {
var amHostAddress = this.get('model.app.amHostHttpAddress');
if (amHostAddress && amHostAddress.indexOf('://') < 0) {
amHostAddress = 'http://' + amHostAddress;
}
return amHostAddress;
})
});

View File

@ -1,31 +0,0 @@
/**
* 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 TableDefinition from 'em-table/utils/table-definition';
import AppTableController from '../app-table-columns';
export default AppTableController.extend({
queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'],
tableDefinition: TableDefinition.create(),
searchText: Ember.computed.alias('tableDefinition.searchText'),
sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'),
sortOrder: Ember.computed.alias('tableDefinition.sortOrder'),
pageNum: Ember.computed.alias('tableDefinition.pageNum'),
rowCount: Ember.computed.alias('tableDefinition.rowCount')
});

View File

@ -32,7 +32,7 @@ function createColumn() {
minWidth: "300px",
getCellContent: function (row) {
return {
routeName: 'yarn-app',
routeName: 'yarn-app.info',
id: row.get('appId'),
displayText: row.get('appId')
};

View File

@ -26,7 +26,6 @@ var Router = Ember.Router.extend({
Router.map(function() {
this.route('yarn-apps', function () {
this.route('apps');
this.route('services');
});
this.route('yarn-services');
this.route('yarn-nodes', function(){
@ -50,11 +49,14 @@ Router.map(function() {
'/yarn-container-log/:node_id/:node_addr/:container_id/:filename' });
this.route('cluster-overview');
this.route('yarn-app', { path: '/yarn-app/:app_id' });
this.route('yarn-app', function() {
this.route('info', {path: '/:app_id/info'});
this.route('attempts', {path: '/:app_id/attempts'});
this.route('charts', {path: '/:app_id/charts'});
});
this.route('yarn-app-attempt', { path: '/yarn-app-attempt/:app_attempt_id'});
this.route('error');
this.route('notfound', { path: '*:' });
this.route('yarn-app-attempts', { path: '/yarn-app-attempts/:app_id' });
this.route('yarn-queues', { path: '/yarn-queues/:queue_name' });
this.route('yarn-flow-activity');

View File

@ -16,35 +16,14 @@
* limitations under the License.
*/
import Ember from 'ember';
import AbstractRoute from './abstract';
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend(AppAttemptMixin, {
model(param) {
return Ember.RSVP.hash({
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store),
rmContainers: this.store.find('yarn-app', param.app_id).then(function() {
return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) {
if (attempts && attempts.get('firstObject')) {
var appAttemptId = attempts.get('firstObject').get('appAttemptId');
return this.store.query('yarn-container', {
app_attempt_id: appAttemptId
});
}
}.bind(this));
}.bind(this)),
nodes: this.store.findAll('yarn-rm-node', {reload: true}),
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-attempt');
this.store.unloadAll('yarn-container');
this.store.unloadAll('yarn-rm-node');
this.store.unloadAll('yarn-app-timeline');
export default AbstractRoute.extend({
actions: {
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
var controller = this.controllerFor('yarn-app');
controller.setProperties({appId: appId, serviceName: serviceName});
controller.updateBreadcrumbs(appId, serviceName, tailCrumbs);
}
}
});

View File

@ -17,13 +17,15 @@
*/
import Ember from 'ember';
import AbstractRoute from './abstract';
import AbstractRoute from '../abstract';
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend(AppAttemptMixin, {
model(param) {
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: 'Attempts'}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
attempts: this.fetchAttemptListFromRMorATS(param.app_id, this.store)
});
},

View File

@ -0,0 +1,53 @@
/**
* 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(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: "Charts"}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
app: this.store.find('yarn-app', param.app_id),
rmContainers: this.store.find('yarn-app', param.app_id).then(function() {
return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) {
if (attempts && attempts.get('firstObject')) {
var appAttemptId = attempts.get('firstObject').get('appAttemptId');
return this.store.query('yarn-container', {
app_attempt_id: appAttemptId,
is_rm: true
});
}
}.bind(this));
}.bind(this)),
nodes: this.store.findAll('yarn-rm-node')
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-attempt');
this.store.unloadAll('yarn-container');
this.store.unloadAll('yarn-rm-node');
}
});

View File

@ -0,0 +1,37 @@
/**
* 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';
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend(AppAttemptMixin, {
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store)
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-timeline');
}
});

View File

@ -46,7 +46,7 @@
<span class="sr-only">(current)</span>
{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-apps.apps' tagName="li" current-when="yarn-apps.apps yarn-apps.services"}}
{{#link-to 'yarn-apps.apps' tagName="li" current-when="yarn-apps.apps"}}
{{#link-to 'yarn-apps.apps' class="navigation-link"}}Applications
<span class="sr-only">(current)</span>
{{/link-to}}

View File

@ -38,7 +38,7 @@
{{#if arr}}
{{#each arr as |app|}}
<tr>
<td><a href="#/yarn-app/{{app.id}}">{{app.id}}</a></td>
<td><a href="#/yarn-app/{{app.id}}/info">{{app.id}}</a></td>
<td>{{app.applicationType}}</td>
<td>{{app.appName}}</td>
<td>{{app.user}}</td>
@ -61,7 +61,7 @@
{{/each}}
{{else}}
<tr>
<td><a href="#/yarn-app/{{app.id}}">{{app.id}}</a></td>
<td><a href="#/yarn-app/{{app.id}}/info">{{app.id}}</a></td>
<td>{{app.applicationType}}</td>
<td>{{app.appName}}</td>
<td>{{app.user}}</td>
@ -83,4 +83,4 @@
</tr>
{{/if}}
</tbody>
</table>
</table>

View File

@ -1,58 +0,0 @@
{{!
* 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">
{{#if service}}
Service
{{else}}
Application
{{/if}}
</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-app' tagName="li"}}
{{#link-to 'yarn-app' model.appId (query-params service=service)}}Information
{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app-attempts' tagName="li"}}
{{#link-to 'yarn-app-attempts' model.appId (query-params service=service)}}Attempts List
{{/link-to}}
{{/link-to}}
</ul>
</ul>
</div>
</div>
</div>
<div class="col-md-10 container-fluid">
<div class="row">
{{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>
{{outlet}}

View File

@ -18,14 +18,13 @@
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
{{#if model.app}}
<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">
{{#if service}}
{{#if serviceName}}
Service
{{else}}
Application
@ -34,13 +33,14 @@
<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-app' tagName="li"}}
{{#link-to 'yarn-app' model.app.id (query-params service=service)}}Information
{{/link-to}}
{{#link-to 'yarn-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
{{#link-to 'yarn-app.info' appId (query-params service=serviceName)}}Information{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app-attempts' tagName="li"}}
{{#link-to 'yarn-app-attempts' model.app.id (query-params service=service)}}Attempts List
{{/link-to}}
{{#link-to 'yarn-app.attempts' tagName="li" class=(if (eq target.currentPath 'yarn-app.attempts') "active")}}
{{#link-to 'yarn-app.attempts' appId (query-params service=serviceName)}}Attempts List{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.charts' tagName="li" class=(if (eq target.currentPath 'yarn-app.charts') "active")}}
{{#link-to 'yarn-app.charts' appId (query-params service=serviceName)}}Resource Usage{{/link-to}}
{{/link-to}}
</ul>
</ul>
@ -49,174 +49,7 @@
</div>
<div class="col-md-10 container-fluid">
<div class="row">
<div class="col-md-12">
{{app-timeout-bar app=model.app}}
</div>
</div>
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Basic Info</div>
<div class="x-scroll">
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Application ID</th>
<th>Name</th>
<th>User</th>
<th>Queue</th>
<th>State</th>
<th>Final Status</th>
<th>Start Time</th>
<th>Elapsed Time</th>
<th>Finished Time</th>
<th>Priority</th>
<th>Progress</th>
<th>Is Unmanaged AM</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.id}}</td>
<td>{{model.app.appName}}</td>
<td>{{model.app.user}}</td>
<td>{{model.app.queue}}</td>
<td>{{model.app.state}}</td>
<td>
<span class={{model.app.finalStatusStyle}}>
{{model.app.finalStatus}}
</span>
</td>
<td>{{model.app.startTime}}</td>
<td>{{model.app.formattedElapsedTime}}</td>
<td>{{model.app.validatedFinishedTs}}</td>
<td>{{model.app.priority}}</td>
<td>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar"
aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100"
style={{model.app.progressStyle}}>
{{model.app.progress}}%
</div>
</div>
</td>
<td>{{model.app.unmanagedApplication}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
{{#if model.app.diagnostics}}
<div class="col-md-12 container-fluid">
{{#if model.app.isFailed}}
<div class="panel panel-danger">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{else}}
<div class="panel panel-default">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{/if}}
</div>
{{/if}}
</div>
<div class="row">
<div class="col-md-8 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Scheduling Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Allocated Resource</th>
<th>Running Containers</th>
<th>Preempted Resource</th>
<th>Num Non-AM container preempted</th>
<th>Num AM container preempted</th>
<th>Aggregated Resource Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.allocatedResource}}</td>
<td>{{model.app.runningContainersNumber}}</td>
<td>{{model.app.preemptedResource}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.aggregatedResourceUsage}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-4 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Application Master Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Master Container Log</th>
<th>Master Node</th>
<th>Master Node Label Expression</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="{{model.app.amContainerLogs}}" target="_blank">Link</a></td>
<td><a href="{{amHostHttpAddressFormatted}}" target="_blank">Link</a></td>
<td>{{model.app.amNodeLabelExpression}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{{#if model.nodes}}
{{#if model.rmContainers}}
<div class="row" id="stackd-bar-chart-mem">
{{per-app-memusage-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-mem"
title=(concat 'Memory usage by nodes for: [' model.app.id ']')}}
</div>
<hr>
<div class="row" id="stackd-bar-chart-ncontainer">
{{per-app-ncontainers-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-ncontainer"
title=(concat 'Running #Containers by nodes for: [' model.app.id ']')}}
</div>
{{/if}}
{{/if}}
{{outlet}}
</div>
</div>
</div>
{{/if}}
{{outlet}}

View File

@ -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.
}}
<div class="row">
{{timeline-view
parent-id="attempt-timeline-div"
my-id="timeline-view"
height="100%"
rmModel=model.attempts
label="shortAppAttemptId"
attemptModel=true
serviceName=model.serviceName
}}
</div>

View File

@ -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.
}}
<div class="row">
<div class="col-md-12 container-fluid">
{{#if isRunningApp}}
<div class="row" id="stackd-bar-chart-mem">
{{per-app-memusage-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-mem"
title=(concat 'Memory usage by nodes for: [' model.appId ']')}}
</div>
<hr>
<div class="row" id="stackd-bar-chart-ncontainer">
{{per-app-ncontainers-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-ncontainer"
title=(concat 'Running #Containers by nodes for: [' model.appId ']')}}
</div>
{{else}}
<div class="panel panel-default">
<h4 class="text-center">No resource usage data is available for this application!</h4>
</div>
{{/if}}
</div>
</div>

View File

@ -0,0 +1,167 @@
{{!
* 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.
}}
<div class="row">
<div class="col-md-12">
{{app-timeout-bar app=model.app}}
</div>
</div>
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Basic Info
</div>
<div class="x-scroll">
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Application ID</th>
<th>Name</th>
<th>User</th>
<th>Queue</th>
<th>State</th>
<th>Final Status</th>
<th>Start Time</th>
<th>Elapsed Time</th>
<th>Finished Time</th>
<th>Priority</th>
{{#unless model.serviceName}}
<th>Progress</th>
<th>Is Unmanaged AM</th>
{{/unless}}
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.id}}</td>
<td>{{model.app.appName}}</td>
<td>{{model.app.user}}</td>
<td>{{model.app.queue}}</td>
<td>{{model.app.state}}</td>
<td>
<span class={{model.app.finalStatusStyle}}>
{{model.app.finalStatus}}
</span>
</td>
<td>{{model.app.startTime}}</td>
<td>{{model.app.formattedElapsedTime}}</td>
<td>{{model.app.validatedFinishedTs}}</td>
<td>{{model.app.priority}}</td>
{{#unless model.serviceName}}
<td>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar"
aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100"
style={{model.app.progressStyle}}>
{{model.app.progress}}%
</div>
</div>
</td>
<td>{{model.app.unmanagedApplication}}</td>
{{/unless}}
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
{{#if model.app.diagnostics}}
<div class="col-md-12 container-fluid">
{{#if model.app.isFailed}}
<div class="panel panel-danger">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{else}}
<div class="panel panel-default">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{/if}}
</div>
{{/if}}
</div>
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Scheduling Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Allocated Resource</th>
<th>Running Containers</th>
<th>Preempted Resource</th>
<th>Num Non-AM container preempted</th>
<th>Num AM container preempted</th>
<th>Aggregated Resource Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.allocatedResource}}</td>
<td>{{model.app.runningContainersNumber}}</td>
<td>{{model.app.preemptedResource}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.aggregatedResourceUsage}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Application Master Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Master Container Log</th>
<th>Master Node</th>
<th>Master Node Label Expression</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="{{model.app.amContainerLogs}}" target="_blank">Link</a></td>
<td><a href="{{amHostHttpAddressFormatted}}" target="_blank">Link</a></td>
<td>{{model.app.amNodeLabelExpression}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -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.
}}
<div class="col-md-12 container-fluid">
<div class="loading-mask">
<img src="assets/images/spinner.gif" alt="Loading...">
</div>
</div>

View File

@ -24,14 +24,13 @@
<div class="col-md-2 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
<h4>Applications</h4>
Applications
</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-apps.apps' tagName="li"}}
{{#link-to 'yarn-apps.apps'}}All Applications
{{/link-to}}
{{#link-to 'yarn-apps.apps'}}All Applications{{/link-to}}
{{/link-to}}
</ul>
</ul>

View File

@ -1,25 +0,0 @@
{{!--
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 model.apps}}
{{em-table columns=columns rows=model.apps definition=tableDefinition}}
{{else}}
<h4 align="center">Could not find any applications from this cluster</h4>
{{/if}}
{{outlet}}

View File

@ -31,8 +31,7 @@
<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 'yarn-services'}}Long Running Services{{/link-to}}
{{/link-to}}
</ul>
</ul>

View File

@ -18,7 +18,7 @@
import { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-app-attempts', 'Unit | Controller | yarn app attempts', {
moduleFor('controller:yarn-app/attempts', 'Unit | Controller | yarn app/attempts', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});

View File

@ -18,7 +18,7 @@
import { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-apps/services', 'Unit | Controller | yarn apps/services', {
moduleFor('controller:yarn-app/charts', 'Unit | Controller | yarn app/charts', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});

View File

@ -0,0 +1,30 @@
/**
* 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('controller:yarn-app/info', 'Unit | Controller | yarn app/info', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -18,7 +18,7 @@
import { moduleFor, test } from 'ember-qunit';
moduleFor('route:yarn-app-attempts', 'Unit | Route | yarn app attempts', {
moduleFor('route:yarn-app/attempts', 'Unit | Route | yarn app/attempts', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});

View File

@ -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-app/charts', 'Unit | Route | yarn app/charts', {
// 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);
});

View File

@ -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-app/info', 'Unit | Route | yarn app/info', {
// 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);
});