YARN-8964. [UI2] YARN ui2 should use clusters/{cluster name} for all ATSv2 REST APIs. Contributed by Akhil PB.
This commit is contained in:
parent
8d2789c5eb
commit
5fe1dbf195
|
@ -16,7 +16,6 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DS from 'ember-data';
|
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import Converter from 'yarn-ui/utils/converter';
|
import Converter from 'yarn-ui/utils/converter';
|
||||||
import RESTAbstractAdapter from './restabstract';
|
import RESTAbstractAdapter from './restabstract';
|
||||||
|
@ -26,8 +25,8 @@ import RESTAbstractAdapter from './restabstract';
|
||||||
* in plain text format and not JSON.
|
* in plain text format and not JSON.
|
||||||
*/
|
*/
|
||||||
export default RESTAbstractAdapter.extend({
|
export default RESTAbstractAdapter.extend({
|
||||||
address: "timelineV1WebAddress",
|
address: "timelineWebAddress",
|
||||||
restNameSpace: "timeline",
|
restNameSpace: "timelineV2Log",
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -36,10 +35,14 @@ export default RESTAbstractAdapter.extend({
|
||||||
|
|
||||||
urlForFindRecord(id/*, modelName, snapshot*/) {
|
urlForFindRecord(id/*, modelName, snapshot*/) {
|
||||||
var splits = Converter.splitForAppLogs(id);
|
var splits = Converter.splitForAppLogs(id);
|
||||||
|
var clusterId = this.get("env.app.clusterId");
|
||||||
var containerId = splits[0];
|
var containerId = splits[0];
|
||||||
var logFile = splits[1];
|
var logFile = splits[1];
|
||||||
|
if (splits[2]) {
|
||||||
|
clusterId = splits[2];
|
||||||
|
}
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
url = url + '/containers/' + containerId + '/logs/' + logFile;
|
url = url + '/containers/' + containerId + '/logs/' + logFile + '?clusterid=' + clusterId;
|
||||||
console.log('log url' + url);
|
console.log('log url' + url);
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,7 +25,11 @@ export default AbstractAdapter.extend({
|
||||||
|
|
||||||
urlForFindRecord(id/*, modelName, snapshot*/) {
|
urlForFindRecord(id/*, modelName, snapshot*/) {
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
url = url + '/apps/' + id + '?fields=ALL';
|
var clusterId = this.get("env.app.clusterId");
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
|
url += '/apps/' + id + '?fields=ALL';
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,16 @@ import AbstractAdapter from './abstract';
|
||||||
|
|
||||||
export default AbstractAdapter.extend({
|
export default AbstractAdapter.extend({
|
||||||
address: "timelineWebAddress",
|
address: "timelineWebAddress",
|
||||||
restNameSpace: "timelineService",
|
restNameSpace: "timelineV2",
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/) {
|
urlForQuery(query/*, modelName*/) {
|
||||||
var url = this.buildURL();
|
var url = this.buildURL();
|
||||||
url += '/' + query.appId + '/entities/COMPONENT_INSTANCE?fields=ALL';
|
var clusterId = this.get("env.app.clusterId");
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
|
url += '/apps/' + query.appId + '/entities/COMPONENT_INSTANCE?fields=ALL';
|
||||||
delete query.appId;
|
delete query.appId;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@ export default AbstractAdapter.extend({
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
pathForType(/*modelName*/) {
|
pathForType(/*modelName*/) {
|
||||||
|
var clusterId = this.get("env.app.clusterId");
|
||||||
|
if (clusterId) {
|
||||||
|
return `clusters/${clusterId}/flows`;
|
||||||
|
}
|
||||||
return 'flows'; // move to some common place, return path by modelname.
|
return 'flows'; // move to some common place, return path by modelname.
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,15 +19,15 @@
|
||||||
import AbstractAdapter from './abstract';
|
import AbstractAdapter from './abstract';
|
||||||
|
|
||||||
export default AbstractAdapter.extend({
|
export default AbstractAdapter.extend({
|
||||||
address: "timelineV1WebAddress",
|
address: "timelineWebAddress",
|
||||||
// restNameSpace: "timelineV2", // Use ATSv2 when it supports log APIs.
|
restNameSpace: "timelineV2Log",
|
||||||
restNameSpace: "timeline", //Using ATSv1.5 now, would be supported by ATSv2 very soon.
|
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/) {
|
urlForQuery(query/*, modelName*/) {
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
var containerId = query['containerId'];
|
var containerId = query['containerId'];
|
||||||
|
var clusterId = this.get("env.app.clusterId");
|
||||||
delete query.containerId;
|
delete query.containerId;
|
||||||
return url + '/containers/' + containerId + '/logs';
|
return url + '/containers/' + containerId + '/logs' + '?clusterid=' + clusterId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,12 +20,16 @@ import AbstractAdapter from './abstract';
|
||||||
|
|
||||||
export default AbstractAdapter.extend({
|
export default AbstractAdapter.extend({
|
||||||
address: "timelineWebAddress",
|
address: "timelineWebAddress",
|
||||||
restNameSpace: "timelineService",
|
restNameSpace: "timelineV2",
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/) {
|
urlForQuery(query/*, modelName*/) {
|
||||||
var url = this.buildURL();
|
var url = this.buildURL();
|
||||||
url += '/' + query.appId + '/entities/COMPONENT?fields=ALL';
|
var clusterId = this.get("env.app.clusterId");
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
|
url += '/apps/' + query.appId + '/entities/COMPONENT?fields=ALL';
|
||||||
delete query.appId;
|
delete query.appId;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,16 @@ import AbstractAdapter from './abstract';
|
||||||
|
|
||||||
export default AbstractAdapter.extend({
|
export default AbstractAdapter.extend({
|
||||||
address: "timelineWebAddress",
|
address: "timelineWebAddress",
|
||||||
restNameSpace: "timelineService",
|
restNameSpace: "timelineV2",
|
||||||
serverName: "ATS",
|
serverName: "ATS",
|
||||||
|
|
||||||
urlForQueryRecord(query/*, modelName*/) {
|
urlForQueryRecord(query/*, modelName*/) {
|
||||||
var url = this.buildURL();
|
var url = this.buildURL();
|
||||||
url += '/' + query.appId + '/entities/SERVICE_ATTEMPT?fields=ALL';
|
var clusterId = this.get("env.app.clusterId");
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
|
url += '/apps/' + query.appId + '/entities/SERVICE_ATTEMPT?fields=ALL';
|
||||||
delete query.appId;
|
delete query.appId;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@ export default AbstractAdapter.extend({
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/) {
|
urlForQuery(query/*, modelName*/) {
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
|
var clusterId = this.get("env.app.clusterId")
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
var appId = query.appId;
|
var appId = query.appId;
|
||||||
query.fields = 'ALL';
|
query.fields = 'ALL';
|
||||||
delete query.appId;
|
delete query.appId;
|
||||||
|
@ -34,6 +38,10 @@ export default AbstractAdapter.extend({
|
||||||
|
|
||||||
urlForFindRecord(id/*, modelName, snapshot*/) {
|
urlForFindRecord(id/*, modelName, snapshot*/) {
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
|
var clusterId = this.get("env.app.clusterId")
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
return url + '/apps/' + Converter.attemptIdToAppId(id) +
|
return url + '/apps/' + Converter.attemptIdToAppId(id) +
|
||||||
"/entities/YARN_APPLICATION_ATTEMPT/" + id + "?fields=ALL";
|
"/entities/YARN_APPLICATION_ATTEMPT/" + id + "?fields=ALL";
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@ export default AbstractAdapter.extend({
|
||||||
|
|
||||||
urlForQuery(query/*, modelName*/){
|
urlForQuery(query/*, modelName*/){
|
||||||
var url = this._buildURL();
|
var url = this._buildURL();
|
||||||
|
var clusterId = this.get("env.app.clusterId")
|
||||||
|
if (clusterId) {
|
||||||
|
url += `/clusters/${clusterId}`;
|
||||||
|
}
|
||||||
var app_attempt_id = query.app_attempt_id;
|
var app_attempt_id = query.app_attempt_id;
|
||||||
query.fields = 'ALL';
|
query.fields = 'ALL';
|
||||||
delete query.app_attempt_id;
|
delete query.app_attempt_id;
|
||||||
|
|
|
@ -84,9 +84,36 @@ function getSecurityURL(rmhost) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getClusterIdFromYARN(rmhost, application) {
|
||||||
|
var httpUrl = window.location.protocol + '//' +
|
||||||
|
(ENV.hosts.localBaseAddress? ENV.hosts.localBaseAddress + '/' : '') + rmhost;
|
||||||
|
|
||||||
|
httpUrl += '/conf?name=yarn.resourcemanager.cluster-id';
|
||||||
|
Ember.Logger.log("Get cluster-id URL is: " + httpUrl);
|
||||||
|
|
||||||
|
var clusterId = "";
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
async: false,
|
||||||
|
context: this,
|
||||||
|
url: httpUrl,
|
||||||
|
success: function(data) {
|
||||||
|
clusterId = data.property.value;
|
||||||
|
Ember.Logger.log("Cluster Id from RM: " + clusterId);
|
||||||
|
application.advanceReadiness();
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
application.advanceReadiness();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
function updateConfigs(application) {
|
function updateConfigs(application) {
|
||||||
var hostname = window.location.hostname;
|
var hostname = window.location.hostname;
|
||||||
var rmhost = hostname + (window.location.port ? ':' + window.location.port: '') + skipTrailingSlash(window.location.pathname);
|
var rmhost = hostname + (window.location.port ? ':' + window.location.port: '') +
|
||||||
|
skipTrailingSlash(window.location.pathname);
|
||||||
|
|
||||||
window.ENV = window.ENV || {};
|
window.ENV = window.ENV || {};
|
||||||
window.ENV.hosts = window.ENV.hosts || {};
|
window.ENV.hosts = window.ENV.hosts || {};
|
||||||
|
@ -103,6 +130,10 @@ function updateConfigs(application) {
|
||||||
var protocolSchemeFromRM = getYarnHttpProtocolScheme(rmhost, application);
|
var protocolSchemeFromRM = getYarnHttpProtocolScheme(rmhost, application);
|
||||||
Ember.Logger.log("Is protocol scheme https? " + (protocolSchemeFromRM == "HTTPS_ONLY"));
|
Ember.Logger.log("Is protocol scheme https? " + (protocolSchemeFromRM == "HTTPS_ONLY"));
|
||||||
var isHttpsSchemeEnabled = (protocolSchemeFromRM == "HTTPS_ONLY");
|
var isHttpsSchemeEnabled = (protocolSchemeFromRM == "HTTPS_ONLY");
|
||||||
|
|
||||||
|
var clusterIdFromYARN = getClusterIdFromYARN(rmhost, application);
|
||||||
|
ENV.clusterId = clusterIdFromYARN;
|
||||||
|
|
||||||
if(!ENV.hosts.timelineWebAddress) {
|
if(!ENV.hosts.timelineWebAddress) {
|
||||||
var timelinehost = "";
|
var timelinehost = "";
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -207,6 +238,7 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
const skipTrailingSlash = function(path) {
|
const skipTrailingSlash = function(path) {
|
||||||
|
path = path.replace('index.html', '');
|
||||||
path = path.replace('ui2/', '');
|
path = path.replace('ui2/', '');
|
||||||
path = path.replace(/\/$/, '');
|
path = path.replace(/\/$/, '');
|
||||||
console.log('base url:' + path)
|
console.log('base url:' + path)
|
||||||
|
|
|
@ -49,8 +49,10 @@ Router.map(function() {
|
||||||
{ path: '/yarn-node-containers/:node_id/:node_addr' });
|
{ path: '/yarn-node-containers/:node_id/:node_addr' });
|
||||||
this.route('yarn-node-container',
|
this.route('yarn-node-container',
|
||||||
{ path: '/yarn-node-container/:node_id/:node_addr/:container_id' });
|
{ path: '/yarn-node-container/:node_id/:node_addr/:container_id' });
|
||||||
this.route('yarn-container-log', { path:
|
this.route('yarn-container-log',
|
||||||
'/yarn-container-log/:node_id/:node_addr/:container_id/:filename' });
|
{ path: '/yarn-container-log/:node_id/:node_addr/:container_id/:filename' });
|
||||||
|
this.route('yarn-log-service',
|
||||||
|
{ path: '/yarn-log-service/:cluster_id/:container_id/:filename' });
|
||||||
|
|
||||||
this.route('yarn-deploy-service');
|
this.route('yarn-deploy-service');
|
||||||
this.route('cluster-overview');
|
this.route('cluster-overview');
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
* 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 Constants from 'yarn-ui/constants';
|
||||||
|
|
||||||
|
import AbstractRoute from './abstract';
|
||||||
|
|
||||||
|
export default AbstractRoute.extend({
|
||||||
|
model(param) {
|
||||||
|
var id = param.container_id + Constants.PARAM_SEPARATOR + param.filename
|
||||||
|
+ Constants.PARAM_SEPARATOR + param.cluster_id;
|
||||||
|
return Ember.RSVP.hash({
|
||||||
|
containerLog: this.store.findRecord('yarn-app-log', id),
|
||||||
|
containerInfo: { id: param.container_id }
|
||||||
|
}).then(function (hash) {
|
||||||
|
// Just return as its success.
|
||||||
|
return hash;
|
||||||
|
}, function (reason) {
|
||||||
|
if (reason.errors && reason.errors[0]) {
|
||||||
|
// This means HTTP error response was sent by adapter.
|
||||||
|
return reason;
|
||||||
|
} else {
|
||||||
|
// Assume empty response received from server.
|
||||||
|
return {
|
||||||
|
containerInfo: { id: param.container_id },
|
||||||
|
containerLog: {
|
||||||
|
logs: "",
|
||||||
|
containerID: param.container_id,
|
||||||
|
logFileName: param.filename
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
afterModel(model) {
|
||||||
|
// Handle errors and redirect if promise is rejected.
|
||||||
|
if (model.errors && model.errors[0]) {
|
||||||
|
if (parseInt(model.errors[0].status) === 404) {
|
||||||
|
this.replaceWith('/notfound');
|
||||||
|
} else {
|
||||||
|
this.replaceWith('/error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
unloadAll() {
|
||||||
|
this.store.unloadAll('yarn-app-log');
|
||||||
|
}
|
||||||
|
});
|
|
@ -29,8 +29,8 @@ export default DS.JSONAPISerializer.extend({
|
||||||
type: primaryModelClass.modelName,
|
type: primaryModelClass.modelName,
|
||||||
attributes: {
|
attributes: {
|
||||||
logs: payload,
|
logs: payload,
|
||||||
containerID: splits[1],
|
containerID: splits[0],
|
||||||
logFileName: splits[2]
|
logFileName: splits[1]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return { data: convertedPayload };
|
return { data: convertedPayload };
|
||||||
|
|
|
@ -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.
|
||||||
|
--}}
|
||||||
|
|
||||||
|
<div class="col-md-12 container-fluid">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h5 align="center">
|
||||||
|
<b>Log: {{model.containerLog.logFileName}} [ {{model.containerLog.containerID}} ]</b>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{{#if model.containerLog.logs}}
|
||||||
|
<pre>{{model.containerLog.logs}}</pre>
|
||||||
|
{{else}}
|
||||||
|
<p>No logs were written in {{model.containerLog.logFileName}}.</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{outlet}}
|
|
@ -119,7 +119,7 @@ export default {
|
||||||
if (splitLen < 2) {
|
if (splitLen < 2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return [splits[0], splits[1]];
|
return splits[2] ? [splits[0], splits[1], splits[2]] : [splits[0], splits[1]];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
memoryToSimpliedUnit: function(mb) {
|
memoryToSimpliedUnit: function(mb) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ module.exports = { // YARN UI App configurations
|
||||||
cluster: 'ws/v1/cluster',
|
cluster: 'ws/v1/cluster',
|
||||||
metrics: 'ws/v1/cluster/metrics',
|
metrics: 'ws/v1/cluster/metrics',
|
||||||
timelineV2: 'ws/v2/timeline',
|
timelineV2: 'ws/v2/timeline',
|
||||||
|
timelineV2Log: 'ws/v2/applicationlog',
|
||||||
dashService: 'app/v1/services',
|
dashService: 'app/v1/services',
|
||||||
node: '{nodeAddress}/ws/v1/node'
|
node: '{nodeAddress}/ws/v1/node'
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue