Repository: ambari Updated Branches: refs/heads/trunk e537178b1 -> 0fc88bed2
AMBARI-13187. Refactor host components utils (onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0fc88bed Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0fc88bed Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0fc88bed Branch: refs/heads/trunk Commit: 0fc88bed2dd3829cf5c33885c92018cec9a788e6 Parents: e537178 Author: Oleg Nechiporenko <onechipore...@apache.org> Authored: Tue Sep 22 18:01:09 2015 +0300 Committer: Oleg Nechiporenko <onechipore...@apache.org> Committed: Tue Sep 22 18:13:27 2015 +0300 ---------------------------------------------------------------------- .../main/admin/kerberos/wizard_controller.js | 5 +- ambari-web/app/controllers/main/host/details.js | 124 ++++------- ambari-web/app/controllers/main/service/item.js | 7 +- ambari-web/app/mixins.js | 3 + .../host/details/actions/install_new_version.js | 76 +++++++ .../host_components/install_component.js | 126 +++++++++++ .../details/support_client_configs_download.js | 86 ++++++++ .../wizard/wizardProgressPageController.js | 5 +- ambari-web/app/utils/components.js | 221 ------------------- .../test/controllers/main/host/details_test.js | 99 +++------ .../test/controllers/main/service/item_test.js | 9 +- .../wizard/wizardProgressPageController_test.js | 4 +- 12 files changed, 376 insertions(+), 389 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/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 3476b2b..6fb0f8b 100644 --- a/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js +++ b/ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js @@ -18,9 +18,8 @@ var App = require('app'); -var componentsUtils = require('utils/components'); -App.KerberosWizardController = App.WizardController.extend({ +App.KerberosWizardController = App.WizardController.extend(App.InstallComponent, { exceptionsOnSkipClient: [{'KDC': 'realm'}, {'KDC': 'kdc_type'}, {'Advanced kerberos-env': 'executable_search_paths'}], @@ -184,7 +183,7 @@ App.KerberosWizardController = App.WizardController.extend({ createKerberosResources: function (callback) { var self = this; this.createKerberosService().done(function () { - componentsUtils.updateAndCreateServiceComponent('KERBEROS_CLIENT').done(function () { + self.updateAndCreateServiceComponent('KERBEROS_CLIENT').done(function () { self.createKerberosHostComponents().done(callback); }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/controllers/main/host/details.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js index e4b27c6..40c645b 100644 --- a/ambari-web/app/controllers/main/host/details.js +++ b/ambari-web/app/controllers/main/host/details.js @@ -18,11 +18,10 @@ var App = require('app'); var batchUtils = require('utils/batch_scheduled_requests'); -var componentsUtils = require('utils/components'); var hostsManagement = require('utils/hosts'); var stringUtils = require('utils/string_utils'); -App.MainHostDetailsController = Em.Controller.extend({ +App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDownload, App.InstallComponent, App.InstallNewVersion, { name: 'mainHostDetailsController', @@ -178,19 +177,6 @@ App.MainHostDetailsController = Em.Controller.extend({ }, /** - * Default error-callback for ajax-requests in current page - * @param {object} request - * @param {object} ajaxOptions - * @param {string} error - * @param {object} opt - * @param {object} params - * @method ajaxErrorCallback - */ - ajaxErrorCallback: function (request, ajaxOptions, error, opt, params) { - return componentsUtils.ajaxErrorCallback(request, ajaxOptions, error, opt, params); - }, - - /** * Return true if hdfs user data is loaded via App.MainServiceInfoConfigsController */ getHdfsUser: function () { @@ -581,7 +567,7 @@ App.MainHostDetailsController = Em.Controller.extend({ component = event.context, hostName = event.selectedHost || this.get('content.hostName'), componentName = component.get('componentName'), - missedComponents = event.selectedHost ? [] : componentsUtils.checkComponentDependencies(componentName, { + missedComponents = event.selectedHost ? [] : this.checkComponentDependencies(componentName, { scope: 'host', installedComponents: this.get('content.hostComponents').mapProperty('componentName') }), @@ -599,7 +585,7 @@ App.MainHostDetailsController = Em.Controller.extend({ switch (componentName) { case 'ZOOKEEPER_SERVER': returnFunc = App.showConfirmationPopup(function () { - self.primary(component); + self.installHostComponentCall(self.get('content.hostName'), component) }, Em.I18n.t('hosts.host.addComponent.' + componentName) + manualKerberosWarning); break; case 'HIVE_METASTORE': @@ -634,7 +620,7 @@ App.MainHostDetailsController = Em.Controller.extend({ var message = this.formatClientsMessage(component); return this.showAddComponentPopup(message, isManualKerberos, function () { - self.primary(component); + self.installHostComponentCall(self.get('content.hostName'), component); }); }, @@ -682,16 +668,6 @@ App.MainHostDetailsController = Em.Controller.extend({ }, /** - * Send request to add host component - * @param {App.HostComponent} component - * @method primary - */ - primary: function (component) { - var self = this; - componentsUtils.installHostComponent(self.get('content.hostName'), component); - }, - - /** * Success callback for install host component request (sent in <code>addNewComponentSuccessCallback</code>) * @param {object} data * @param {object} opt @@ -971,7 +947,7 @@ App.MainHostDetailsController = Em.Controller.extend({ App.router.get('mainServiceInfoConfigsController').loadStep(); } if (params.host) { - componentsUtils.installHostComponent(params.host, App.StackServiceComponent.find(params.componentName)); + this.installHostComponentCall(params.host, App.StackServiceComponent.find(params.componentName)); } }, /** @@ -2295,7 +2271,7 @@ App.MainHostDetailsController = Em.Controller.extend({ }, downloadClientConfigs: function (event) { - componentsUtils.downloadClientConfigs.call(this, { + this.downloadClientConfigsCall({ hostName: event.context.get('hostName'), componentName: event.context.get('componentName'), displayName: event.context.get('displayName') @@ -2316,7 +2292,7 @@ App.MainHostDetailsController = Em.Controller.extend({ } }); clientsToAdd.forEach(function (component, index, array) { - var dependencies = componentsUtils.checkComponentDependencies(component.get('componentName'), { + var dependencies = this.checkComponentDependencies(component.get('componentName'), { scope: 'host', installedComponents: this.get('content.hostComponents').mapProperty('componentName') }).reject(function (componentName) { @@ -2348,8 +2324,8 @@ App.MainHostDetailsController = Em.Controller.extend({ self.showAddComponentPopup(message, isManualKerberos, function () { sendInstallCommand(); clientsToAdd.forEach(function (component) { - this.primary(component); - }, self); + self.installHostComponentCall(self.get('content.hostName'), component); + }); }); } else { sendInstallCommand(); @@ -2360,6 +2336,42 @@ App.MainHostDetailsController = Em.Controller.extend({ }, /** + * Check if all required components are installed on host. + * Available options: + * scope: 'host' - dependency level `host`,`cluster` or `*`. + * hostName: 'example.com' - host name to search installed components + * installedComponents: ['A', 'B'] - names of installed components + * + * By default scope level is `*` + * For host level dependency you should specify at least `hostName` or `installedComponents` attribute. + * + * @param {String} componentName + * @param {Object} opt - options. Allowed options are `hostName`, `installedComponents`, `scope`. + * @return {Array} - names of missed components + */ + checkComponentDependencies: function (componentName, opt) { + opt = opt || {}; + opt.scope = opt.scope || '*'; + var installedComponents; + var dependencies = App.StackServiceComponent.find(componentName).get('dependencies'); + dependencies = opt.scope === '*' ? dependencies : dependencies.filterProperty('scope', opt.scope); + if (dependencies.length == 0) return []; + switch (opt.scope) { + case 'host': + Em.assert("You should pass at least `hostName` or `installedComponents` to options.", opt.hostName || opt.installedComponents); + installedComponents = opt.installedComponents || App.HostComponent.find().filterProperty('hostName', opt.hostName).mapProperty('componentName').uniq(); + break; + default: + // @todo: use more appropriate value regarding installed components + installedComponents = opt.installedComponents || App.HostComponent.find().mapProperty('componentName').uniq(); + break; + } + return dependencies.filter(function (dependency) { + return !installedComponents.contains(dependency.componentName); + }).mapProperty('componentName'); + }, + + /** * On click handler for custom command from items menu * @param context */ @@ -2403,52 +2415,6 @@ App.MainHostDetailsController = Em.Controller.extend({ }, /** - * show popup confirmation of version installation - * @param event - */ - installVersionConfirmation: function (event) { - var self = this; - - return App.showConfirmationPopup(function () { - self.installVersion(event); - }, - Em.I18n.t('hosts.host.stackVersions.install.confirmation').format(event.context.get('displayName')) - ); - }, - - /** - * install HostStackVersion on host - * @param {object} event - */ - installVersion: function (event) { - App.ajax.send({ - name: 'host.stack_versions.install', - sender: this, - data: { - hostName: this.get('content.hostName'), - version: event.context - }, - success: 'installVersionSuccessCallback' - }); - }, - - /** - * success callback of <code>installVersion</code> - * on success set version status to INSTALLING - * @param {object} data - * @param {object} opt - * @param {object} params - */ - installVersionSuccessCallback: function (data, opt, params) { - App.HostStackVersion.find(params.version.get('id')).set('status', 'INSTALLING'); - App.db.set('repoVersionInstall', 'id', [data.Requests.id]); - App.clusterStatus.setClusterStatus({ - wizardControllerName: this.get('name'), - localdb: App.db.data - }); - }, - - /** * Call callback after loading service metrics * @param callback */ http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/controllers/main/service/item.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js index 99c2061..6e1151e 100644 --- a/ambari-web/app/controllers/main/service/item.js +++ b/ambari-web/app/controllers/main/service/item.js @@ -18,9 +18,8 @@ var App = require('app'); var batchUtils = require('utils/batch_scheduled_requests'); -var componentsUtils = require('utils/components'); -App.MainServiceItemController = Em.Controller.extend({ +App.MainServiceItemController = Em.Controller.extend(App.SupportClientConfigsDownload, { name: 'mainServiceItemController', /** @@ -808,7 +807,7 @@ App.MainServiceItemController = Em.Controller.extend({ } ); } else { - componentsUtils.installHostComponent(selectedHost, component); + self.installHostComponentCall(selectedHost, component); } // Remove host from 'without' collection to immediate recalculate add menu item state @@ -888,7 +887,7 @@ App.MainServiceItemController = Em.Controller.extend({ downloadClientConfigs: function (event) { var component = this.get('content.clientComponents').rejectProperty('totalCount', 0)[0]; - componentsUtils.downloadClientConfigs.call(this, { + this.downloadClientConfigsCall({ serviceName: this.get('content.serviceName'), componentName: (event && event.name) || component.get('componentName'), displayName: (event && event.label) || component.get('displayName') http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/mixins.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js index d86eccf..6552c61 100644 --- a/ambari-web/app/mixins.js +++ b/ambari-web/app/mixins.js @@ -27,6 +27,9 @@ require('mixins/common/serverValidator'); require('mixins/common/table_server_view_mixin'); require('mixins/common/table_server_mixin'); require('mixins/main/host/details/host_components/decommissionable'); +require('mixins/main/host/details/host_components/install_component'); +require('mixins/main/host/details/actions/install_new_version'); +require('mixins/main/host/details/support_client_configs_download'); require('mixins/main/service/groups_mapping'); require('mixins/main/service/themes_mapping'); require('mixins/main/service/versions_mapping'); http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/mixins/main/host/details/actions/install_new_version.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/host/details/actions/install_new_version.js b/ambari-web/app/mixins/main/host/details/actions/install_new_version.js new file mode 100644 index 0000000..44e2550 --- /dev/null +++ b/ambari-web/app/mixins/main/host/details/actions/install_new_version.js @@ -0,0 +1,76 @@ +/** + * 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'); + +App.InstallNewVersion = Em.Mixin.create({ + + /** + * show popup confirmation of version installation + * @param event + */ + installVersionConfirmation: function (event) { + var self = this; + + return App.showConfirmationPopup(function () { + self.installVersion(event); + }, + Em.I18n.t('hosts.host.stackVersions.install.confirmation').format(event.context.get('displayName')) + ); + }, + + /** + * install HostStackVersion on host + * @param {object} event + */ + installVersion: function (event) { + App.ajax.send({ + name: 'host.stack_versions.install', + sender: this, + data: { + hostName: this.get('content.hostName'), + version: event.context + }, + success: 'installVersionSuccessCallback' + }); + }, + + /** + * success callback of <code>installVersion</code> + * on success set version status to INSTALLING + * @param {object} data + * @param {object} opt + * @param {object} params + */ + installVersionSuccessCallback: function (data, opt, params) { + App.HostStackVersion.find(params.version.get('id')).set('status', 'INSTALLING'); + App.db.set('repoVersionInstall', 'id', [data.Requests.id]); + App.clusterStatus.setClusterStatus({ + wizardControllerName: this.get('name'), + localdb: App.db.data + }); + }, + + /** + * Call callback after loading service metrics + * @param callback + */ + isServiceMetricsLoaded: function(callback) { + App.router.get('mainController').isLoading.call(App.router.get('clusterController'), 'isServiceContentFullyLoaded').done(callback); + } + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/mixins/main/host/details/host_components/install_component.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/host/details/host_components/install_component.js b/ambari-web/app/mixins/main/host/details/host_components/install_component.js new file mode 100644 index 0000000..858c95f --- /dev/null +++ b/ambari-web/app/mixins/main/host/details/host_components/install_component.js @@ -0,0 +1,126 @@ + + +var App = require('app'); + +App.InstallComponent = Em.Mixin.create({ + + installHostComponentCall: function (hostName, component) { + var self = this, + componentName = component.get('componentName'), + displayName = component.get('displayName'); + this.updateAndCreateServiceComponent(componentName).done(function () { + return App.ajax.send({ + name: 'host.host_component.add_new_component', + sender: self, + data: { + hostName: hostName, + component: component, + data: JSON.stringify({ + RequestInfo: { + "context": Em.I18n.t('requestInfo.installHostComponent') + " " + displayName + }, + Body: { + host_components: [ + { + HostRoles: { + component_name: componentName + } + } + ] + } + }) + }, + success: 'addNewComponentSuccessCallback', + error: 'ajaxErrorCallback' + }); + }); + }, + + /** + * Success callback for add host component request + * @param {object} data + * @param {object} opt + * @param {object} params + * @return {$.ajax} + * @method addNewComponentSuccessCallback + */ + addNewComponentSuccessCallback: function (data, opt, params) { + return App.ajax.send({ + name: 'common.host.host_component.update', + sender: App.router.get('mainHostDetailsController'), + data: { + hostName: params.hostName, + componentName: params.component.get('componentName'), + serviceName: params.component.get('serviceName'), + component: params.component, + "context": Em.I18n.t('requestInfo.installNewHostComponent') + " " + params.component.get('displayName'), + HostRoles: { + state: 'INSTALLED' + }, + urlParams: "HostRoles/state=INIT" + }, + success: 'installNewComponentSuccessCallback', + error: 'ajaxErrorCallback' + }); + }, + + /** + * Default error-callback for ajax-requests in current page + * @param {object} request + * @param {object} ajaxOptions + * @param {string} error + * @param {object} opt + * @param {object} params + * @method ajaxErrorCallback + */ + ajaxErrorCallback: function (request, ajaxOptions, error, opt, params) { + App.ajax.defaultErrorHandler(request, opt.url, opt.method); + }, + + /** + * + * @param componentName + * @returns {*} + */ + updateAndCreateServiceComponent: function (componentName) { + var self = this; + var dfd = $.Deferred(); + var updater = App.router.get('updateController'); + updater.updateComponentsState(function () { + updater.updateServiceMetric(function () { + self.createServiceComponent(componentName, dfd); + }); + }); + return dfd.promise(); + }, + + /** + * + * @param componentName + * @param dfd + * @returns {*} + */ + createServiceComponent: function (componentName, dfd) { + var allServiceComponents = []; + var services = App.Service.find().mapProperty('serviceName'); + services.forEach(function (_service) { + var _serviceComponents = App.Service.find(_service).get('serviceComponents'); + allServiceComponents = allServiceComponents.concat(_serviceComponents); + }, this); + if (allServiceComponents.contains(componentName)) { + dfd.resolve(); + } else { + return App.ajax.send({ + name: 'common.create_component', + sender: this, + data: { + componentName: componentName, + serviceName: App.StackServiceComponent.find().findProperty('componentName', componentName).get('serviceName') + } + }).complete(function () { + dfd.resolve(); + }); + } + } + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/mixins/main/host/details/support_client_configs_download.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/host/details/support_client_configs_download.js b/ambari-web/app/mixins/main/host/details/support_client_configs_download.js new file mode 100644 index 0000000..5d02190 --- /dev/null +++ b/ambari-web/app/mixins/main/host/details/support_client_configs_download.js @@ -0,0 +1,86 @@ +/** + * 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'); + +App.SupportClientConfigsDownload = Em.Mixin.create({ + + /** + * + * @param {{hostName: string, componentName: string, displayName: string, serviceName: string}} data + */ + downloadClientConfigsCall: function (data) { + var url = this._getUrl(data.hostName, data.serviceName, data.componentName); + try { + var self = this; + $.fileDownload(url).fail(function (error) { + var errorMessage = ''; + var isNoConfigs = false; + if (error && $(error).text()) { + var errorObj = JSON.parse($(error).text()); + if (errorObj && errorObj.message && errorObj.status) { + isNoConfigs = errorObj.message.indexOf(Em.I18n.t('services.service.actions.downloadClientConfigs.fail.noConfigFile')) !== -1; + errorMessage += isNoConfigs ? Em.I18n.t('services.service.actions.downloadClientConfigs.fail.noConfigFile') : + Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.errorMessage').format(data.displayName, errorObj.status, errorObj.message); + } + else { + errorMessage += Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.noErrorMessage').format(data.displayName); + } + errorMessage += isNoConfigs ? '' : Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.question'); + } + else { + errorMessage += Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.noErrorMessage').format(data.displayName) + + Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.question'); + } + return App.ModalPopup.show({ + header: Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.header').format(data.displayName), + bodyClass: Em.View.extend({ + template: Em.Handlebars.compile(errorMessage) + }), + secondary: isNoConfigs ? false : Em.I18n.t('common.cancel'), + onPrimary: function () { + this.hide(); + if (!isNoConfigs) { + self.downloadClientConfigs({ + context: Em.Object.create(data) + }) + } + } + }); + }); + } catch (err) { + var newWindow = window.open(url); + newWindow.focus(); + } + }, + + /** + * + * @param {string|null} hostName + * @param {string} serviceName + * @param {string} componentName + * @returns {string} + * @private + */ + _getUrl: function (hostName, serviceName, componentName) { + var isForHost = !Em.isNone(hostName); + return App.get('apiPrefix') + '/clusters/' + App.router.getClusterName() + '/' + + (isForHost ? 'hosts/' + hostName + '/host_components/' : 'services/' + serviceName + '/components/') + + componentName + '?format=client_config_tar'; + } + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/mixins/wizard/wizardProgressPageController.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/wizard/wizardProgressPageController.js b/ambari-web/app/mixins/wizard/wizardProgressPageController.js index d290173..e0440c4 100644 --- a/ambari-web/app/mixins/wizard/wizardProgressPageController.js +++ b/ambari-web/app/mixins/wizard/wizardProgressPageController.js @@ -17,14 +17,13 @@ */ var App = require('app'); -var componentsUtils = require('utils/components'); /** * Mixin for wizard controller for showing command progress on wizard pages * This should * @type {Ember.Mixin} */ -App.wizardProgressPageControllerMixin = Em.Mixin.create({ +App.wizardProgressPageControllerMixin = Em.Mixin.create(App.InstallComponent, { controllerName: '', clusterDeployState: 'WIZARD_DEPLOY', status: 'IN_PROGRESS', @@ -517,7 +516,7 @@ App.wizardProgressPageControllerMixin = Em.Mixin.create({ } }; if (!!hostsWithoutComponents.length) { - componentsUtils.updateAndCreateServiceComponent(componentName).done(function () { + self.updateAndCreateServiceComponent(componentName).done(function () { App.ajax.send({ name: 'wizard.step8.register_host_to_component', sender: self, http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/app/utils/components.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/components.js b/ambari-web/app/utils/components.js deleted file mode 100644 index 54ee6c0..0000000 --- a/ambari-web/app/utils/components.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * 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'); - -module.exports = { - installHostComponent: function (hostName, component) { - var self = this, - componentName = component.get('componentName'), - displayName = component.get('displayName'); - this.updateAndCreateServiceComponent(componentName).done(function () { - App.ajax.send({ - name: 'host.host_component.add_new_component', - sender: self, - data: { - hostName: hostName, - component: component, - data: JSON.stringify({ - RequestInfo: { - "context": Em.I18n.t('requestInfo.installHostComponent') + " " + displayName - }, - Body: { - host_components: [ - { - HostRoles: { - component_name: componentName - } - } - ] - } - }) - }, - success: 'addNewComponentSuccessCallback', - error: 'ajaxErrorCallback' - }); - }); - }, - - /** - * Success callback for add host component request - * @param {object} data - * @param {object} opt - * @param {object} params - * @method addNewComponentSuccessCallback - */ - addNewComponentSuccessCallback: function (data, opt, params) { - console.log('Send request for ADDING NEW COMPONENT successfully'); - App.ajax.send({ - name: 'common.host.host_component.update', - sender: App.router.get('mainHostDetailsController'), - data: { - hostName: params.hostName, - componentName: params.component.get('componentName'), - serviceName: params.component.get('serviceName'), - component: params.component, - "context": Em.I18n.t('requestInfo.installNewHostComponent') + " " + params.component.get('displayName'), - HostRoles: { - state: 'INSTALLED' - }, - urlParams: "HostRoles/state=INIT" - }, - success: 'installNewComponentSuccessCallback', - error: 'ajaxErrorCallback' - }); - }, - - /** - * Default error-callback for ajax-requests in current page - * @param {object} request - * @param {object} ajaxOptions - * @param {string} error - * @param {object} opt - * @param {object} params - * @method ajaxErrorCallback - */ - ajaxErrorCallback: function (request, ajaxOptions, error, opt, params) { - console.log('error on change component host status'); - App.ajax.defaultErrorHandler(request, opt.url, opt.method); - }, - - downloadClientConfigs: function (data) { - var isForHost = typeof data.hostName !== 'undefined'; - var url = App.get('apiPrefix') + '/clusters/' + App.router.getClusterName() + '/' + - (isForHost ? 'hosts/' + data.hostName + '/host_components/' : 'services/' + data.serviceName + '/components/') + - data.componentName + '?format=client_config_tar'; - try { - var self = this; - $.fileDownload(url).fail(function (error) { - var errorMessage = ''; - var isNoConfigs = false; - if (error && $(error).text()) { - var errorObj = JSON.parse($(error).text()); - if (errorObj && errorObj.message && errorObj.status) { - isNoConfigs = errorObj.message.indexOf(Em.I18n.t('services.service.actions.downloadClientConfigs.fail.noConfigFile')) !== -1; - errorMessage += isNoConfigs ? Em.I18n.t('services.service.actions.downloadClientConfigs.fail.noConfigFile') : - Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.errorMessage').format(data.displayName, errorObj.status, errorObj.message); - } else { - errorMessage += Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.noErrorMessage').format(data.displayName); - } - errorMessage += isNoConfigs ? '' : Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.question'); - } else { - errorMessage += Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.noErrorMessage').format(data.displayName) + - Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.body.question'); - } - App.ModalPopup.show({ - header: Em.I18n.t('services.service.actions.downloadClientConfigs.fail.popup.header').format(data.displayName), - bodyClass: Ember.View.extend({ - template: Em.Handlebars.compile(errorMessage) - }), - secondary: isNoConfigs ? false : Em.I18n.t('common.cancel'), - onPrimary: function () { - this.hide(); - if (!isNoConfigs) { - self.downloadClientConfigs({ - context: Em.Object.create(data) - }) - } - } - }); - }); - } catch (err) { - var newWindow = window.open(url); - newWindow.focus(); - } - }, - /** - * Check if all required components are installed on host. - * Available options: - * scope: 'host' - dependency level `host`,`cluster` or `*`. - * hostName: 'example.com' - host name to search installed components - * installedComponents: ['A', 'B'] - names of installed components - * - * By default scope level is `*` - * For host level dependency you should specify at least `hostName` or `installedComponents` attribute. - * - * @param {String} componentName - * @param {Object} opt - options. Allowed options are `hostName`, `installedComponents`, `scope`. - * @return {Array} - names of missed components - */ - checkComponentDependencies: function (componentName, opt) { - opt = opt || {}; - opt.scope = opt.scope || '*'; - var installedComponents; - var dependencies = App.StackServiceComponent.find(componentName).get('dependencies'); - dependencies = opt.scope === '*' ? dependencies : dependencies.filterProperty('scope', opt.scope); - if (dependencies.length == 0) return []; - switch (opt.scope) { - case 'host': - Em.assert("You should pass at least `hostName` or `installedComponents` to options.", opt.hostName || opt.installedComponents); - installedComponents = opt.installedComponents || App.HostComponent.find().filterProperty('hostName', opt.hostName).mapProperty('componentName').uniq(); - break; - default: - // @todo: use more appropriate value regarding installed components - installedComponents = opt.installedComponents || App.HostComponent.find().mapProperty('componentName').uniq(); - break; - } - return dependencies.filter(function (dependency) { - return !installedComponents.contains(dependency.componentName); - }).mapProperty('componentName'); - }, - - /** - * - * @param componentName - * @returns {*} - */ - updateAndCreateServiceComponent: function (componentName) { - var self = this; - var dfd = $.Deferred(); - var updater = App.router.get('updateController'); - updater.updateComponentsState(function () { - updater.updateServiceMetric(function () { - self.createServiceComponent(componentName, dfd); - }); - }); - return dfd.promise(); - }, - - /** - * - * @param componentName - * @param dfd - * @returns {*} - */ - createServiceComponent: function (componentName, dfd) { - var allServiceComponents = []; - var services = App.Service.find().mapProperty('serviceName'); - services.forEach(function (_service) { - var _serviceComponents = App.Service.find(_service).get('serviceComponents'); - allServiceComponents = allServiceComponents.concat(_serviceComponents); - }, this); - if (allServiceComponents.contains(componentName)) { - dfd.resolve(); - } else { - App.ajax.send({ - name: 'common.create_component', - sender: this, - data: { - componentName: componentName, - serviceName: App.StackServiceComponent.find().findProperty('componentName', componentName).get('serviceName') - } - }).complete(function () { - dfd.resolve(); - }); - } - } -}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/test/controllers/main/host/details_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js index 463bbc2..6121cc5 100644 --- a/ambari-web/test/controllers/main/host/details_test.js +++ b/ambari-web/test/controllers/main/host/details_test.js @@ -23,7 +23,6 @@ require('models/service'); require('models/host_component'); require('models/host_stack_version'); var batchUtils = require('utils/batch_scheduled_requests'); -var componentsUtils = require('utils/components'); var hostsManagement = require('utils/hosts'); var controller; @@ -35,7 +34,7 @@ describe('App.MainHostDetailsController', function () { then: Em.K, complete: Em.K }); - controller = App.MainHostDetailsController.create({ + controller = App.MainHostDetailsController.create(App.InstallComponent, { content: Em.Object.create({ hostComponents: [] }) @@ -226,11 +225,11 @@ describe('App.MainHostDetailsController', function () { }); describe('#ajaxErrorCallback()', function () { - it('call componentsUtils.ajaxErrorCallback', function () { - sinon.stub(componentsUtils, 'ajaxErrorCallback', Em.K); + it('call mainServiceItemController.ajaxErrorCallback', function () { + sinon.stub(controller, 'ajaxErrorCallback', Em.K); controller.ajaxErrorCallback('request', 'ajaxOptions', 'error', 'opt', 'params'); - expect(componentsUtils.ajaxErrorCallback.calledWith('request', 'ajaxOptions', 'error', 'opt', 'params')).to.be.true; - componentsUtils.ajaxErrorCallback.restore(); + expect(controller.ajaxErrorCallback.calledWith('request', 'ajaxOptions', 'error', 'opt', 'params')).to.be.true; + controller.ajaxErrorCallback.restore(); }); }); @@ -478,18 +477,23 @@ describe('App.MainHostDetailsController', function () { beforeEach(function () { sinon.spy(App, "showConfirmationPopup"); sinon.stub(controller, "addClientComponent", Em.K); - sinon.stub(controller, "primary", Em.K); - controller.set('content', {hostComponents: [Em.Object.create({ - componentName: "HDFS_CLIENT" - })]}); - sinon.stub(componentsUtils, 'checkComponentDependencies', Em.K); + sinon.stub(controller, "installHostComponentCall", Em.K); + sinon.stub(controller, "checkComponentDependencies", Em.K); + controller.set('content', { + hostComponents: [Em.Object.create({ + componentName: "HDFS_CLIENT" + })] + }); + controller.reopen({ + securityEnabled: false + }); }); afterEach(function () { App.showConfirmationPopup.restore(); controller.addClientComponent.restore(); - controller.primary.restore(); - componentsUtils.checkComponentDependencies.restore(); + controller.installHostComponentCall.restore(); + controller.checkComponentDependencies.restore(); }); it('add ZOOKEEPER_SERVER', function () { @@ -498,12 +502,8 @@ describe('App.MainHostDetailsController', function () { componentName: 'ZOOKEEPER_SERVER' }) }; - var popup = controller.addComponent(event); + controller.addComponent(event); expect(App.showConfirmationPopup.calledOnce).to.be.true; - popup.onPrimary(); - expect(controller.primary.calledWith(Em.Object.create({ - componentName: 'ZOOKEEPER_SERVER' - }))).to.be.true; }); it('add slave component', function () { var event = { @@ -591,60 +591,16 @@ describe('App.MainHostDetailsController', function () { beforeEach(function () { sinon.spy(App.ModalPopup, 'show'); - sinon.stub(controller, 'primary', Em.K); }); afterEach(function () { App.ModalPopup.show.restore(); - controller.primary.restore(); }); it('should display add component confirmation', function () { - var popup = controller.showAddComponentPopup(message, false, function () { - controller.primary(component); - }); + var popup = controller.showAddComponentPopup(message, false, Em.K); expect(App.ModalPopup.show.calledOnce).to.be.true; expect(popup.get('addComponentMsg')).to.eql(Em.I18n.t('hosts.host.addComponent.msg').format(message)); - popup.onPrimary(); - expect(controller.primary.calledWith(component)).to.be.true; - }); - }); - - describe('#primary()', function () { - beforeEach(function () { - sinon.stub(App.StackServiceComponent, 'find', function () { - return [ - Em.Object.create({ - componentName: 'COMP1', - serviceName: 's1' - }) - ] - }); - - sinon.stub(App.router, 'get', function () { - return Em.Object.create({ - updateComponentsState: function (callback) { - return callback(); - }, - updateServiceMetric: function (callback) { - return callback(); - } - }) - }); - }); - afterEach(function () { - App.router.get.restore(); - App.StackServiceComponent.find.restore(); - }); - - it('Query should be sent', function () { - var component = Em.Object.create({ - componentName: 'COMP1', - displayName: 'comp1' - }); - App.serviceComponents = ['COMP1']; - controller.primary(component); - expect(App.ajax.send.calledOnce).to.be.true; }); }); @@ -2093,16 +2049,16 @@ describe('App.MainHostDetailsController', function () { }))).to.equal(0); }); }); - describe('#downloadClientConfigs()', function () { + describe('#downloadClientConfigsCall', function () { beforeEach(function () { - sinon.stub(componentsUtils, 'downloadClientConfigs', Em.K); + sinon.stub(controller, 'downloadClientConfigsCall', Em.K); }); afterEach(function () { - componentsUtils.downloadClientConfigs.restore(); + controller.downloadClientConfigsCall.restore(); }); - it('should launch componentsUtils.downloadClientConfigs method', function () { + it('should launch controller.downloadClientConfigsCall method', function () { controller.downloadClientConfigs({ context: Em.Object.create({ componentName: 'name', @@ -2110,7 +2066,7 @@ describe('App.MainHostDetailsController', function () { displayName: 'dName' }) }); - expect(componentsUtils.downloadClientConfigs.calledWith({ + expect(controller.downloadClientConfigsCall.calledWith({ componentName: 'name', hostName: 'host1', displayName: 'dName' @@ -2478,8 +2434,7 @@ describe('App.MainHostDetailsController', function () { showAlertPopupCalled: false, title: 'Clients to add have mutual dependencies' } - ], - componentsUtils = require('utils/components'); + ]; beforeEach(function () { sinon.stub(controller, 'sendComponentCommand', Em.K); @@ -2505,12 +2460,12 @@ describe('App.MainHostDetailsController', function () { App.get('router.mainAdminKerberosController').getSecurityType.restore(); App.showAlertPopup.restore(); App.StackServiceComponent.find.restore(); - componentsUtils.checkComponentDependencies.restore(); + controller.checkComponentDependencies.restore(); }); cases.forEach(function (item) { it(item.title, function () { - sinon.stub(componentsUtils, 'checkComponentDependencies', function (componentName, params) { + sinon.stub(controller, 'checkComponentDependencies', function (componentName, params) { return item.dependencies[componentName]; }); controller.installClients({ http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/test/controllers/main/service/item_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/service/item_test.js b/ambari-web/test/controllers/main/service/item_test.js index f27508b..b3151dd 100644 --- a/ambari-web/test/controllers/main/service/item_test.js +++ b/ambari-web/test/controllers/main/service/item_test.js @@ -27,7 +27,6 @@ require('controllers/global/cluster_controller'); require('controllers/main/service/reassign_controller'); require('controllers/main/service/item'); var batchUtils = require('utils/batch_scheduled_requests'); -var componentsUtils = require('utils/components'); describe('App.MainServiceItemController', function () { @@ -1076,15 +1075,15 @@ describe('App.MainServiceItemController', function () { }); beforeEach(function () { - sinon.stub(componentsUtils, 'downloadClientConfigs', Em.K); + sinon.stub(mainServiceItemController, 'downloadClientConfigsCall', Em.K); }); afterEach(function () { - componentsUtils.downloadClientConfigs.restore(); + mainServiceItemController.downloadClientConfigsCall.restore(); }); it('should launch $.fileDownload method', function () { mainServiceItemController.downloadClientConfigs(); - expect(componentsUtils.downloadClientConfigs.calledWith({ + expect(mainServiceItemController.downloadClientConfigsCall.calledWith({ serviceName: 'S1', componentName: 'C1', displayName: 'd1' @@ -1096,7 +1095,7 @@ describe('App.MainServiceItemController', function () { name: 'name1' }; mainServiceItemController.downloadClientConfigs(event); - expect(componentsUtils.downloadClientConfigs.calledWith({ + expect(mainServiceItemController.downloadClientConfigsCall.calledWith({ serviceName: 'S1', componentName: 'name1', displayName: 'label1' http://git-wip-us.apache.org/repos/asf/ambari/blob/0fc88bed/ambari-web/test/mixins/wizard/wizardProgressPageController_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mixins/wizard/wizardProgressPageController_test.js b/ambari-web/test/mixins/wizard/wizardProgressPageController_test.js index a9b8822..84efaf5 100644 --- a/ambari-web/test/mixins/wizard/wizardProgressPageController_test.js +++ b/ambari-web/test/mixins/wizard/wizardProgressPageController_test.js @@ -30,7 +30,7 @@ describe('App.wizardProgressPageControllerMixin', function() { callback(); }}); }); - sinon.stub(require('utils/components'), "updateAndCreateServiceComponent").returns({ + sinon.stub(mixedObjectInstance, "updateAndCreateServiceComponent").returns({ done: function(callback) { return callback(); } @@ -70,7 +70,7 @@ describe('App.wizardProgressPageControllerMixin', function() { afterEach(function() { App.ajax.send.restore(); App.StackServiceComponent.find.restore(); - require('utils/components').updateAndCreateServiceComponent.restore(); + mixedObjectInstance.updateAndCreateServiceComponent.restore(); mixedObjectInstance.onCreateComponent.restore(); mixedObjectInstance.updateComponent.restore(); mixedObjectInstance.checkInstalledComponents.restore();