You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by su...@apache.org on 2017/12/05 14:11:20 UTC

hadoop git commit: YARN-7092. Render application specific log under application tab in new YARN UI. Contributed by Akhil PB.

Repository: hadoop
Updated Branches:
  refs/heads/trunk f9f317b70 -> 99ccca341


YARN-7092. Render application specific log under application tab in new YARN UI. Contributed by Akhil PB.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/99ccca34
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/99ccca34
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/99ccca34

Branch: refs/heads/trunk
Commit: 99ccca341f3669b801428dea0acdba597f34c668
Parents: f9f317b
Author: Sunil G <su...@apache.org>
Authored: Tue Dec 5 19:41:07 2017 +0530
Committer: Sunil G <su...@apache.org>
Committed: Tue Dec 5 19:41:07 2017 +0530

----------------------------------------------------------------------
 .../src/main/webapp/app/adapters/yarn-log.js    |  39 ++++
 .../webapp/app/components/collapsible-panel.js  |  64 ++++++
 .../main/webapp/app/components/timeline-view.js |   6 +-
 .../webapp/app/controllers/yarn-app-attempt.js  |   2 +-
 .../webapp/app/controllers/yarn-app/logs.js     | 204 +++++++++++++++++++
 .../src/main/webapp/app/models/yarn-log.js      |  27 +++
 .../src/main/webapp/app/router.js               |   1 +
 .../main/webapp/app/routes/yarn-app-attempt.js  |   4 +-
 .../main/webapp/app/routes/yarn-app/attempts.js |   4 +-
 .../src/main/webapp/app/routes/yarn-app/logs.js |  47 +++++
 .../src/main/webapp/app/serializers/yarn-log.js |  48 +++++
 .../templates/components/collapsible-panel.hbs  |  21 ++
 .../app/templates/components/timeline-view.hbs  |  66 +++---
 .../webapp/app/templates/yarn-app-attempt.hbs   |  21 +-
 .../src/main/webapp/app/templates/yarn-app.hbs  |   3 +
 .../webapp/app/templates/yarn-app/attempts.hbs  |  13 ++
 .../main/webapp/app/templates/yarn-app/logs.hbs | 132 ++++++++++++
 .../src/main/webapp/bower-shrinkwrap.json       |  12 +-
 .../components/collapsible-panel-test.js        |  43 ++++
 .../webapp/tests/unit/adapters/yarn-log-test.js |  30 +++
 .../unit/controllers/yarn-app/logs-test.js      |  30 +++
 .../webapp/tests/unit/models/yarn-log-test.js   |  30 +++
 .../tests/unit/routes/yarn-app/logs-test.js     |  29 +++
 .../tests/unit/serializers/yarn-log-test.js     |  33 +++
 24 files changed, 857 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-log.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-log.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-log.js
