You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2015/10/16 12:38:41 UTC
[1/2] ambari git commit: AMBARI-13449. FE changes for
persisting/updating/removing KDC admin credentials.
Repository: ambari
Updated Branches:
refs/heads/trunk a509510ee -> 1076ec760
AMBARI-13449. FE changes for persisting/updating/removing KDC admin credentials.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1076ec76
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1076ec76
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1076ec76
Branch: refs/heads/trunk
Commit: 1076ec760bdafae4de876e66e39acad4f26c0b7e
Parents: 4a95428
Author: Alex Antonenko <hi...@gmail.com>
Authored: Fri Oct 16 13:13:53 2015 +0300
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Fri Oct 16 13:38:21 2015 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 1 +
.../app/controllers/main/admin/kerberos.js | 5 +
.../main/admin/kerberos/wizard_controller.js | 10 +-
ambari-web/app/messages.js | 3 +
.../common/kdc_credentials_controller_mixin.js | 5 +-
ambari-web/app/styles/common.less | 8 +-
.../common/form/manage_credentilas_form.hbs | 58 +++++
.../app/templates/main/admin/kerberos.hbs | 3 +
ambari-web/app/utils/ajax/ajax.js | 2 +-
ambari-web/app/utils/credentials.js | 47 ++++-
ambari-web/app/views.js | 2 +
.../common/form/manage_credentials_form_view.js | 209 +++++++++++++++++++
.../common/modal_popups/invalid_KDC_popup.js | 2 +-
.../manage_kdc_credentials_popup.js | 58 +++++
.../form/manage_kdc_credentials_form_test.js | 138 ++++++++++++
15 files changed, 535 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/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 5b5f588..b59f91f 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -273,6 +273,7 @@ var files = [
'test/views/common/controls_view_test',
'test/views/common/configs/widgets/time_interval_spinner_view_test',
'test/views/common/form/spinner_input_view_test',
+ 'test/views/common/form/manage_kdc_credentials_form_test',
'test/views/wizard/step3/hostLogPopupBody_view_test',
'test/views/wizard/step3/hostWarningPopupBody_view_test',
'test/views/wizard/step3/hostWarningPopupFooter_view_test',
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/controllers/main/admin/kerberos.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/kerberos.js b/ambari-web/app/controllers/main/admin/kerberos.js
index ca2f0dc..d339f63 100644
--- a/ambari-web/app/controllers/main/admin/kerberos.js
+++ b/ambari-web/app/controllers/main/admin/kerberos.js
@@ -582,5 +582,10 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
dfd.reject();
}, Em.I18n.t('common.warning'), Em.I18n.t('common.proceedAnyway'));
}
+ },
+
+ showManageKDCCredentialsPopup: function() {
+ return App.showManageCredentialsPopup();
}
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js b/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
index 6209f29..e0e146a 100644
--- a/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
+++ b/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
@@ -263,10 +263,14 @@ App.KerberosWizardController = App.WizardController.extend(App.InstallComponent,
callback: function() {
var self = this;
var dfd = $.Deferred();
- credentialsUtils.isStorePersisted(App.get('clusterName')).then(function(isPersisted) {
- self.set('content.secureStoragePersisted', isPersisted);
+ if (App.get('supports.storeKDCCredentials')) {
+ credentialsUtils.isStorePersisted(App.get('clusterName')).then(function(isPersisted) {
+ self.set('content.secureStoragePersisted', isPersisted);
+ dfd.resolve();
+ });
+ } else {
dfd.resolve();
- });
+ }
return dfd.promise();
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 6437ee9..5df161b 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1033,6 +1033,9 @@ Em.I18n.translations = {
'admin.kerberos.credentials.store.hint.supported': 'When checked, Ambari will store the KDC Admin credentials so they are not required to be re-entered during future changes of services, hosts, and components.',
'admin.kerberos.credentials.store.hint.not.supported': 'Ambari is not configured for storing credentials',
'admin.kerberos.credentials.store.label': 'Save Admin Credentials',
+ 'admin.kerberos.credentials.store.menu.label': 'Manage KDC Credentials',
+ 'admin.kerberos.credentials.remove.confirmation.header': 'Remove KDC Credentials Confirmation',
+ 'admin.kerberos.credentials.remove.confirmation.body': 'You are about to remove the KDC Credentials from Ambari. Are you sure?',
'admin.kerberos.wizard.configuration.note': 'This is the initial configuration created by Enable Kerberos wizard.',
'admin.kerberos.wizard.header':'Enable Kerberos Wizard',
'admin.kerberos.button.enable': 'Enable Kerberos',
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/mixins/common/kdc_credentials_controller_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/kdc_credentials_controller_mixin.js b/ambari-web/app/mixins/common/kdc_credentials_controller_mixin.js
index 67f2664..070ea35 100644
--- a/ambari-web/app/mixins/common/kdc_credentials_controller_mixin.js
+++ b/ambari-web/app/mixins/common/kdc_credentials_controller_mixin.js
@@ -81,14 +81,11 @@ App.KDCCredentialsControllerMixin = Em.Mixin.create({
* @returns {$.Deferred} promise object
*/
createKDCCredentials: function(configs) {
- var self = this;
var resource = credentialsUtils.createCredentialResource(
configs.findProperty('name', 'admin_principal').get('value'),
configs.findProperty('name', 'admin_password').get('value'),
this._getStorageTypeValue(configs));
- return credentialsUtils.createCredentials(App.get('clusterName'), this.get('credentialAlias'), resource).fail(function() {
- return self.updateKDCCredentials(resource);
- });
+ return credentialsUtils.createOrUpdateCredentials(App.get('clusterName'), this.get('credentialAlias'), resource);
},
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/styles/common.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/common.less b/ambari-web/app/styles/common.less
index b4cb61d..60b7553 100644
--- a/ambari-web/app/styles/common.less
+++ b/ambari-web/app/styles/common.less
@@ -224,8 +224,8 @@
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
- padding: 0px 0px;
- margin: 0px 0px;
+ padding: 0 0;
+ margin: 0 0;
border: none;
width: 50px;
height: 18px;
@@ -365,4 +365,8 @@
outline: 0 none;
}
}
+}
+
+.lh-btn {
+ line-height: 30px;
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/templates/common/form/manage_credentilas_form.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/form/manage_credentilas_form.hbs b/ambari-web/app/templates/common/form/manage_credentilas_form.hbs
new file mode 100644
index 0000000..c72e024
--- /dev/null
+++ b/ambari-web/app/templates/common/form/manage_credentilas_form.hbs
@@ -0,0 +1,58 @@
+{{!
+* 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.
+}}
+
+
+<form class="form-horizontal">
+ <div class="control-group">
+ <label class="control-label">{{t popup.invalid.KDC.admin.principal}}</label>
+ <div class="controls">
+ {{view Ember.TextField valueBinding="view.principal" class="form-control"}}
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label">{{t popup.invalid.KDC.admin.password}}</label>
+ <div class="controls">
+ {{view Ember.TextField type="password" valueBinding="view.password" class="form-control"}}
+ </div>
+ </div>
+ <div class="control-group">
+ <span class="control-label"></span>
+ <div class="controls">
+ {{#if App.supports.storeKDCCredentials}}
+ <label>
+ {{view Ember.Checkbox checkedBinding="view.storeCredentials" disabledBinding="view.checkboxDisabled" classNames="pull-left"}}
+ <span {{bindAttr class=":mls view.checkboxDisabled:muted"}}>
+ {{t admin.kerberos.credentials.store.label}}
+ <a class="icon-question-sign icon-blue" rel="tooltip" href="javascript:void(null);" data-toggle="tooltip" {{bindAttr data-original-title="view.hintMessage"}}><a/>
+ </span>
+ </label>
+ {{/if}}
+ </div>
+ </div>
+ <div class="control-group">
+ <span class="control-label"></span>
+ <div class="controls">
+ <button {{bindAttr class=":btn :btn-danger :pull-left view.isRemovable::hidden" disabled="view.isRemoveDisabled"}} {{action removeKDCCredentials target="view"}}>
+ <i class="icon-remove-circle"></i> {{t common.remove}}</button>
+ <div {{bindAttr class=":spinner :mll :pull-left view.isActionInProgress::hide"}}></div>
+ {{#if view.actionStatus}}
+ <span class="pull-left lh-btn mll text-success">{{view.actionStatus}}</span>
+ {{/if}}
+ </div>
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/templates/main/admin/kerberos.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/kerberos.hbs b/ambari-web/app/templates/main/admin/kerberos.hbs
index 88aa4e2..2ba6001 100644
--- a/ambari-web/app/templates/main/admin/kerberos.hbs
+++ b/ambari-web/app/templates/main/admin/kerberos.hbs
@@ -24,6 +24,9 @@
{{#unless isManualKerberos}}
<button class="btn btn-success" {{bindAttr disabled="isKerberosButtonsDisabled"}} {{action regenerateKeytabs target="controller"}}>
<i class="icon-repeat"></i> {{t admin.kerberos.button.regenerateKeytabs}}</button>
+ {{#if App.supports.storeKDCCredentials}}
+ <button class="btn btn-primary" {{action showManageKDCCredentialsPopup target="controller"}}>{{t admin.kerberos.credentials.store.menu.label}}</button>
+ {{/if}}
{{/unless}}
<br/>
{{#unless isEditMode}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js
index f0ebbff..52f3aca 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -797,7 +797,7 @@ var urls = {
},
'credentials.list': {
- 'real': '/clusters/{clusterName}/credentials',
+ 'real': '/clusters/{clusterName}/credentials?fields=Credential/*',
'mock': ''
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/utils/credentials.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/credentials.js b/ambari-web/app/utils/credentials.js
index 0639091..cc45288 100644
--- a/ambari-web/app/utils/credentials.js
+++ b/ambari-web/app/utils/credentials.js
@@ -69,11 +69,37 @@ module.exports = {
});
},
+ credentialsSuccessCallback: function(data, opt, params) {
+ params.callback(data.items.length ? data.items.mapProperty('Credential') : []);
+ },
+
createCredentialsErrorCallback: function(req, ajaxOpts, error) {
console.error('createCredentials ERROR:', error);
},
/**
+ * @see createCredentials
+ * @param {string} clusterName
+ * @param {string} alias
+ * @param {object} resource
+ * @returns {$.Deferred} promise object
+ */
+ createOrUpdateCredentials: function(clusterName, alias, resource) {
+ var self = this;
+ var dfd = $.Deferred();
+ this.createCredentials(clusterName, alias, resource).then(function() {
+ dfd.resolve();
+ }, function() {
+ self.updateCredentials(clusterName, alias, resource).always(function() {
+ var status = arguments[1];
+ var result = arguments[2];
+ dfd.resolve(status === "success", result);
+ });
+ });
+ return dfd.promise();
+ },
+
+ /**
* Retrieve single credential from cluster by specified alias name
*
* @member utils.credentials
@@ -131,16 +157,13 @@ module.exports = {
sender: this,
name: 'credentials.list',
data: {
- clusterName: clusterName
+ clusterName: clusterName,
+ callback: callback
},
success: 'credentialsSuccessCallback'
});
},
- credentialsSuccessCallback: function(data, opt, params) {
- params.callback(data.items.length ? data.items.mapProperty('Credential') : []);
- },
-
/**
* Remove credential from server by specified cluster name and alias
*
@@ -241,5 +264,19 @@ module.exports = {
key: key,
type: type
};
+ },
+
+ /**
+ * Check that KDC credentials stored as <b>persisted</b> and not <b>temporary</b> from specified credentials list.
+ *
+ * @param {object[]} credentials credentials list retrieved from API @see credentials
+ * @returns {boolean} <code>true</code> if credentials are persisted
+ */
+ isKDCCredentialsPersisted: function(credentials) {
+ var kdcCredentials = credentials.findProperty('alias', this.ALIAS.KDC_CREDENTIALS);
+ if (kdcCredentials) {
+ return Em.getWithDefault(kdcCredentials, 'type', this.STORE_TYPES.TEMPORARY) === this.STORE_TYPES.PERSISTENT;
+ }
+ return false;
}
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index e83b5d2..d6132e6 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -27,6 +27,7 @@ require('views/common/chart/linear');
require('views/common/chart/linear_time');
require('views/common/modal_popup');
require('views/common/modal_popups/alert_popup');
+require('views/common/modal_popups/manage_kdc_credentials_popup');
require('views/common/modal_popups/confirmation_feedback_popup');
require('views/common/modal_popups/confirmation_popup');
require('views/common/modal_popups/hosts_table_list_popup');
@@ -42,6 +43,7 @@ require('views/common/time_range');
require('views/common/time_range_list');
require('views/common/form/field');
require('views/common/form/spinner_input_view');
+require('views/common/form/manage_credentials_form_view');
require('views/common/quick_view_link_view');
require('views/common/configs/services_config');
require('views/common/configs/service_config_container_view');
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/views/common/form/manage_credentials_form_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/form/manage_credentials_form_view.js b/ambari-web/app/views/common/form/manage_credentials_form_view.js
new file mode 100644
index 0000000..c71021c
--- /dev/null
+++ b/ambari-web/app/views/common/form/manage_credentials_form_view.js
@@ -0,0 +1,209 @@
+/**
+ * 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');
+var credentialsUtils = require('utils/credentials');
+
+App.ManageCredentialsFormView = Em.View.extend({
+ templateName: require('templates/common/form/manage_credentilas_form'),
+ viewName: 'manageCredentialsForm',
+ principal: "",
+ password: "",
+
+ /**
+ * Store Admin credentials checkbox value
+ *
+ * @type {boolean}
+ */
+ storeCredentials: false,
+
+ /**
+ * Status of persistent storage. Returns <code>true</code> if persistent storage is available.
+ * @type {boolean}
+ */
+ storePersisted: false,
+
+ /**
+ * Disable checkbox if persistent storage not available
+ *
+ * @type {boolean}
+ */
+ checkboxDisabled: Ember.computed.not('storePersisted'),
+
+ /**
+ * Credentials can be removed, in case when they stored to persistent secure storage.
+ *
+ * @type {boolean}
+ */
+ isRemovable: false,
+
+ /**
+ * Remove button disabled status.
+ *
+ * @type {boolean}
+ */
+ isRemoveDisabled: true,
+
+ /**
+ * Signalize that action was performed and waiting for result.
+ *
+ * @type {boolean}
+ */
+ isActionInProgress: false,
+
+ /**
+ * Status message of performed action, e.g. remove or save credentials. Set to <code>false</code> to hide this message.
+ *
+ * @type {boolean|string}
+ */
+ actionStatus: false,
+
+ isSubmitDisabled: function() {
+ return Em.isEmpty(this.get('principal')) || Em.isEmpty(this.get('password'));
+ }.property('principal', 'password'),
+
+ /**
+ * Returns storage type used to save credentials e.g. <b>persistent</b>, <b>temporary</b> (default)
+ *
+ * @type {string}
+ */
+ storageType: function() {
+ return this.get('storeCredentials') ? credentialsUtils.STORE_TYPES.PERSISTENT : credentialsUtils.STORE_TYPES.TEMPORARY;
+ }.property('storeCredentials'),
+
+ /**
+ * Message to display in tooltip regarding persistent storage state.
+ *
+ * @type {string}
+ */
+ hintMessage: function() {
+ return this.get('storePersisted') ?
+ Em.I18n.t('admin.kerberos.credentials.store.hint.supported') :
+ Em.I18n.t('admin.kerberos.credentials.store.hint.not.supported');
+ }.property('storePersisted'),
+
+ /**
+ * Observe changes for principal and password.
+ * Hide status message and toggle action progress if performed.
+ */
+ formInputObserver: function() {
+ if (this.get('actionStatus') || this.get('isActionInProgress')) {
+ this.setInProgress(false);
+ this.set('actionStatus', false);
+ }
+ }.observes('password', 'principal'),
+
+ didInsertElement: function() {
+ this._super();
+ App.tooltip(this.$('[rel="tooltip"]'));
+ },
+
+ willInsertElement: function() {
+ this._super();
+ this.prepareContent();
+ },
+
+ prepareContent: function() {
+ var self = this;
+ credentialsUtils.isStorePersisted(App.get('clusterName')).then(function(isPersisted) {
+ Em.run.next(function() {
+ self.set('storePersisted', isPersisted);
+ });
+ });
+ credentialsUtils.credentials(App.get('clusterName'), function(credentials) {
+ Em.run.next(function() {
+ self.set('isRemovable', credentialsUtils.isKDCCredentialsPersisted(credentials));
+ self.set('isRemoveDisabled', !self.get('isRemovable'));
+ });
+ });
+ },
+
+ /**
+ * Save credentials action.
+ *
+ * @returns {boolean|$.Deferred}
+ */
+ saveKDCCredentials: function () {
+ var self = this;
+ var dfd = $.Deferred();
+
+ this.setInProgress(true);
+ credentialsUtils.createOrUpdateCredentials(
+ App.get('clusterName'),
+ credentialsUtils.ALIAS.KDC_CREDENTIALS,
+ credentialsUtils.createCredentialResource(this.get('principal'), this.get('password'), this.get('storageType')))
+ .always(function() {
+ self.setInProgress(false);
+ self.prepareContent();
+ self.set('actionStatus', Em.I18n.t('common.success'));
+ self.get('parentView').set('isCredentialsSaved', true);
+ dfd.resolve();
+ });
+ return dfd.promise();
+ },
+
+ /**
+ * Remove KDC credentials action.
+ *
+ * @returns {App.ModalPopup}
+ */
+ removeKDCCredentials: function() {
+ var t = Em.I18n.t;
+ var self = this;
+ this.set('actionStatus', false);
+ var popup = App.showConfirmationPopup(
+ function() {
+ self.setInProgress(true);
+ credentialsUtils.removeCredentials(App.get('clusterName'), credentialsUtils.ALIAS.KDC_CREDENTIALS)
+ .always(function() {
+ self.setInProgress(false);
+ self.prepareContent();
+ self.set('actionStatus', Em.I18n.t('common.success'));
+ self.get('parentView').set('isCredentialsRemoved', true);
+ });
+ }, t('admin.kerberos.credentials.remove.confirmation.body'),
+ function () {},
+ null,
+ t('yes'),
+ false);
+ popup.set('secondary', t('no'));
+ return popup;
+ },
+
+ /**
+ * Toggle action status and disable/enable appropriate buttons.
+ *
+ * @param {boolean} [isInProgress=false] progress status
+ */
+ setInProgress: function(isInProgress) {
+ if (isInProgress) {
+ this.set('actionStatus', false);
+ if (this.get('isRemovable')) {
+ this.set('isRemoveDisabled', true);
+ }
+ this.set('isSubmitDisabled', true);
+ this.set('isActionInProgress', true);
+ } else {
+ if (this.get('isRemovable')) {
+ this.set('isRemoveDisabled', false);
+ }
+ this.set('isSubmitDisabled', false);
+ this.set('isActionInProgress', false);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/views/common/modal_popups/invalid_KDC_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/invalid_KDC_popup.js b/ambari-web/app/views/common/modal_popups/invalid_KDC_popup.js
index 9c63f8f..ca5de7d 100644
--- a/ambari-web/app/views/common/modal_popups/invalid_KDC_popup.js
+++ b/ambari-web/app/views/common/modal_popups/invalid_KDC_popup.js
@@ -110,7 +110,7 @@ App.showInvalidKDCPopup = function (ajaxOpt, message) {
this.hide();
if (App.get('supports.storeKDCCredentials')) {
var resource = credentialsUtils.createCredentialResource(this.get('principal'), this.get('password'), this.get('storageType'));
- credentialsUtils.updateCredentials(App.get('clusterName'), credentialsUtils.ALIAS.KDC_CREDENTIALS, resource);
+ credentialsUtils.createOrUpdateCredentials(App.get('clusterName'), credentialsUtils.ALIAS.KDC_CREDENTIALS, resource);
}
App.get('router.clusterController').createKerberosAdminSession(this.get('principal'), this.get('password'), ajaxOpt);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/app/views/common/modal_popups/manage_kdc_credentials_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/manage_kdc_credentials_popup.js b/ambari-web/app/views/common/modal_popups/manage_kdc_credentials_popup.js
new file mode 100644
index 0000000..1de8e56
--- /dev/null
+++ b/ambari-web/app/views/common/modal_popups/manage_kdc_credentials_popup.js
@@ -0,0 +1,58 @@
+/**
+ * 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');
+var credentialsUtils = require('utils/credentials');
+
+/**
+ * @return {*}
+ */
+App.showManageCredentialsPopup = function () {
+ return App.ModalPopup.show({
+ header: Em.I18n.t('admin.kerberos.credentials.store.menu.label'),
+ bodyClass: App.ManageCredentialsFormView,
+ primary: Em.I18n.t('common.save'),
+ isCredentialsRemoved: false,
+
+ disablePrimary: function() {
+ return this.get('formView.isSubmitDisabled');
+ }.property('formView.isSubmitDisabled'),
+
+ formView: function() {
+ return this.get('childViews').findProperty('viewName', 'manageCredentialsForm');
+ }.property(),
+
+ credentialsRemoveObserver: function() {
+ if (this.get('isCredentialsRemoved')) {
+ this.hide();
+ }
+ }.observes('isCredentialsRemoved'),
+
+ onPrimary: function() {
+ var self = this;
+ var formView = this.get('formView');
+ if (formView) {
+ formView.saveKDCCredentials().always(function() {
+ self.hide();
+ });
+ } else {
+ this.hide();
+ }
+ }
+ });
+};
http://git-wip-us.apache.org/repos/asf/ambari/blob/1076ec76/ambari-web/test/views/common/form/manage_kdc_credentials_form_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/form/manage_kdc_credentials_form_test.js b/ambari-web/test/views/common/form/manage_kdc_credentials_form_test.js
new file mode 100644
index 0000000..ca5e4d0
--- /dev/null
+++ b/ambari-web/test/views/common/form/manage_kdc_credentials_form_test.js
@@ -0,0 +1,138 @@
+/**
+ * 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');
+var credentialUtils = require('utils/credentials');
+
+var view;
+
+describe('#App.ManageCredentialsFormView', function() {
+ beforeEach(function() {
+ view = App.ManageCredentialsFormView.create({
+ parentView: Em.Object.create({})
+ });
+ });
+
+ afterEach(function() {
+ view.destroy();
+ });
+
+ describe('#prepareContent', function() {
+ [
+ {
+ isStorePersistent: true,
+ credentials: [
+ {
+ alias: 'kdc.admin.credential',
+ type: 'persisted'
+ }
+ ],
+ e: {
+ isRemovable: true,
+ isRemoveDisabled: false,
+ storePersisted: true
+ },
+ m: 'persistent store is available, previous credentials were stored as persisted. Remove button should be visible and active.'
+ },
+ {
+ isStorePersistent: true,
+ credentials: [
+ {
+ alias: 'kdc.admin.credential',
+ type: 'temporary'
+ }
+ ],
+ e: {
+ isRemovable: false,
+ isRemoveDisabled: true,
+ storePersisted: true
+ },
+ m: 'persistent store is available, previous credentials were stored as temporary. Remove button should be hidden and disabled.'
+ }
+ ].forEach(function(test) {
+ it(test.m, function(done) {
+ sinon.stub(credentialUtils, 'credentials', function(clusterName, callback) {
+ callback(test.credentials);
+ });
+ sinon.stub(credentialUtils, 'isStorePersisted', function() {
+ return $.Deferred().resolve(test.isStorePersistent).promise();
+ });
+ view.prepareContent();
+ Em.run.next(function() {
+ assert.equal(view.get('isRemovable'), test.e.isRemovable, '#isRemovable property validation');
+ assert.equal(view.get('isRemoveDisabled'), test.e.isRemoveDisabled, '#isRemoveDisabled property validation');
+ assert.equal(view.get('storePersisted'), test.e.storePersisted, '#storePersisted property validation');
+ credentialUtils.credentials.restore();
+ credentialUtils.isStorePersisted.restore();
+ done();
+ });
+ });
+ });
+ });
+
+ describe('#isSubmitDisabled', function() {
+ it('save button disabled by default', function() {
+ expect(view.get('isSubmitDisabled')).to.be.true;
+ });
+ it('save button disabled when password is empty', function() {
+ view.set('principal', 'some_principal');
+ expect(view.get('isSubmitDisabled')).to.be.true;
+ });
+ it('save button disabled when principal is empty', function() {
+ view.set('password', 'some_password');
+ expect(view.get('isSubmitDisabled')).to.be.true;
+ });
+ it('save button should be enabled when principal and password are filled', function() {
+ view.set('password', 'some_password');
+ view.set('principal', 'principal');
+ expect(view.get('isSubmitDisabled')).to.be.false;
+ });
+ });
+
+ describe('#removeKDCCredentials', function() {
+ it('should show confirmation popup', function() {
+ var popup = view.removeKDCCredentials();
+ expect(popup).be.instanceof(App.ModalPopup);
+ popup.destroy();
+ });
+ it('should call credentialUtils#removeCredentials', function() {
+ this.clock = sinon.useFakeTimers();
+ var popup = view.removeKDCCredentials();
+ assert.isFalse(view.get('actionStatus'), '#actionStatus before remove');
+ sinon.stub(credentialUtils, 'removeCredentials', function() {
+ var dfd = $.Deferred();
+ setTimeout(function() {
+ dfd.resolve();
+ }, 500);
+ return dfd.promise();
+ });
+ popup.onPrimary();
+ assert.isTrue(view.get('isActionInProgress'), 'action in progress');
+ assert.isTrue(view.get('isRemoveDisabled'), 'remove button disabled');
+ assert.isTrue(view.get('isSubmitDisabled'), 'submit button disabled');
+ this.clock.tick(1000);
+ assert.isFalse(view.get('isActionInProgress'), 'action finished');
+ assert.equal(Em.I18n.t('common.success'), view.get('actionStatus'), '#actionStatus after remove');
+ assert.isTrue(view.get('parentView.isCredentialsRemoved'), 'parentView#isCredentialsRemoved property should be triggered when remove complete');
+ credentialUtils.removeCredentials.restore();
+ this.clock.restore();
+ popup.destroy();
+ });
+ });
+
+});
[2/2] ambari git commit: AMBARI-13448. CSV export: downloaded data
does not reflect what's shown in the chart
Posted by al...@apache.org.
AMBARI-13448. CSV export: downloaded data does not reflect what's shown in the chart
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4a954283
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4a954283
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4a954283
Branch: refs/heads/trunk
Commit: 4a954283e96a1e598e436b9c264939398793c59d
Parents: a509510
Author: Alex Antonenko <hi...@gmail.com>
Authored: Fri Oct 16 13:08:00 2015 +0300
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Fri Oct 16 13:38:21 2015 +0300
----------------------------------------------------------------------
.../views/common/widget/graph_widget_view.js | 2 +-
.../common/widget/graph_widget_view_test.js | 112 +++++++++++++++++++
2 files changed, 113 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a954283/ambari-web/app/views/common/widget/graph_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/widget/graph_widget_view.js b/ambari-web/app/views/common/widget/graph_widget_view.js
index fb8e754..1ed20d2 100644
--- a/ambari-web/app/views/common/widget/graph_widget_view.js
+++ b/ambari-web/app/views/common/widget/graph_widget_view.js
@@ -313,7 +313,7 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, App.ExportMetricsMixin, {
isCSV = !!event.context,
fileType = isCSV ? 'csv' : 'json',
fileName = 'data.' + fileType,
- metrics = this.get('content.metrics'),
+ metrics = this.get('data'),
hasData = Em.isArray(metrics) && metrics.some(function (item) {
return Em.isArray(item.data);
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/4a954283/ambari-web/test/views/common/widget/graph_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/widget/graph_widget_view_test.js b/ambari-web/test/views/common/widget/graph_widget_view_test.js
index deccce5..7215128 100644
--- a/ambari-web/test/views/common/widget/graph_widget_view_test.js
+++ b/ambari-web/test/views/common/widget/graph_widget_view_test.js
@@ -18,6 +18,7 @@
var App = require('app');
require('views/common/widget/graph_widget_view');
+var fileUtils = require('utils/file_utils');
describe('App.GraphWidgetView', function () {
var view = App.GraphWidgetView.create();
@@ -126,4 +127,115 @@ describe('App.GraphWidgetView', function () {
});
});
+ describe('#exportGraphData', function () {
+
+ var cases = [
+ {
+ data: null,
+ prepareCSVCallCount: 0,
+ prepareJSONCallCount: 0,
+ downloadTextFileCallCount: 0,
+ showAlertPopupCallCount: 1,
+ title: 'no data'
+ },
+ {
+ data: {},
+ prepareCSVCallCount: 0,
+ prepareJSONCallCount: 0,
+ downloadTextFileCallCount: 0,
+ showAlertPopupCallCount: 1,
+ title: 'invalid data'
+ },
+ {
+ data: [
+ {
+ data: null
+ }
+ ],
+ prepareCSVCallCount: 0,
+ prepareJSONCallCount: 0,
+ downloadTextFileCallCount: 0,
+ showAlertPopupCallCount: 1,
+ title: 'empty data'
+ },
+ {
+ data: [
+ {
+ data: {}
+ }
+ ],
+ prepareCSVCallCount: 0,
+ prepareJSONCallCount: 0,
+ downloadTextFileCallCount: 0,
+ showAlertPopupCallCount: 1,
+ title: 'malformed data'
+ },
+ {
+ data: [
+ {
+ data: [
+ {
+ key: 'value'
+ }
+ ]
+ }
+ ],
+ prepareCSVCallCount: 0,
+ prepareJSONCallCount: 1,
+ downloadTextFileCallCount: 1,
+ showAlertPopupCallCount: 0,
+ title: 'JSON export'
+ },
+ {
+ data: [
+ {
+ data: [
+ {
+ key: 'value'
+ }
+ ]
+ }
+ ],
+ event: {
+ context: true
+ },
+ prepareCSVCallCount: 1,
+ prepareJSONCallCount: 0,
+ downloadTextFileCallCount: 1,
+ showAlertPopupCallCount: 0,
+ title: 'CSV export'
+ }
+ ];
+
+ beforeEach(function () {
+ sinon.stub(view, 'prepareCSV').returns([]);
+ sinon.stub(view, 'prepareJSON').returns([]);
+ sinon.stub(fileUtils, 'downloadTextFile', Em.K);
+ sinon.stub(App, 'showAlertPopup', Em.K);
+ });
+
+ afterEach(function () {
+ view.prepareCSV.restore();
+ view.prepareJSON.restore();
+ fileUtils.downloadTextFile.restore();
+ App.showAlertPopup.restore();
+ });
+
+ cases.forEach(function (item) {
+ it(item.title, function () {
+ view.set('data', item.data);
+ view.exportGraphData(item.event || {});
+ expect(view.prepareCSV.callCount).to.equal(item.prepareCSVCallCount);
+ expect(view.prepareJSON.callCount).to.equal(item.prepareJSONCallCount);
+ expect(fileUtils.downloadTextFile.callCount).to.equal(item.downloadTextFileCallCount);
+ expect(App.showAlertPopup.callCount).to.equal(item.showAlertPopupCallCount);
+ if (item.downloadTextFileCallCount) {
+ var fileType = item.event && item.event.context ? 'csv' : 'json';
+ expect(fileUtils.downloadTextFile.calledWith([], fileType, 'data.' + fileType)).to.be.true;
+ }
+ });
+ });
+
+ });
+
});
\ No newline at end of file