Kaynağa Gözat

AMBARI-7626. Slider View: UI should not use view parameters. (onechiporenko via srimanth)

Srimanth Gunturi 11 yıl önce
ebeveyn
işleme
659682d86f

+ 8 - 0
contrib/views/slider/src/main/resources/ui/app/assets/data/resource/slider-properties-2.json

@@ -0,0 +1,8 @@
+{
+  "version": "1.0.0",
+  "validation": [],
+  "parameters": {
+    "gangliaHost": "c6401.ambari.apache.org",
+    "gangliaClusters": "App1:8881,App2:8882"
+  }
+}

+ 13 - 40
contrib/views/slider/src/main/resources/ui/app/controllers/slider_controller.js

@@ -21,7 +21,7 @@
  * After this set <code>App.sliderConfig</code>-models and enable/disable Slider
  * After this set <code>App.sliderConfig</code>-models and enable/disable Slider
  * @type {Ember.Controller}
  * @type {Ember.Controller}
  */
  */
-App.SliderController = Ember.Controller.extend({
+App.SliderController = Ember.Controller.extend(App.RunPeriodically, {
 
 
   /**
   /**
    *  Load resources on controller initialization
    *  Load resources on controller initialization
@@ -39,10 +39,9 @@ App.SliderController = Ember.Controller.extend({
    */
    */
   getParametersFromViewProperties: function () {
   getParametersFromViewProperties: function () {
     return App.ajax.send({
     return App.ajax.send({
-      name: 'slider.getViewParams',
+      name: 'slider.getViewParams.v2',
       sender: this,
       sender: this,
-      success: 'getParametersFromViewPropertiesSuccessCallback',
-      error: 'finishSliderConfiguration'
+      success: 'getParametersFromViewPropertiesSuccessCallback'
     });
     });
   },
   },
 
 
@@ -54,17 +53,14 @@ App.SliderController = Ember.Controller.extend({
    * @method getParametersFromViewPropertiesSuccessCallback
    * @method getParametersFromViewPropertiesSuccessCallback
    */
    */
   getParametersFromViewPropertiesSuccessCallback: function (data) {
   getParametersFromViewPropertiesSuccessCallback: function (data) {
-    var properties = Em.get(data, 'ViewInstanceInfo.properties'),
-      initialValuesToLoad = this.get('initialValuesToLoad'),
-      sliderConfigs = App.SliderApp.store.all('sliderConfig'),
-      self = this;
-    App.set('label', Em.get(data, 'ViewInstanceInfo.label') || App.get('instance'));
+    var properties = Em.get(data, 'parameters'),
+      sliderConfigs = App.SliderApp.store.all('sliderConfig');
     sliderConfigs.forEach(function (model) {
     sliderConfigs.forEach(function (model) {
       var key = model.get('viewConfigName');
       var key = model.get('viewConfigName');
       model.set('value', properties[key]);
       model.set('value', properties[key]);
     });
     });
-    self.finishSliderConfiguration();
-    self.initGangliaProperties();
+    this.initGangliaProperties();
+    this.finishSliderConfiguration(data);
   },
   },
 
 
   /**
   /**
@@ -72,8 +68,8 @@ App.SliderController = Ember.Controller.extend({
    */
    */
   initGangliaProperties: function () {
   initGangliaProperties: function () {
     var sliderConfigs = App.SliderApp.store.all('sliderConfig'),
     var sliderConfigs = App.SliderApp.store.all('sliderConfig'),
-      gangliaClusters = sliderConfigs.findBy('viewConfigName', 'ganglia.additional.clusters'),
-      gangliaHost = sliderConfigs.findBy('viewConfigName', 'ganglia.server.hostname');
+      gangliaClusters = sliderConfigs.findBy('viewConfigName', 'gangliaClusters'),
+      gangliaHost = sliderConfigs.findBy('viewConfigName', 'gangliaHost');
     App.set('gangliaClusters', this.formatGangliaClusters(gangliaClusters.get('value')));
     App.set('gangliaClusters', this.formatGangliaClusters(gangliaClusters.get('value')));
     App.set('gangliaHost', gangliaHost.get('value'));
     App.set('gangliaHost', gangliaHost.get('value'));
   },
   },
@@ -103,36 +99,13 @@ App.SliderController = Ember.Controller.extend({
 
 
   /**
   /**
    * After all Slider-configs are loaded, application should check self status
    * After all Slider-configs are loaded, application should check self status
-   * If config <code>required</code>-property is true, its value shouldn't be empty
-   * If config depends on some other config (see <code>requireDependsOn</code>-property)
-   * and referenced config-value is not-false, current config should have not-empty value
+   * @param {object} data - received from server information about current Slider-status
    * @method finishSliderConfiguration
    * @method finishSliderConfiguration
    */
    */
-  finishSliderConfiguration: function () {
-    //check if all services exist
-    var errors = [];
-    App.SliderApp.store.all('sliderConfig').forEach(function (model) {
-      if (model.get('required')) {
-        if (Em.isEmpty(model.get('value'))) {
-          errors.push(Em.I18n.t('error.config_is_empty').format(model.get('viewConfigName')));
-        }
-      }
-      else {
-        var dependenceConfig = model.get('requireDependsOn');
-        if (!Em.isNone(dependenceConfig)) {
-          var depValue = dependenceConfig.get('value').toLowerCase();
-          if (depValue == "true") {
-            if (Em.isEmpty(model.get('value'))) {
-              errors.push(Em.I18n.t('error.config_is_empty_2').format(model.get('viewConfigName'), dependenceConfig.get('viewConfigName')));
-            }
-          }
-        }
-      }
-    });
-    errors.uniq();
+  finishSliderConfiguration: function (data) {
     App.setProperties({
     App.setProperties({
-      viewErrors: errors,
-      viewEnabled: errors.length === 0,
+      viewErrors: data.validations,
+      viewEnabled: data.validations.length === 0,
       mapperTime: new Date().getTime()
       mapperTime: new Date().getTime()
     });
     });
   }
   }

+ 20 - 0
contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js

@@ -47,6 +47,26 @@ var urls = {
     }
     }
   },
   },
 
 
+  'slider.getViewParams.v2': {
+    real: 'resources/status',
+    mock: '/data/resource/slider-properties-2.json',
+    headers: {
+      "Accept": "application/json; charset=utf-8",
+      "Content-Type": "text/plain; charset=utf-8"
+    },
+    schema: {
+      required: ['version', 'validation', 'parameters'],
+      properties: {
+        validation: {
+          type: 'array'
+        },
+        parameters: {
+          type : 'object'
+        }
+      }
+    }
+  },
+
   'mapper.applicationTypes': {
   'mapper.applicationTypes': {
     real: 'apptypes?fields=*',
     real: 'apptypes?fields=*',
     mock: '/data/apptypes/all_fields.json',
     mock: '/data/apptypes/all_fields.json',

+ 3 - 8
contrib/views/slider/src/main/resources/ui/app/initialize.js

@@ -67,7 +67,7 @@ App.initializer({
       /**
       /**
        * @type {string}
        * @type {string}
        */
        */
-      label: '',
+      label: instanceName,
 
 
       /**
       /**
        * API url for Slider
        * API url for Slider
@@ -91,12 +91,6 @@ App.initializer({
        */
        */
       viewErrors: [],
       viewErrors: [],
 
 
-      /**
-       * Host with Nagios Server
-       * @type {string|null}
-       */
-      nagiosHost: null,
-
       /**
       /**
        * Host with Ganglia Server
        * Host with Ganglia Server
        * @type {string|null}
        * @type {string|null}
@@ -117,7 +111,8 @@ App.initializer({
 
 
     });
     });
     if(!window.QUnit) {
     if(!window.QUnit) {
-      application.SliderController.proto().initResources();
+      var sliderController = application.__container__.lookup('controller:Slider');
+      sliderController.run('initResources');
       application.ApplicationTypeMapper.load();
       application.ApplicationTypeMapper.load();
       application.SliderAppsMapper.run('load');
       application.SliderAppsMapper.run('load');
     }
     }

+ 1 - 13
contrib/views/slider/src/main/resources/ui/app/models/slider_config.js

@@ -38,19 +38,7 @@ App.SliderConfig = DS.Model.extend({
   /**
   /**
    * @type {null|string}
    * @type {null|string}
    */
    */
-  value: null,
-
-  /**
-   * Is property required
-   * @type {bool}
-   */
-  required: DS.attr('bool'),
-
-  /**
-   * If provided config has not-false value current config shouldn't be empty
-   * @type {App.SliderConfig}
-   */
-  requireDependsOn: DS.belongsTo('sliderConfig')
+  value: null
 
 
 });
 });
 
 

+ 2 - 16
contrib/views/slider/src/main/resources/ui/app/routes/main.js

@@ -52,22 +52,8 @@ App.SliderAppsRoute = Ember.Route.extend({
 
 
     // Load sliderConfigs to storage
     // Load sliderConfigs to storage
     App.SliderApp.store.pushMany('sliderConfig', Em.A([
     App.SliderApp.store.pushMany('sliderConfig', Em.A([
-      Em.Object.create({id: 1, required: true, viewConfigName: 'hdfs.url', displayName: 'hdfsAddress', linkedService: 'HDFS'}),
-      Em.Object.create({id: 2, required: true, viewConfigName: 'yarn.rm.url', displayName: 'yarnResourceManager', linkedService: 'YARN'}),
-      Em.Object.create({id: 3, required: true, viewConfigName: 'yarn.rm.webapp.url', displayName: 'yarnResourceManagerWebapp', linkedService: 'YARN'}),
-      Em.Object.create({id: 4, required: true, viewConfigName: 'yarn.rm.scheduler.url',  displayName: 'yarnResourceManagerScheduler'}),
-      Em.Object.create({id: 5, required: true, viewConfigName: 'zookeeper.quorum', displayName: 'zookeeperQuorum', linkedService: 'ZOOKEEPER'}),
-      Em.Object.create({id: 6, required: false, viewConfigName: 'ganglia.server.hostname', displayName: 'gangliaServer'}),
-      Em.Object.create({id: 7, required: false, viewConfigName: 'ganglia.additional.clusters', displayName: 'gangliaClusters'}),
-      Em.Object.create({id: 8, required: false, viewConfigName: 'slider.user', displayName: 'sliderUser'}),
-      Em.Object.create({id: 9, required: true, viewConfigName: 'slider.security.enabled', displayName: 'sliderSecurityEnabled'}),
-      Em.Object.create({id: 10, required: false, requireDependsOn: 9, viewConfigName: 'yarn.rm.kerberos.principal', displayName: 'yarnResourceManagerPrincipal'}),
-      Em.Object.create({id: 11, required: false, requireDependsOn: 9, viewConfigName: 'dfs.namenode.kerberos.principal', displayName: 'dfsNamenodeKerberosPrincipal'}),
-      Em.Object.create({id: 12, required: false, requireDependsOn: 9, viewConfigName: 'view.kerberos.principal', displayName: 'viewKerberosPrincipal'}),
-      Em.Object.create({id: 13, required: false, requireDependsOn: 9, viewConfigName: 'view.kerberos.principal.keytab', displayName: 'ViewKerberosPrincipalKeytab'}),
-      Em.Object.create({id: 14, required: false, viewConfigName: 'yarm.rm.ha.hosts', displayName: 'yarnResourceManagerHighAvailabilityHosts'}),
-      Em.Object.create({id: 15, required: false, viewConfigName: 'yarn.rm.store.class', displayName: 'yarnResourceManagerStoreClass'}),
-      Em.Object.create({id: 16, required: false, viewConfigName: 'yarn.rm.ha.automatic-failover.zk-base-path', displayName: 'yarnResourceManagerHighAvailabilityAutoFailoverZooKeeperBasePath'})
+      Em.Object.create({id: 1, required: false, viewConfigName: 'gangliaHost', displayName: 'gangliaServer'}),
+      Em.Object.create({id: 2, required: false, viewConfigName: 'gangliaClusters', displayName: 'gangliaClusters'})
     ]));
     ]));
   },
   },
 
 

+ 11 - 0
contrib/views/slider/src/main/resources/ui/app/styles/common.less

@@ -103,3 +103,14 @@ select {
 .modal-backdrop.in {
 .modal-backdrop.in {
   opacity:0;
   opacity:0;
 }
 }
+
+
+.slider-errors-wrapper {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  padding: 10px;
+  background-color: #fff;
+}

+ 18 - 7
contrib/views/slider/src/main/resources/ui/app/templates/application.hbs

@@ -16,6 +16,22 @@
 * limitations under the License.
 * limitations under the License.
 }}
 }}
 
 
+{{!
+  DON'T TRY TO PUT OUTLET INTO CONDITIONAL STATES
+  https://github.com/emberjs/ember.js/issues/3187 - CLOSED BUT NOT FIXED YET
+}}
+
+
+{{#unless App.viewEnabled}}
+  <div class="slider-errors-wrapper">
+    <div class="alert alert-danger">
+      {{#each error in App.viewErrors}}
+        <h3 class="error-message">{{{error.message}}}</h3>
+      {{/each}}
+    </div>
+  </div>
+{{/unless}}
+
 <div class="slider-header">
 <div class="slider-header">
   {{#view view.SliderTitleView}}
   {{#view view.SliderTitleView}}
       <h3 class="pull-left" id="slider-title"><span class="slider-app-title">{{App.label}}</span></h3>
       <h3 class="pull-left" id="slider-title"><span class="slider-app-title">{{App.label}}</span></h3>
@@ -31,10 +47,5 @@
   {{/view}}
   {{/view}}
   {{outlet bs-tooltip-box}}
   {{outlet bs-tooltip-box}}
 </div>
 </div>
-{{#if App.viewEnabled}}
-  {{outlet}}
-{{else}}
-  {{#each error in App.viewErrors}}
-    <h3>{{{error}}}</h3>
-  {{/each}}
-{{/if}}
+
+{{outlet}}

+ 0 - 7
contrib/views/slider/src/main/resources/ui/app/templates/slider_app/summary.hbs

@@ -61,13 +61,6 @@
       <div class="panel-heading">
       <div class="panel-heading">
         {{t common.status}}
         {{t common.status}}
         <div class="btn-group pull-right panel-link">
         <div class="btn-group pull-right panel-link">
-          {{#if App.nagiosHost}}
-            <a class="btn btn-default btn-sm" target="_blank" rel="tooltip"
-              {{translateAttr title="sliderApp.summary.go_to_nagios"}}
-              {{bind-attr href="view.nagiosUrl"}}>
-              <i class="icon-link"></i>
-            </a>
-          {{/if}}
         </div>
         </div>
       </div>
       </div>
       <div class="app-alerts">
       <div class="app-alerts">

+ 0 - 7
contrib/views/slider/src/main/resources/ui/app/views/slider_app/summary_view.js

@@ -96,13 +96,6 @@ App.SliderAppSummaryView = Ember.View.extend({
     return 'http://' + App.get('gangliaHost') + '/ganglia';
     return 'http://' + App.get('gangliaHost') + '/ganglia';
   }.property('App.gangliaHost', 'controller.model.quickLinks.@each.url'),
   }.property('App.gangliaHost', 'controller.model.quickLinks.@each.url'),
 
 
-  /**
-   * @type {string}
-   */
-  nagiosUrl: function () {
-    return 'http://' + App.get('nagiosHost') + '/nagios';
-  }.property('App.nagiosHost'),
-
   didInsertElement: function() {
   didInsertElement: function() {
     var self = this;
     var self = this;
     Em.run.next(function() {
     Em.run.next(function() {

+ 1 - 1
contrib/views/slider/src/main/resources/ui/test/integration/pages/index_test.js

@@ -44,7 +44,7 @@ test('sliderConfigs', function () {
 
 
   visit('/');
   visit('/');
   // configs count may be changed by adding new slider-configs
   // configs count may be changed by adding new slider-configs
-  equal(App.SliderApp.store.all('sliderConfig').content.length, 16, 'slider configs should be set');
+  equal(App.SliderApp.store.all('sliderConfig').content.length, 2, 'slider configs should be set');
 
 
 });
 });
 
 

+ 46 - 0
contrib/views/slider/src/main/resources/ui/test/integration/pages/slider_errors_test.js

@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+QUnit.module('integration/pages - index', {
+
+  setup: function () {
+    Ember.run(App, App.advanceReadiness);
+    Em.run(function () {
+      var p = {
+        validation: [
+          {message: 'Some mythical error'},
+          {message: 'Error with DNA'}
+        ],
+        parameters: {}
+      };
+      App.__container__.lookup('controller:Slider').getParametersFromViewPropertiesSuccessCallback(p);
+    });
+  },
+
+  teardown: function () {
+    App.reset();
+  }
+
+});
+
+test('Slider has validation errors', function () {
+
+  visit('/');
+  equal(find('.slider-errors-wrapper .error-message').length, 2, 'Error-messages exist on the page');
+
+});