Repository: ambari
Updated Branches:
  refs/heads/trunk 5b75e7abf -> 841483b9b


AMBARI-8672. Config validations not displaying ERRORs (Buzhor Denys via 
srimanth)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/841483b9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/841483b9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/841483b9

Branch: refs/heads/trunk
Commit: 841483b9bf05e7887aa02a60fb2594a3f36d39bd
Parents: 5b75e7a
Author: Srimanth Gunturi <sgunt...@hortonworks.com>
Authored: Thu Dec 11 12:06:29 2014 -0800
Committer: Srimanth Gunturi <sgunt...@hortonworks.com>
Committed: Thu Dec 11 12:06:29 2014 -0800

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 .../app/controllers/wizard/step7_controller.js  |   3 +-
 ambari-web/app/mixins/common/serverValidator.js |  28 +++-
 .../configs/config_recommendation_popup.hbs     |   9 +-
 .../test/mixins/common/serverValidator_test.js  | 134 +++++++++++++++++++
 5 files changed, 171 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/841483b9/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js 
b/ambari-web/app/assets/test/tests.js
index 8615b35..2aab326 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -127,6 +127,7 @@ var files = ['test/init_model_test',
   'test/mappers/stack_mapper_test',
   'test/mixins/common/chart/storm_linear_time_test',
   'test/mixins/common/localStorage_test',
+  'test/mixins/common/serverValidator_test',
   'test/mixins/common/table_server_view_mixin_test',
   'test/mixins/main/host/details/host_components/decommissionable_test',
   'test/mixins/wizard/addSeccurityConfigs_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/841483b9/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js 
b/ambari-web/app/controllers/wizard/step7_controller.js
index d004c05..d11e88b 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -242,7 +242,7 @@ App.WizardStep7Controller = 
Em.Controller.extend(App.ServerValidatorMixin, {
         attributeValue: filter.attributeValue,
         name: this.t(filter.caption),
         selected: false
-      })
+      });
     }, this);
   }.property('propertyFilters'),
 
@@ -256,6 +256,7 @@ App.WizardStep7Controller = 
Em.Controller.extend(App.ServerValidatorMixin, {
    * @method clearStep
    */
   clearStep: function () {
+    this.set('configValidationGlobalMessage', []);
     this.set('submitButtonClicked', false);
     this.set('isSubmitDisabled', true);
     this.set('isRecommendedLoaded', false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/841483b9/ambari-web/app/mixins/common/serverValidator.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/serverValidator.js 
b/ambari-web/app/mixins/common/serverValidator.js
index 4eccf37..449b1ee 100644
--- a/ambari-web/app/mixins/common/serverValidator.js
+++ b/ambari-web/app/mixins/common/serverValidator.js
@@ -37,6 +37,11 @@ App.ServerValidatorMixin = Em.Mixin.create({
   configValidationFailed: false,
 
   /**
+   * @type {object[]} contains additional message about validation errors
+   */
+  configValidationGlobalMessage: [],
+
+  /**
    * recommendation configs loaded from server
    * (used only during install)
    * @type {Object}
@@ -73,7 +78,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
     return this.get('content.serviceName')
         ? [App.StackService.find(this.get('content.serviceName'))]
         : this.get('content.services').filter(function(s){
-          return (s.get('isSelected') || s.get('isInstalled'))
+          return (s.get('isSelected') || s.get('isInstalled'));
         }).concat(require("data/service_configs"));
   }.property('content.serviceName', 'content.services', 
'content.services.@each.isSelected', 'content.services.@each.isInstalled', 
'content.stacks.@each.isSelected'),
 
@@ -137,6 +142,7 @@ App.ServerValidatorMixin = Em.Mixin.create({
   serverSideValidation: function () {
     var deferred = $.Deferred();
     this.set('configValidationFailed', false);
+    this.set('configValidationGlobalMessage', []);
     if (this.get('configValidationFailed')) {
       this.warnUser(deferred);
     } else {
@@ -189,6 +195,8 @@ App.ServerValidatorMixin = Em.Mixin.create({
    */
   validationSuccess: function(data) {
     var self = this;
+    var checkedProperties = [];
+    var globalWarning = [];
     self.set('configValidationError', false);
     self.set('configValidationWarning', false);
     data.resources.forEach(function(r) {
@@ -206,12 +214,28 @@ App.ServerValidatorMixin = Em.Mixin.create({
                   property.set('warnMessage', item.message);
                   property.set('warn', true);
                 }
+                // store property data to detect WARN or ERROR messages for 
missed property
+                if (["ERROR", "WARN"].contains(item.level)) 
checkedProperties.push(item['config-type'] + '/' + item['config-name']);
               }
             });
-          })
+          });
+          // check if error or warn message detected for property that absent 
in step configs
+          if (["ERROR", "WARN"].contains(item.level) && 
!checkedProperties.contains(item['config-type'] + '/' + item['config-name'])) {
+            var message = {
+              propertyName: item['config-name'],
+              filename: item['config-type'],
+              warnMessage: item.message,
+              serviceName: App.StackService.find().filter(function(service) {
+                return !!service.get('configTypes')[item['config-type']];
+              })[0].get('displayName')
+            };
+            self.set(item.level == 'WARN' ? 'configValidationWarning' : 
'configValidationError', true);
+            globalWarning.push(message);
+          }
         }
       });
     });