new file mode 100644
index 0000000..df29b71
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-log.js
@@ -0,0 +1,39 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  // restNameSpace: "timelineV2", // Use ATSv2 when it supports log APIs.
+  restNameSpace: "timeline", //Using ATSv1.5 now, would be supported by ATSv2 very soon.
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/) {
+    var url = this._buildURL();
+    var containerId = query['containerId'];
+    delete query.containerId;
+    return url + '/containers/' + containerId + '/logs';
+  },
+
+  fetchLogFileContent(containerId, logFile) {
+    var url = this._buildURL();
+    url = url + '/containers/' + containerId + '/logs/' + logFile;
+    return Ember.$.ajax({url: url, type: 'GET', dataType: 'text'});
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/collapsible-panel.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/collapsible-panel.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/collapsible-panel.js
new file mode 100644
index 0000000..6a40f8f
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/collapsible-panel.js
@@ -0,0 +1,64 @@
+/**
+ * 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({
+  classNames: ['pull-right'],
+
+  targetId: '',
+  initialClosedState: false,
+
+  didInsertElement() {
+    if (!this.get('targetId')) {
+      this.$('.toggle_switch').hide();
+    }
+    if (this.get('targetId') && this.get('initialClosedState')) {
+      this.$('.toggle_switch').show();
+      this.toggleToggleSwitchArrow();
+      Ember.$('#' + this.get('targetId')).removeClass('panel-collapsed').show();
+    }
+  },
+
+  toggleToggleSwitchArrow() {
+    let $toggleArrow = this.$('.toggle_switch').find('span');
+    if ($toggleArrow.hasClass('glyphicon-chevron-up')) {
+      $toggleArrow.removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');
+    } else {
+      $toggleArrow.removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');
+    }
+  },
+
+  toggleCollapsiblePanel() {
+    let $collapsiblePanel = Ember.$('#' + this.get('targetId'));
+    if ($collapsiblePanel.hasClass('panel-collapsed')) {
+      $collapsiblePanel.removeClass('panel-collapsed');
+      $collapsiblePanel.slideDown();
+    } else {
+      $collapsiblePanel.addClass('panel-collapsed');
+      $collapsiblePanel.slideUp();
+    }
+  },
+
+  actions: {
+    togglePanelCollapse() {
+      this.toggleToggleSwitchArrow();
+      this.toggleCollapsiblePanel();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js
index 865fe52..420d793 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js
@@ -472,9 +472,5 @@ export default Ember.Component.extend({
       prop = 'http://' + prop;
     }
     return prop;
-  },
-
-  isDataEmpty: Ember.computed(function() {
-    return this.modelArr.length === 0;
-  })
+  }
 });

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js
index 1121a84..504b66e 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js
@@ -22,7 +22,7 @@ export default Ember.Controller.extend({
   queryParams: ["service"],
   service: undefined,
 
-  breadcrumbs: Ember.computed("model.attempt.appId", function () {
+  breadcrumbs: Ember.computed("model.attempt.appId", "model.attempt.id", function () {
     var appId = this.get("model.attempt.appId");
     var attemptId = this.get("model.attempt.id");
     var serviceName = this.get('service');

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app/logs.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app/logs.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app/logs.js
new file mode 100644
index 0000000..c996f05
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app/logs.js
@@ -0,0 +1,204 @@
+/**
+ * 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,
+
+  selectedAttemptId: '',
+  attemptContainerList: null,
+  selectedContainerId: '',
+  selectedLogFileName: '',
+  containerLogFiles: null,
+  selectedLogFileContent: '',
+
+  _isLoadingTopPanel: false,
+  _isLoadingBottomPanel: false,
+
+  actions: {
+    showContainersForAttemptId(attemptId) {
+      this.set('selectedAttemptId', '');
+      if (attemptId) {
+        this.set('_isLoadingTopPanel', true);
+        this.set('selectedAttemptId', attemptId);
+        this.fetchContainersForAttemptId(attemptId).then((hash) => {
+          let containers = null;
+          if (hash.rmContainers.get('length') > 0 && hash.rmContainers.get('content')) {
+            containers = (containers || []).concat(hash.rmContainers.get('content'));
+          }
+          if (hash.tsContainers.get('length') > 0 && hash.tsContainers.get('content')) {
+            containers = (containers || []).concat(hash.tsContainers.get('content'));
+          }
+          this.set('attemptContainerList', containers);
+        }).finally(() => {
+          this.set('_isLoadingTopPanel', false);
+        });
+      } else {
+        this.set('attemptContainerList', null);
+        this.set('selectedContainerId', '');
+        this.set('containerLogFiles', null);
+        this.set('selectedLogFileName', '');
+        this.set('selectedLogFileContent', '');
+      }
+    },
+
+    showLogFilesForContainerId(containerId) {
+      this.set('selectedContainerId', '');
+      this.set('containerLogFiles', null);
+      this.set('selectedLogFileName', '');
+      this.set('selectedLogFileContent', '');
+      if (containerId) {
+        this.set('_isLoadingBottomPanel', true);
+        this.set('selectedContainerId', containerId);
+        this.fetchLogFilesForContainerId(containerId).then((hash) => {
+          if (hash.logs.get('length') > 0) {
+            this.set('containerLogFiles', hash.logs);
+          } else {
+            this.set('containerLogFiles', null);
+          }
+        }).finally(() => {
+          this.set('_isLoadingBottomPanel', false);
+        });
+      }
+    },
+
+    showContentForLogFile(logFile) {
+      this.set('selectedLogFileName', '');
+      Ember.$("#logContentTextArea1234554321").val('');
+      this.set('showFullLog', false);
+      if (logFile) {
+        this.set('_isLoadingBottomPanel', true);
+        this.set('selectedLogFileName', logFile);
+        this.fetchContentForLogFile(this.get('selectedContainerId'), logFile).then((content) => {
+          this.set('selectedLogFileContent', content.trim());
+        }, () => {
+          this.set('selectedLogFileContent', '');
+        }).always(() => {
+          this.set('_isLoadingBottomPanel', false);
+        });
+      } else {
+        this.set('selectedLogFileContent', '');
+      }
+    },
+
+    findNextTextInLogContent() {
+      let searchInputElem = document.getElementById('logSeachInput98765');
+      this.send('searchTextInLogContent', searchInputElem.value);
+    },
+
+    searchTextInLogContent(searchText) {
+      Ember.$('body').scrollTop(278);
+      let textAreaElem = document.getElementById('logContentTextArea1234554321');
+      let logContent = textAreaElem.innerText;
+      let startIndex = this.searchTextStartIndex || 0;
+      if (startIndex === -1) {
+        startIndex = this.searchTextStartIndex = 0;
+      }
+      if (this.prevSearchText !== searchText) {
+        startIndex = this.searchTextStartIndex = 0;
+      }
+      if (searchText && searchText.trim()) {
+        searchText = searchText.trim();
+        this.prevSearchText = searchText;
+        if (startIndex === 0) {
+          startIndex = logContent.indexOf(searchText, 0);
+        }
+        let endIndex = startIndex + searchText.length;
+        if (document.createRange && window.getSelection) {
+          let range = document.createRange();
+          range.selectNodeContents(textAreaElem);
+          range.setStart(textAreaElem.childNodes.item(0), startIndex);
+          range.setEnd(textAreaElem.childNodes.item(0), endIndex);
+          let selection = window.getSelection();
+          selection.removeAllRanges();
+          selection.addRange(range);
+        }
+        this.searchTextStartIndex = logContent.indexOf(searchText, endIndex + 1);
+      } else {
+        this.searchTextStartIndex = 0;
+      }
+    },
+
+    showFullLogFileContent() {
+      this.set('showFullLog', true);
+      this.notifyPropertyChange('selectedLogFileContent');
+    }
+  },
+
+  attemptList: Ember.computed('model.attempts', function() {
+    let attempts = this.get('model.attempts');
+    let list = null;
+    if (attempts && attempts.get('length') && attempts.get('content')) {
+      list = [].concat(attempts.get('content'));
+    }
+    return list;
+  }),
+
+  fetchContainersForAttemptId(attemptId) {
+    return Ember.RSVP.hash({
+      rmContainers: this.store.query('yarn-container', {
+        app_attempt_id: attemptId
+      }).catch(function() {
+        return Ember.A();
+      }),
+      tsContainers: this.store.query('yarn-timeline-container', {
+        app_attempt_id: attemptId
+      }).catch(function() {
+        return Ember.A();
+      })
+    });
+  },
+
+  fetchLogFilesForContainerId(containerId) {
+    return Ember.RSVP.hash({
+      logs: this.store.query('yarn-log', {
+        containerId: containerId
+      }).catch(function() {
+        return Ember.A();
+      })
+    });
+  },
+
+  fetchContentForLogFile(containerId, logFile) {
+    let logAdapter = this.store.adapterFor('yarn-log');
+    return logAdapter.fetchLogFileContent(containerId, logFile);
+  },
+
+  resetAfterRefresh() {
+    this.set('selectedAttemptId', '');
+    this.set('attemptContainerList', null);
+    this.set('selectedContainerId', '');
+    this.set('selectedLogFileName', '');
+    this.set('containerLogFiles', null);
+    this.set('selectedLogFileContent', '');
+  },
+
+  showFullLog: false,
+
+  showLastFewLinesOfLogContent: Ember.computed('selectedLogFileContent', function() {
+    let content = this.get('selectedLogFileContent');
+    let lines = content.split('\n');
+    if (this.get('showFullLog') || lines.length < 10) {
+      return content;
+    }
+    return lines.slice(lines.length - 10).join('\n');
+  })
+
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-log.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-log.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-log.js
new file mode 100644
index 0000000..f022bc7
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-log.js
@@ -0,0 +1,27 @@
+/**
+ * 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 DS from 'ember-data';
+
+export default DS.Model.extend({
+  fileName: DS.attr('string'),
+  fileSize: DS.attr('string'),
+  lastModifiedTime: DS.attr('string'),
+  containerId: DS.attr('string'),
+  nodeId: DS.attr('string')
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js
index dea2733..bd7af21 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js
@@ -60,6 +60,7 @@ Router.map(function() {
     this.route('components');
     this.route('charts');
     this.route('configs');
+    this.route('logs');
   });
   this.route('yarn-component-instances', function() {
     this.route('info', {path: '/:component_name/info'});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js
index b561bf6..829cfe9 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js
@@ -26,11 +26,13 @@ export default AbstractRoute.extend(AppAttemptMixin, {
       attempt: this.fetchAttemptInfoFromRMorATS(param.app_attempt_id, this.store),
       rmContainers: this.store.query('yarn-container', {
         app_attempt_id: param.app_attempt_id
+      }).catch(function() {
+        return Ember.A();
       }),
       tsContainers: this.store.query('yarn-timeline-container', {
         app_attempt_id: param.app_attempt_id
       }).catch(function() {
-        return [];
+        return Ember.A();
       })
     });
   },

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/attempts.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/attempts.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/attempts.js
index 339a10d..451ecc2 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/attempts.js
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/attempts.js
@@ -29,7 +29,9 @@ export default AbstractRoute.extend(AppAttemptMixin, {
     return Ember.RSVP.hash({
       appId: app_id,
       serviceName: service,
-      attempts: this.fetchAttemptListFromRMorATS(app_id, this.store)
+      attempts: this.fetchAttemptListFromRMorATS(app_id, this.store).catch(function() {
+        return Ember.A();
+      })
     });
   },
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/logs.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/logs.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/logs.js
new file mode 100644
index 0000000..66eb662
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app/logs.js
@@ -0,0 +1,47 @@
+/**
+ * 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) {
+    const { app_id } = this.paramsFor('yarn-app');
+    const { service } = param;
+    transition.send('updateBreadcrumbs', app_id, service, [{text: 'Logs'}]);
+    return Ember.RSVP.hash({
+      appId: app_id,
+      serviceName: service,
+      attempts: this.fetchAttemptListFromRMorATS(app_id, this.store).catch(function() {
+        return [];
+      })
+    });
+  },
+
+  unloadAll() {
+    this.store.unloadAll('yarn-app-attempt');
+    this.store.unloadAll('yarn-timeline-appattempt');
+    this.store.unloadAll('yarn-container');
+    this.store.unloadAll('yarn-timeline-container');
+    this.store.unloadAll('yarn-log');
+    if (this.controller) {
+      this.controller.resetAfterRefresh();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-log.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-log.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-log.js
new file mode 100644
index 0000000..93174d0
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-log.js
@@ -0,0 +1,48 @@
+/**
+ * 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 DS from 'ember-data';
+
+export default DS.JSONAPISerializer.extend({
+  internalNormalizeSingleResponse(store, primaryModelClass, payload, containerId, nodeId) {
+    var fixedPayload = {
+      id: "yarn_log_" + payload.fileName + "_" + Date.now(),
+      type: primaryModelClass.modelName,
+      attributes: {
+        fileName: payload.fileName,
+        fileSize: payload.fileSize,
+        lastModifiedTime: payload.lastModifiedTime,
+        containerId: containerId,
+        nodeId: nodeId
+      }
+    };
+    return fixedPayload;
+  },
+
+  normalizeArrayResponse(store, primaryModelClass, payload/*, id, requestType*/) {
+    var normalizedArrayResponse = {
+      data: []
+    };
+    if (payload && payload.containerLogsInfo && payload.containerLogsInfo.containerLogInfo) {
+      normalizedArrayResponse.data = payload.containerLogsInfo.containerLogInfo.map((paylog) => {
+        return this.internalNormalizeSingleResponse(store, primaryModelClass, paylog,
+          payload.containerLogsInfo.containerId, payload.containerLogsInfo.nodeId);
+      });
+    }
+    return normalizedArrayResponse;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/collapsible-panel.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/collapsible-panel.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/collapsible-panel.hbs
new file mode 100644
index 0000000..aab80b1
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/collapsible-panel.hbs
@@ -0,0 +1,21 @@
+{{!
+ * 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.
+}}
+
+<a class="pull-right toggle_switch" href="#" {{action "togglePanelCollapse"}}>
+  <span class="glyphicon glyphicon-chevron-up"></span>
+</a>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs
index 9e32e47..13348b2 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs
@@ -25,49 +25,41 @@
         Containers
       {{/if}}
     </div>
-    {{#if isDataEmpty}}
-      <ul class="nav nav-tabs" role="tablist">
-        <li class="active">
-          <a href="#graphViewTab" role="tab" data-toggle="tab">Graph View</a>
-        </li>
-        <li class="">
-          <a href="#gridViewTab" role="tab" data-toggle="tab">Grid View</a>
-        </li>
-      </ul>
-      <div class="panel-body">
-        <div class="tab-content">
-          <div role="tabpanel" class="tab-pane active" id="graphViewTab">
-            <br/><br/>
-            <div class="col-md-7 container-fluid" id={{parent-id}}></div>
-            <!-- diag info -->
-            <div class="col-md-5 container-fluid">
-              <div class="panel panel-default add-ellipsis attempt-info-panel">
-                <div class="panel-heading">
-                  {{#if selected.link}}
-                    {{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}}
-                  {{else}}
-                    {{selected.id}}
-                  {{/if}}
-                </div>
-                {{#if attemptModel}}
-                  {{app-attempt-table attempt=selected}}
+    <ul class="nav nav-tabs" role="tablist">
+      <li class="active">
+        <a href="#graphViewTab" role="tab" data-toggle="tab">Graph View</a>
+      </li>
+      <li class="">
+        <a href="#gridViewTab" role="tab" data-toggle="tab">Grid View</a>
+      </li>
+    </ul>
+    <div class="panel-body">
+      <div class="tab-content">
+        <div role="tabpanel" class="tab-pane active" id="graphViewTab">
+          <br/><br/>
+          <div class="col-md-7 container-fluid" id={{parent-id}}></div>
+          <!-- diag info -->
+          <div class="col-md-5 container-fluid">
+            <div class="panel panel-default add-ellipsis attempt-info-panel">
+              <div class="panel-heading">
+                {{#if selected.link}}
+                  {{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}}
                 {{else}}
-                  {{container-table container=selected}}
+                  {{selected.id}}
                 {{/if}}
               </div>
+              {{#if attemptModel}}
+                {{app-attempt-table attempt=selected}}
+              {{else}}
+                {{container-table container=selected}}
+              {{/if}}
             </div>
           </div>
-          <div role="tabpanel" class="tab-pane" id="gridViewTab">
-            {{em-table columns=gridColumns rows=gridRows}}
-          </div>
+        </div>
+        <div role="tabpanel" class="tab-pane" id="gridViewTab">
+          {{em-table columns=gridColumns rows=gridRows}}
         </div>
       </div>
-    {{else}}
-      <div class="panel-body">
-        <h4 class="text-center">No data available!</h4>
-      </div>
-    {{/if}}
+    </div>
   </div>
 </div>
-
-{{outlet}}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs
index 7579bdc..2e2f6d0 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs
@@ -48,7 +48,26 @@
     </div>
     <div class="row">
       {{#if (or model.rmContainers model.tsContainers)}}
-        {{timeline-view parent-id="containers-timeline-div" my-id="timeline-view" height="400" rmModel=model.rmContainers tsModel=model.tsContainers label="shortAppAttemptId" attemptModel=false}}
+        {{timeline-view
+          parent-id="containers-timeline-div"
+          my-id="timeline-view"
+          height="400"
+          rmModel=model.rmContainers
+          tsModel=model.tsContainers
+          label="shortAppAttemptId"
+          attemptModel=false
+        }}
+      {{else}}
+        <div class="col-md-12 container-fluid">
+          <div class="panel panel-default">
+            <div class="panel-heading">
+               Containers
+            </div>
+            <div class="panel-body">
+              <h4 class="text-center">No data available!</h4>
+            </div>
+          </div>
+        </div>
       {{/if}}
     </div>
   </div>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs
index fc40837..ca93428 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs
@@ -125,6 +125,9 @@
             {{#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=model.serviceName)}}Diagnostics{{/link-to}}
             {{/link-to}}
+            {{#link-to 'yarn-app.logs' tagName="li" class=(if (eq target.currentPath 'yarn-app.logs') "active")}}
+              {{#link-to 'yarn-app.logs' appId (query-params service=serviceName)}}Logs{{/link-to}}
+            {{/link-to}}
           </ul>
         </ul>
       </div>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/attempts.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/attempts.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/attempts.hbs
index 37ed079..5857d89 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/attempts.hbs
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/attempts.hbs
@@ -17,6 +17,7 @@
 }}
 
 <div>
+{{#if model.attempts}}
   {{timeline-view
     parent-id="attempt-timeline-div"
     my-id="timeline-view"
@@ -26,4 +27,16 @@
     attemptModel=true
     serviceName=model.serviceName
   }}
+{{else}}
+  <div class="col-md-12 container-fluid">
+    <div class="panel panel-default">
+      <div class="panel-heading">
+         Application Attempts
+      </div>
+      <div class="panel-body">
+        <h4 class="text-center">No data available!</h4>
+      </div>
+    </div>
+  </div>
+{{/if}}
 </div>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/logs.hbs
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/logs.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/logs.hbs
new file mode 100644
index 0000000..34c6ee1
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app/logs.hbs
@@ -0,0 +1,132 @@
+{{!
+ * 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">
+    <div class="panel panel-default">
+      <div class="panel-heading">
+        Logs {{collapsible-panel targetId="logFilesCollapsablePanel"}}
+      </div>
+      <div class="panel-body" id="logFilesCollapsablePanel">
+        {{#if _isLoadingTopPanel}}
+          <div class="text-center" style="z-index: 100; position: absolute; left: 46%;">
+            <img src="assets/images/spinner.gif" alt="Loading...">
+          </div>
+        {{/if}}
+        {{#if attemptList}}
+          <div class="row">
+            <div class="col-md-6">
+              <label>Choose attempt to fetch containers</label>
+              <select class="form-control" onchange={{action "showContainersForAttemptId" value="target.value"}} style="max-width:350px;">
+                <option value="" selected={{eq selectedAttemptId ''}}>None</option>
+                {{#each attemptList as |attempt|}}
+                  <option value="{{attempt.id}}" selected={{eq selectedAttemptId attempt.id}}>{{attempt.id}}</option>
+                {{/each}}
+              </select>
+            </div>
+            {{#if attemptContainerList}}
+              <div class="col-md-6">
+                <label>Choose container to fetch logs</label>
+                <select class="form-control" onchange={{action "showLogFilesForContainerId" value="target.value"}} style="max-width:350px">
+                  <option value="" selected={{eq selectedContainerId ''}}>None</option>
+                  {{#each attemptContainerList as |container|}}
+                    <option value="{{container.id}}" selected={{eq selectedContainerId container.id}}>{{container.id}}</option>
+                  {{/each}}
+                </select>
+              </div>
+            {{else}}
+              {{#if (and selectedAttemptId (not _isLoadingTopPanel))}}
+                <div class="col-md-4">
+                  <h4 class="text-center" style="margin-top:25px;">No container data available!</h4>
+                </div>
+              {{/if}}
+            {{/if}}
+          </div>
+        {{else}}
+          <div class="col-md-12">
+            <h4 class="text-center">No data available!</h4>
+          </div>
+        {{/if}}
+      </div>
+    </div>
+  </div>
+</div>
+{{#if selectedContainerId}}
+  <div class="row">
+    <div class="col-md-12">
+      <div class="panel panel-default" style="min-height:150px;">
+        <div class="panel-heading">
+          Log: {{selectedLogFileName}} [ {{selectedContainerId}} &amp; {{selectedAttemptId}} ]
+          {{collapsible-panel targetId="logContentCollapsablePanel"}}
+        </div>
+        <div class="panel-body" id="logContentCollapsablePanel">
+          {{#if _isLoadingBottomPanel}}
+            <div class="text-center" style="z-index: 100; position: absolute; left: 46%;">
+              <img src="assets/images/spinner.gif" alt="Loading...">
+            </div>
+          {{/if}}
+          {{#if containerLogFiles}}
+            <div class="row">
+              <div class="col-md-6" style="margin-bottom:20px;">
+                <label>Choose log for {{selectedContainerId}}</label>
+                <select class="form-control" onchange={{action "showContentForLogFile" value="target.value"}} style="max-width:350px">
+                  <option value="" selected={{eq selectedLogFileName ''}}>None</option>
+                  {{#each containerLogFiles as |file|}}
+                    <option value="{{file.fileName}}" selected={{eq selectedLogFileName file.fileName}}>{{file.fileName}} - {{file.fileSize}} bytes</option>
+                  {{/each}}
+                </select>
+              </div>
+              {{#if selectedLogFileName}}
+                <div class="col-md-6">
+                  <label>Find in log</label>
+                  <div class="input-group" style="max-width:350px;">
+                    {{input
+                      class="form-control"
+                      value=""
+                      enter="searchTextInLogContent"
+                      id="logSeachInput98765"
+                    }}
+                    <span class="input-group-btn">
+                      <button class="btn btn-default" {{action "findNextTextInLogContent"}}>Find</button>
+                    </span>
+                  </div>
+                </div>
+              {{/if}}
+            </div>
+            <div class="row">
+              {{#if selectedLogFileContent}}
+                {{#unless showFullLog}}
+                  <div class="col-md-12">
+                    <strong>Showing last 10 lines of log. Click <a href="#" {{action "showFullLogFileContent"}}>here</a> for full log.</strong>
+                  </div>
+                {{/unless}}
+                <pre id="logContentTextArea1234554321" class="log-content-area">{{showLastFewLinesOfLogContent}}</pre>
+              {{/if}}
+            </div>
+          {{else}}
+            {{#unless _isLoadingBottomPanel}}
+              <div class="col-md-12" style="margin-top:20px;">
+                <h4 class="text-center">No log data available!</h4>
+              </div>
+            {{/unless}}
+          {{/if}}
+        </div>
+      </div>
+    </div>
+  </div>
+{{/if}}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/bower-shrinkwrap.json
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/bower-shrinkwrap.json b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/bower-shrinkwrap.json
index b0f3aa3..ffe3805 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/bower-shrinkwrap.json
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/bower-shrinkwrap.json
@@ -1,6 +1,6 @@
 {
   "https://github.com/DataTables/DataTables.git": {
-    "1.10.15": "1.10.15"
+    "1.10.15": "84d24d41477bac7657c9ddfa1d86245f9affc879"
   },
   "https://github.com/components/ember-data.git": {
     "2.1.0": "d8b4d3092f67afe22d9d374c40d719d557915fa3"
@@ -27,10 +27,10 @@
     "0.1.7": "7bb21488563bd1bba23e903a812bf5815beddd1a"
   },
   "https://github.com/fgnass/spin.js.git": {
-    "2.3.2": "2.3.2"
+    "2.3.2": "5a9ea41651105302fe76d15cb294070c5863e759"
   },
   "https://github.com/ivaynberg/select2.git": {
-    "4.0.0": "4.0.0"
+    "4.0.0": "80eb44bec78568b152dc5547269c164cb7b5363c"
   },
   "https://github.com/jquery/jquery-dist.git": {
     "2.1.4": "7751e69b615c6eca6f783a81e292a55725af6b85"
@@ -39,20 +39,20 @@
     "1.19.0": "467e7e34652ad7d5883ce9c568461cf8c5e172a8"
   },
   "https://github.com/mbostock-bower/d3-bower.git": {
-    "3.5.17": "3.5.17"
+    "3.5.17": "abe0262a205c9f3755c3a757de4dfd1d49f34b24"
   },
   "https://github.com/moment/moment-timezone.git": {
     "0.5.0": "74a2e9378ecf4a31a168f3049f086565c8d66814"
   },
   "https://github.com/moment/moment.git": {
-    "2.10.6": "2.10.6",
+    "2.10.6": "446ce77eb08c5c862d7b0b11ef1d2e884d12e3d7",
     "2.12.0": "d3d7488b4d60632854181cb0a9af325d57fb3d51"
   },
   "https://github.com/rwjblue/ember-qunit-builds.git": {
     "0.4.16": "142c4066a5458bef9dfcb92b70152b9c01d79188"
   },
   "https://github.com/sreenaths/more-js.git": {
-    "0.8.2": "0.8.2"
+    "0.8.2": "015ab7c7dad2dc9edc0049b8b65aeb020fd20c51"
   },
   "https://github.com/sreenaths/snippet-ss.git": {
     "1.11.0": "c1abc566f4e001b7f1939b6dbdd911eadc969cf9"

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/collapsible-panel-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/collapsible-panel-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/collapsible-panel-test.js
new file mode 100644
index 0000000..b80eb07
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/collapsible-panel-test.js
@@ -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('collapsible-panel', 'Integration | Component | collapsible panel', {
+  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`{{collapsible-panel}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#collapsible-panel}}
+      template block text
+    {{/collapsible-panel}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/adapters/yarn-log-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/adapters/yarn-log-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/adapters/yarn-log-test.js
new file mode 100644
index 0000000..04664cc
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/adapters/yarn-log-test.js
@@ -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('adapter:yarn-log', 'Unit | Adapter | yarn log', {
+  // Specify the other units that are required for this test.
+  // needs: ['serializer:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  let adapter = this.subject();
+  assert.ok(adapter);
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/controllers/yarn-app/logs-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/controllers/yarn-app/logs-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/controllers/yarn-app/logs-test.js
new file mode 100644
index 0000000..87c8dde
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/controllers/yarn-app/logs-test.js
@@ -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/logs', 'Unit | Controller | yarn app/logs', {
+  // 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);
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/models/yarn-log-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/models/yarn-log-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/models/yarn-log-test.js
new file mode 100644
index 0000000..6c331b4
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/models/yarn-log-test.js
@@ -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 { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('yarn-log', 'Unit | Model | yarn log', {
+  // Specify the other units that are required for this test.
+  needs: []
+});
+
+test('it exists', function(assert) {
+  let model = this.subject();
+  // let store = this.store();
+  assert.ok(!!model);
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-app/logs-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-app/logs-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-app/logs-test.js
new file mode 100644
index 0000000..e1bc64e
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-app/logs-test.js
@@ -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/logs', 'Unit | Route | yarn app/logs', {
+  // 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);
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/99ccca34/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/serializers/yarn-log-test.js
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/serializers/yarn-log-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/serializers/yarn-log-test.js
new file mode 100644
index 0000000..a84e689
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/serializers/yarn-log-test.js
@@ -0,0 +1,33 @@
+/**
+ * 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 { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('yarn-log', 'Unit | Serializer | yarn log', {
+  // Specify the other units that are required for this test.
+  needs: ['serializer:yarn-log']
+});
+
+// Replace this with your real tests.
+test('it serializes records', function(assert) {
+  let record = this.subject();
+
+  let serializedRecord = record.serialize();
+
+  assert.ok(serializedRecord);
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org