+    self.set('configValidationGlobalMessage', globalWarning);
   },
 
   validationError: function (jqXHR, ajaxOptions, error, opt) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/841483b9/ambari-web/app/templates/common/configs/config_recommendation_popup.hbs
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/templates/common/configs/config_recommendation_popup.hbs 
b/ambari-web/app/templates/common/configs/config_recommendation_popup.hbs
index 0a3e231..3c5a0cf 100644
--- a/ambari-web/app/templates/common/configs/config_recommendation_popup.hbs
+++ b/ambari-web/app/templates/common/configs/config_recommendation_popup.hbs
@@ -57,6 +57,13 @@
         {{/if}}
       {{/each}}
     {{/each}}
+    {{#each message in configValidationGlobalMessage}}
+      <tr>
+        <td>{{message.serviceName}}</td>
+        <td>{{message.propertyName}}</td>
+        <td colspan="2">{{message.warnMessage}} in {{message.filename}}</td>
+      </tr>
+    {{/each}}
     </tbody>
   </table>
-</div>
\ No newline at end of file
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/841483b9/ambari-web/test/mixins/common/serverValidator_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/serverValidator_test.js 
b/ambari-web/test/mixins/common/serverValidator_test.js
new file mode 100644
index 0000000..306c54b
--- /dev/null
+++ b/ambari-web/test/mixins/common/serverValidator_test.js
@@ -0,0 +1,134 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+describe('App.ServerValidatorMixin', function() {
+  var mixinObject = Em.Object.extend(App.ServerValidatorMixin, {});
+  describe('#validationSuccess', function() {
+    var instanceObject;
+    var genRespItem = function(name, filename, level, message) {
+      return {
+        type: 'configuration',
+        'config-name': name,
+        'config-type': filename,
+        level: level,
+        message: message
+      };
+    };
+    var genResponse = function(items) {
+      return {
+        items: (items.map(function(item) { return genRespItem.apply(undefined, 
item); }))
+      };
+    };
+    var genConfigs = function(configs) {
+      return Em.Object.create({
+        configs: (configs.map(function(item) {
+            return Em.Object.create({ name: item[0], filename: item[1] });
+          }))
+      });
+    };
+    var tests = [
+      {
+        stepConfigs: Em.A([
+          genConfigs([
+            ['prop1', 'some-site.xml']
+          ])
+        ]),
+        resources: [
+          genResponse([
+            ['prop1', 'some-site', 'WARN', 'Some warn'],
+            ['prop2', 'some-site', 'ERROR', 'Value should be set']
+          ])
+        ],
+        expected: [
+          { prop: 'configValidationError', value: true },
+          { prop: 'configValidationWarning', value: true },
+          { prop: 'configValidationGlobalMessage.length', value: 1 },
+          { prop: 'configValidationGlobalMessage[0].serviceName', value: 'Some 
Service' },
+          { prop: 'configValidationGlobalMessage[0].propertyName', value: 
'prop2' },
+        ],
+        message: 'validation failed on absent property from step configs. 
global message should be showed.'
+      },
+      {
+        stepConfigs: Em.A([
+          genConfigs([
+            ['prop1', 'some-site.xml'],
+            ['prop2', 'some-site.xml']
+          ])
+        ]),
+        resources: [
+          genResponse([
+            ['prop1', 'some-site', 'WARN', 'Some warn'],
+          ])
+        ],
+        expected: [
+          { prop: 'configValidationError', value: false },
+          { prop: 'configValidationWarning', value: true },
+          { prop: 'configValidationGlobalMessage.length', value: 0}
+        ],
+        message: 'all properties present in step configs. validation failed. 
Present WARN and ERROR level messages.'
+      },
+            {
+        stepConfigs: Em.A([
+          genConfigs([
+            ['prop1', 'some-site.xml'],
+            ['prop2', 'some-site.xml']
+          ])
+        ]),
+        resources: [
+          {
+            items: []
+          }
+        ],
+        expected: [
+          { prop: 'configValidationFailed', value: false },
+          { prop: 'configValidationError', value: false },
+          { prop: 'configValidationWarning', value: false },
+          { prop: 'configValidationGlobalMessage.length', value: 0}
+        ],
+        message: 'validation success. no errors flags should be set.'
+      }
+    ];
+    
+    beforeEach(function() {
+      instanceObject = mixinObject.create({});
+      sinon.stub(App.StackService, 'find').returns([
+        Em.Object.create({
+          displayName: 'Some Service',
+          configTypes: { 'some-site': {} }
+        })
+      ]);
+    });
+
+    afterEach(function() {
+      App.StackService.find.restore();
+    });
+    
+    tests.forEach(function(test) {
+      it(test.message, function() {
+        instanceObject.set('stepConfigs', test.stepConfigs);
+        instanceObject.validationSuccess({resources: test.resources});
+        test.expected.forEach(function(e) {
+          expect(instanceObject).to.have.deep.property(e.prop, e.value);
+        });
+      });
+    });
+  });
+});
+

Reply via email to