AMBARI-22420 - Enable mpack version selection (Jason Golieb via jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4087a117 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4087a117 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4087a117 Branch: refs/heads/branch-feature-AMBARI-14714-ui Commit: 4087a11790b76c05898935e9689a377399e13bec Parents: 0d39eb4 Author: Jonathan Hurley <[email protected]> Authored: Mon Nov 13 13:31:05 2017 -0500 Committer: Jonathan Hurley <[email protected]> Committed: Mon Nov 13 13:31:05 2017 -0500 ---------------------------------------------------------------------- .gitignore | 1 + ambari-web/app/app.js | 3 +- ambari-web/app/controllers/installer.js | 221 ++++--- .../app/controllers/main/host/add_controller.js | 2 +- .../controllers/main/service/add_controller.js | 4 +- ambari-web/app/controllers/wizard.js | 8 +- .../wizard/configureDownload_controller.js | 9 +- .../wizard/downloadProducts_controller.js | 45 +- .../wizard/selectMpacks_controller.js | 167 +++-- .../app/controllers/wizard/step2_controller.js | 20 +- .../app/controllers/wizard/step3_controller.js | 9 + .../app/controllers/wizard/step5_controller.js | 10 + .../app/controllers/wizard/step6_controller.js | 14 + .../app/controllers/wizard/step7_controller.js | 2 +- .../app/controllers/wizard/step8_controller.js | 13 +- ambari-web/app/messages.js | 6 +- .../mixins/wizard/assign_master_components.js | 30 +- ambari-web/app/routes/installer.js | 154 +++-- .../common/assign_master_components.hbs | 4 + .../app/templates/wizard/selectMpacks.hbs | 6 +- .../app/templates/wizard/selectMpacks/mpack.hbs | 14 +- .../selectMpacks/selectedMpackVersion.hbs | 2 +- ambari-web/app/templates/wizard/step2.hbs | 3 + ambari-web/app/templates/wizard/step3.hbs | 5 +- ambari-web/app/templates/wizard/step6.hbs | 3 + ambari-web/app/views.js | 2 - .../app/views/wizard/selectMpacks/mpack_view.js | 31 - .../selectMpacks/selectedMpackVersion_view.js | 27 - .../app/views/wizard/selectMpacks_view.js | 53 +- ambari-web/app/views/wizard/step2_view.js | 1 + ambari-web/app/views/wizard/step6_view.js | 1 + ambari-web/test/controllers/installer_test.js | 110 +++- .../main/host/add_controller_test.js | 2 +- .../main/service/add_controller_test.js | 2 +- .../controllers/wizard/selectMpacks_test.js | 633 ++++++++++++++++++- .../test/controllers/wizard/step5_test.js | 1 + .../test/controllers/wizard/step6_test.js | 13 +- .../test/controllers/wizard/step8_test.js | 127 ++-- ambari-web/test/views/wizard/step2_view_test.js | 7 +- ambari-web/test/views/wizard/step6_view_test.js | 5 +- 40 files changed, 1364 insertions(+), 406 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index a40e61a..50b7ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.ignore .classpath .project .settings http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/app.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js index 2526baa..8c79b79 100644 --- a/ambari-web/app/app.js +++ b/ambari-web/app/app.js @@ -373,7 +373,8 @@ module.exports = Em.Application.create({ addableMasterInstallerWizard: function () { return App.StackServiceComponent.find().filterProperty('isMasterAddableInstallerWizard').mapProperty('componentName') - }.property('App.router.clusterController.isLoaded'), + }.property(), + //.property('App.router.clusterController.isLoaded'), multipleMasters: function () { return App.StackServiceComponent.find().filterProperty('isMasterWithMultipleInstances').mapProperty('componentName') http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js index 5dd0941..14ae790 100644 --- a/ambari-web/app/controllers/installer.js +++ b/ambari-web/app/controllers/installer.js @@ -82,7 +82,12 @@ App.InstallerController = App.WizardController.extend(App.Persist, { controllerName: 'installerController', mpacks: [], mpackVersions: [], - mpackServices: [] + mpackServices: [], + // Tracks which steps have been saved before. + // If you revisit a step, we will know if the step has been saved previously and we can warn about making changes. + // If a previously saved step is changed, setStepSaved() will "unsave" all subsequent steps so we don't warn on every screen. + // Furthermore, we only need to track this state for steps that have an affect on subsequent steps. + stepsSavedState: null }), /** @@ -98,7 +103,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, { 'installOptions', 'allHostNamesPattern', 'serviceComponents', - 'clientInfo', + 'clients', 'selectedServiceNames', 'serviceConfigGroups', 'serviceConfigProperties', @@ -117,7 +122,8 @@ App.InstallerController = App.WizardController.extend(App.Persist, { 'selectedMpacks', 'selectedServices', 'selectedStack', - 'downloadConfig' + 'downloadConfig', + 'stepsSavedState' ], init: function () { @@ -585,11 +591,16 @@ App.InstallerController = App.WizardController.extend(App.Persist, { * Load master component hosts data for using in required step controllers * @param inMemory {Boolean}: Load master component hosts from memory */ - loadMasterComponentHosts: function (inMemory) { - var props = this.getDBProperties(['masterComponentHosts', 'hosts']); - var masterComponentHosts = !!inMemory ? this.get("content.masterComponentHosts") : props.masterComponentHosts, - hosts = props.hosts || {}, - hostNames = Em.keys(hosts); + loadMasterComponentHosts: function (lookInMemoryOnly) { + var props = this.getDBProperties(['masterComponentHosts', 'hosts']), + masterComponentHosts = this.get("content.masterComponentHosts"), + hosts = props.hosts || {}, + hostNames = Em.keys(hosts); + + if (!lookInMemoryOnly && !masterComponentHosts) { + masterComponentHosts = props.masterComponentHosts; + } + if (Em.isNone(masterComponentHosts)) { masterComponentHosts = []; } else { @@ -652,7 +663,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, { }); }, this); }, this); - this.setDBProperty('clientInfo', clients); + this.setDBProperty('clients', clients); this.set('content.clients', clients); }, @@ -1021,6 +1032,7 @@ App.InstallerController = App.WizardController.extend(App.Persist, { { type: 'sync', callback: function () { + this.load('stepsSavedState'); this.load('cluster'); } } @@ -1035,68 +1047,21 @@ App.InstallerController = App.WizardController.extend(App.Persist, { ], 'configureDownload': [ { - type: 'async', + type: 'sync', callback: function () { - var dfd = $.Deferred(); - - this.loadStacks().done(function(stacksLoaded) { - App.router.get('clusterController').loadAmbariProperties().always(function() { - dfd.resolve(stacksLoaded); - }); - }); - - return dfd.promise(); + this.load('downloadConfig'); } }, - // { - // type: 'async', - // callback: function (stacksLoaded) { - // var dfd = $.Deferred(); - // - // if (!stacksLoaded) { - // $.when.apply(this, this.loadStacksVersions()).done(function () { - // dfd.resolve(true); - // }); - // } else { - // dfd.resolve(stacksLoaded); - // } - // - // return dfd.promise(); - // } - // } ], - // 'step1': [ - // { - // type: 'async', - // callback: function () { - // var dfd = $.Deferred(); - // - // this.loadStacks().done(function(stacksLoaded) { - // App.router.get('clusterController').loadAmbariProperties().always(function() { - // dfd.resolve(stacksLoaded); - // }); - // }); - // - // return dfd.promise(); - // } - // }, - // { - // type: 'async', - // callback: function (stacksLoaded) { - // var dfd = $.Deferred(); - // - // if (!stacksLoaded) { - // $.when.apply(this, this.loadStacksVersions()).done(function () { - // dfd.resolve(true); - // }); - // } else { - // dfd.resolve(stacksLoaded); - // } - // - // return dfd.promise(); - // } - // } - // ], + 'selectMpacks': [ + { + type: 'sync', + callback: function () { + this.load('selectedServices'); + this.load('selectedMpacks'); + } + } + ], 'step3': [ { type: 'sync', @@ -1105,19 +1070,17 @@ App.InstallerController = App.WizardController.extend(App.Persist, { } } ], - // 'step4': [ - // { - // type: 'async', - // callback: function () { - // return this.loadServices(); - // } - // } - // ], 'step5': [ { + type: 'async', + callback: function () { + return this.finishRegisteringMpacks(this.getStepSavedState('step5')); + } + }, + { type: 'sync', callback: function () { - this.setSkipSlavesStep(App.StackService.find().filterProperty('isSelected'), 6); //TODO: something needs to be changed here + this.setSkipSlavesStep(App.StackService.find().filterProperty('isSelected'), this.getStepIndex('step7')); this.loadMasterComponentHosts(); this.loadConfirmedHosts(); this.loadComponentsFromConfigs(); @@ -1153,6 +1116,14 @@ App.InstallerController = App.WizardController.extend(App.Persist, { return dfd.promise(); } } + ], + 'step8': [ + { + type: 'sync', + callback: function () { + this.load('selectedStack'); + } + } ] }, @@ -1364,6 +1335,104 @@ App.InstallerController = App.WizardController.extend(App.Persist, { } } sCallback(); + }, + + clearStackServices: function () { + const stackServices = App.StackService.find(); + stackServices.forEach(service => { + Em.run.once(this, () => App.MpackServiceMapper.deleteRecord(service)); + }); + }, + + getStepSavedState: function (stepName) { + const stepIndex = this.getStepIndex(stepName); + const stepsSaved = this.get('content.stepsSavedState'); + + if (!!stepIndex && stepsSaved && stepsSaved[stepIndex]) { + return true; + } + + return false; + }, + + setStepUnsaved: function (stepName) { + const stepIndex = this.getStepIndex(stepName); + const oldState = this.get('content.stepsSavedState') || {}; + const newState = Em.Object.create(oldState); + newState[stepIndex] = false; + + this.set('content.stepsSavedState', newState); + this.save('stepsSavedState'); + }, + + /** + * Updates the stepsSaved array based on the stepName provided. + * If the passed step is already saved, then nothing is changed. + * Otherwise, the passed step is set to saved and all subsequent steps are set to unsaved. + * + * @param {type} stepName Name of the step being saved. + */ + setStepSaved: function (stepName) { + const stepIndex = this.getStepIndex(stepName); + const oldState = this.get('content.stepsSavedState') || {}; + const newState = Em.Object.create(oldState); + + if (!newState[stepIndex]) { + for (let i = stepIndex + 1, length = this.get('steps').length; i < length; i++) { + newState[i] = false; + }; + + newState[stepIndex] = true; + + this.set('content.stepsSavedState', newState); + this.save('stepsSavedState'); + } + }, + + /** + * This runs when Step5 loads and completes the mpack registration process that was begun in the Download Mpacks step. + * It populates the StackService model from the stack version definitions. + * Then, it persists info about the selected services and the selected stack. + * + * @return {object} a promise + */ + finishRegisteringMpacks: function (keepStackServices) { + return this.getMpackStackVersions().then(data => { + data.items.forEach(versionDefinition => App.stackMapper.map(versionDefinition)) + + if (!keepStackServices) { + this.clearStackServices(); + } + + //get info about services from specific stack versions and save to StackService model + const selectedServices = this.get('content.selectedServices'); + const servicePromises = selectedServices.map(service => this.loadMpackServiceInfo(service.stackName, service.stackVersion, service.name)); + + return $.when(...servicePromises).then(() => { + const services = App.StackService.find(); + this.set('content.services', services); + + const clients = []; + services.forEach(service => { + const client = service.get('serviceComponents').filterProperty('isClient', true); + client.forEach(clientComponent => { + clients.pushObject({ + component_name: clientComponent.get('componentName'), + display_name: clientComponent.get('displayName'), + isInstalled: false + }); + }); + }); + this.set('content.clients', clients); + this.save('clients'); + + // - for now, pull the stack from the single mpack that we can install + // - when we can support multiple mpacks, make this an array of selectedStacks (or just use the selectedServices array?) and add the repo data to it + const selectedService = selectedServices[0]; + this.set('content.selectedStack', { name: selectedService.stackName, version: selectedService.stackVersion }); + this.save('selectedStack'); + }); + }); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/main/host/add_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host/add_controller.js b/ambari-web/app/controllers/main/host/add_controller.js index 6b158c1..bd528f2 100644 --- a/ambari-web/app/controllers/main/host/add_controller.js +++ b/ambari-web/app/controllers/main/host/add_controller.js @@ -223,7 +223,7 @@ App.AddHostController = App.WizardController.extend({ var serviceComponents = App.StackServiceComponent.find(); var services = this.get('content.services').filterProperty('isInstallable').filterProperty('isSelected'); var clients = this.getClientsToInstall(services, serviceComponents); - this.setDBProperty('clientInfo', clients); + this.setDBProperty('clients', clients); this.set('content.clients', clients); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/main/service/add_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/add_controller.js b/ambari-web/app/controllers/main/service/add_controller.js index c11bcf2..0399a48 100644 --- a/ambari-web/app/controllers/main/service/add_controller.js +++ b/ambari-web/app/controllers/main/service/add_controller.js @@ -378,7 +378,7 @@ App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs, { }, this); }, this); - this.setDBProperty('clientInfo', clients); + this.setDBProperty('clients', clients); this.set('content.clients', clients); }, @@ -386,7 +386,7 @@ App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs, { * Load information about hosts with clients components */ loadClients: function () { - var clients = this.getDBProperty('clientInfo'); + var clients = this.getDBProperty('clients'); if (clients) { this.set('content.clients', clients); } else { http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js index 540cc63..c5a07ff 100644 --- a/ambari-web/app/controllers/wizard.js +++ b/ambari-web/app/controllers/wizard.js @@ -319,14 +319,14 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM return false; } - if ((this.get('currentStep') - step) > 1 && !disableNaviWarning) { + if ((this.get('currentStep') - step) > 0 && !disableNaviWarning) { App.ModalPopup.show({ header: Em.I18n.t('installer.navigation.warning.header'), onPrimary: function () { App.router.send('goto' + stepName.capitalize()); this.hide(); }, - body: "If you proceed to go back to Step " + step + ", you will lose any changes you have made beyond this step" + body: Em.I18n.t('installer.navigation.warning') }); } else { App.router.send('goto' + stepName.capitalize()); @@ -1257,7 +1257,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM * Load information about hosts with clients components */ loadClients: function () { - var clients = this.getDBProperty('clientInfo'); + var clients = this.getDBProperty('clients'); this.set('content.clients', clients); }, @@ -1374,7 +1374,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM }, /** - * Determine if <code>Assign Slaves and Clients</code> step should be skipped + * Determine if <code>Assign Slaves and Clients</code> step ("step7") should be skipped * @method setSkipSlavesStep * @param services * @param step http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/configureDownload_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/configureDownload_controller.js b/ambari-web/app/controllers/wizard/configureDownload_controller.js index f3a8b1b..0246ad0 100644 --- a/ambari-web/app/controllers/wizard/configureDownload_controller.js +++ b/ambari-web/app/controllers/wizard/configureDownload_controller.js @@ -49,8 +49,9 @@ App.WizardConfigureDownloadController = Em.Controller.extend({ }, loadStep: function () { - if (!this.get('content.downloadConfig')) { - let downloadConfig = this.get('wizardController').getDBProperty('downloadConfig'); + let downloadConfig = this.get('content.downloadConfig'); + //if (!this.get('content.downloadConfig')) { + //let downloadConfig = this.get('wizardController').getDBProperty('downloadConfig'); if (!downloadConfig) { downloadConfig = { @@ -60,7 +61,7 @@ App.WizardConfigureDownloadController = Em.Controller.extend({ } this.set('content.downloadConfig', downloadConfig); - } + //} }, /** @@ -90,7 +91,7 @@ App.WizardConfigureDownloadController = Em.Controller.extend({ return; } - this.get('wizardController').setDBProperty('downloadConfig', this.get('content.downloadConfig')); + //this.get('wizardController').setDBProperty('downloadConfig', this.get('content.downloadConfig')); App.router.send('next'); } http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/downloadProducts_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/downloadProducts_controller.js b/ambari-web/app/controllers/wizard/downloadProducts_controller.js index 165debb..b353732 100644 --- a/ambari-web/app/controllers/wizard/downloadProducts_controller.js +++ b/ambari-web/app/controllers/wizard/downloadProducts_controller.js @@ -24,7 +24,7 @@ App.WizardDownloadProductsController = Em.Controller.extend({ mpacks: [], addMpacks: function () { - const selectedMpacks = this.get('content.selectedMpacks') || this.get('wizardController').getDBProperty('selectedMpacks'); + const selectedMpacks = this.get('content.selectedMpacks'); selectedMpacks.forEach(mpack => { this.get('mpacks').pushObject(Em.Object.create({ @@ -95,14 +95,7 @@ App.WizardDownloadProductsController = Em.Controller.extend({ return mpacks.filterProperty('success', false).length > 0 || App.get('router.btnClickInProgress'); }.property('[email protected]', 'App.router.btnClickInProgress'), - /** - * Onclick handler for <code>Next</code> button. - * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress') - * @method submit - */ submit: function () { - const self = this; - if (App.get('router.nextBtnClickInProgress')) { return; } @@ -121,41 +114,7 @@ App.WizardDownloadProductsController = Em.Controller.extend({ //var versionData = installerController.getSelectedRepoVersionData(); //This would be used to post a VDF xml for a local repo (I think), but do we still need to do this when we will just be using mpacks? $.when(...stackVersionsRegistered).always(() => { //this uses always() because the api call made by createMpackStackVersion will return a 500 error //if the stack version has already been registered, but we want to proceed anyway - self.get('wizardController').getMpackStackVersions().then(data => { - data.items.forEach(versionDefinition => App.stackMapper.map(versionDefinition)) - - //get info about services from specific stack versions and save to StackService model - const selectedServices = self.get('content.selectedServices') || self.get('wizardController').getDBProperty('selectedServices'); - const servicePromises = selectedServices.map(service => self.get('wizardController').loadMpackServiceInfo(service.stackName, service.stackVersion, service.name)); - - $.when(...servicePromises).then(() => { - const serviceInfo = App.StackService.find(); - self.set('content.services', serviceInfo); - - const clients = []; - serviceInfo.forEach(service => { - const client = service.get('serviceComponents').filterProperty('isClient', true); - client.forEach(clientComponent => { - clients.pushObject({ - component_name: clientComponent.get('componentName'), - display_name: clientComponent.get('displayName'), - isInstalled: false - }); - }); - }); - self.set('content.clients', clients); - self.get('wizardController').setDBProperty('clientInfo', clients); - - // - for now, pull the stack from the single mpack that we can install - // - when we can support multiple mpacks, make this an array of selectedStacks (or just use the selectedServices array?) and add the repo data to it - const selectedService = selectedServices[0]; - const selectedStack = self.get('wizardController').getStack(selectedService.stackName, selectedService.stackVersion); - self.set('content.selectedStack', selectedStack); - self.get('wizardController').setDBProperty('selectedStack', selectedStack); - - App.router.send('next'); - }); - }); + App.router.send('next'); }); }); } http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/selectMpacks_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/selectMpacks_controller.js b/ambari-web/app/controllers/wizard/selectMpacks_controller.js index 9ab5a12..a7c62ff 100644 --- a/ambari-web/app/controllers/wizard/selectMpacks_controller.js +++ b/ambari-web/app/controllers/wizard/selectMpacks_controller.js @@ -22,19 +22,15 @@ App.WizardSelectMpacksController = Em.Controller.extend({ name: 'wizardSelectMpacksController', - //mpacks: Em.computed.alias('content.mpacks'), - - getMpacks: function () { - App.ajax.send({ + loadRegistry: function () { + return App.ajax.send({ name: 'registry.mpacks.versions', showLoadingPopup: true, - sender: this, - success: 'getMpacksSucceeded', - error: 'getMpacksFailed' + sender: this }); }, - getMpacksSucceeded: function (data) { + loadRegistrySucceeded: function (data) { const mpacks = data.items.reduce( (mpacks, registry) => mpacks.concat( registry.mpacks.map(mpack => { @@ -42,9 +38,10 @@ App.WizardSelectMpacksController = Em.Controller.extend({ name: mpack.RegistryMpackInfo.mpack_name, description: mpack.RegistryMpackInfo.mpack_description, logoUrl: mpack.RegistryMpackInfo.mpack_logo_url, - versions: mpack.versions ? mpack.versions.map(version => { + versions: mpack.versions ? mpack.versions.map((version, index) => { return Em.Object.create({ selected: false, + displayed: index === 0 ? true : false, //by default, display first version id: mpack.RegistryMpackInfo.mpack_name + version.RegistryMpackVersionInfo.mpack_version, version: version.RegistryMpackVersionInfo.mpack_version, docUrl: version.RegistryMpackVersionInfo.mpack_dock_url, @@ -89,19 +86,56 @@ App.WizardSelectMpacksController = Em.Controller.extend({ this.set('content.mpackServices', mpackServices); }, - getMpacksFailed: function () { + isSaved: function () { + const wizardController = this.get('wizardController'); + if (wizardController) { + return wizardController.getStepSavedState('selectMpacks'); + } + return false; + }.property('wizardController.content.stepsSavedState'), + + loadRegistryFailed: function () { this.set('content.mpacks', []); + + App.showAlertPopup( + Em.I18n.t('common.error'), //header + Em.I18n.t('installer.selectMpacks.loadRegistryFailed') //body + ); }, - loadStep: function () { + getRegistry: function () { + const deferred = $.Deferred(); + const mpacks = this.get('content.mpacks'); const mpackVersions = this.get('content.mpackVersions'); const mpackServices = this.get('content.mpackServices'); if (!mpacks || mpacks.length === 0 || !mpackVersions || mpackVersions.length === 0 || !mpackServices || mpackServices.length === 0) { - //this.showLoadingSpinner(); - this.getMpacks(); + this.loadRegistry().then(registry => { + this.loadRegistrySucceeded(registry); + deferred.resolve(); + }, + () => { + this.loadRegistryFailed(); + deferred.reject(); + }); + } else { + deferred.resolve(); } + + return deferred.promise(); + }, + + loadStep: function () { + this.getRegistry().then(() => { + //add previously selected services + const selectedServices = this.get('content.selectedServices'); + if (selectedServices) { + selectedServices.forEach(service => { + this.addService(service.id); + }); + } + }); }, isSubmitDisabled: function () { @@ -109,37 +143,68 @@ App.WizardSelectMpacksController = Em.Controller.extend({ return mpackServices.filterProperty('selected', true).length === 0 || App.get('router.btnClickInProgress'); }.property('[email protected]', 'App.router.btnClickInProgress'), - loadSelectionFailed: function () { - App.showAlertPopup( - Em.I18n.t('common.error'), //header - Em.I18n.t('installer.selectMpacks.loadSelectionFailed') //body - ); - }, - - /** - * Adds service to selection. - * - * @param {string} serviceName - */ - selectService: function (event) { - const serviceId = event.context; + getServiceById: function (serviceId) { const mpackServices = this.get('content.mpackServices'); const byServiceId = service => service.id === serviceId; - const service = mpackServices.find(byServiceId); - service.set('selected', true); - service.set('mpackVersion.selected', true); + return service; }, - removeService: function (event) { - const serviceId = event.context; - const mpackServices = this.get('content.mpackServices'); - const byServiceId = service => service.id === serviceId; + getMpackVersionById: function (versionId) { + const mpackVersions = this.get('content.mpackVersions'); + const byVersionId = version => version.id === versionId; + const version = mpackVersions.find(byVersionId); + return version; + }, - const service = mpackServices.find(byServiceId); - service.set('selected', false); + displayMpackVersion: function (versionId) { + const version = this.getMpackVersionById(versionId); + + if (version) { + version.mpack.versions.forEach(mpackVersion => { + if (mpackVersion.get('id') === versionId) { + mpackVersion.set('displayed', true); + } else { + mpackVersion.set('displayed', false); + } + }) + } + }, + + addServiceHandler: function (serviceId) { + if (this.addService(serviceId)) { + this.get('wizardController').setStepUnsaved('selectMpacks'); + } + }, + + addService: function (serviceId) { + const service = this.getServiceById(serviceId); + + if (service) { + service.set('selected', true); + service.set('mpackVersion.selected', true); + return true; + } + + return false; + }, + + removeServiceHandler: function (serviceId) { + if (this.removeService(serviceId)) { + this.get('wizardController').setStepUnsaved('selectMpacks'); + } + }, - service.set('mpackVersion.selected', service.get('mpackVersion.services').some(s => s.get('selected') === true)); + removeService: function (serviceId) { + const service = this.getServiceById(serviceId); + + if (service) { + service.set('selected', false); + service.set('mpackVersion.selected', service.get('mpackVersion.services').some(s => s.get('selected') === true)); + return true; + } + + return false; }, selectedServices: function () { @@ -157,21 +222,32 @@ App.WizardSelectMpacksController = Em.Controller.extend({ return versions ? versions.some(v => v.get('selected') === true) : false; }.property('[email protected]', 'selectedServices'), + clearSelection: function () { + const mpackServices = this.get('content.mpackServices'); + if (mpackServices) { + mpackServices.setEach('selected', false); + } + + const versions = this.get('content.mpackVersions'); + if (versions) { + versions.setEach('selected', false); + } + }, + /** * Onclick handler for <code>Next</code> button. * Disable 'Next' button while it is already under process. (using Router's property 'nextBtnClickInProgress') * @method submit */ submit: function () { - const self = this; - - if(App.get('router.nextBtnClickInProgress')) { + if (App.get('router.nextBtnClickInProgress')) { return; } if (!this.get('isSubmitDisabled')) { const selectedServices = this.get('selectedServices').map(service => ({ + id: service.id, name: service.name, mpackName: service.mpackVersion.name, mpackVersion: service.mpackVersion.version, @@ -179,14 +255,12 @@ App.WizardSelectMpacksController = Em.Controller.extend({ stackVersion: service.mpackVersion.stackVersion }) ); - self.set('content.selectedServices', selectedServices); - self.get('wizardController').setDBProperty('selectedServices', selectedServices); + this.set('content.selectedServices', selectedServices); const selectedServiceNames = selectedServices.map(service => service.name); - self.set('content.selectedServiceNames', selectedServiceNames); - self.get('wizardController').setDBProperty('selectedServiceNames', selectedServiceNames); + this.set('content.selectedServiceNames', selectedServiceNames); - const selectedMpacks = self.get('selectedMpackVersions').map(mpackVersion => + const selectedMpacks = this.get('selectedMpackVersions').map(mpackVersion => ({ name: mpackVersion.mpack.name, displayName: mpackVersion.mpack.displayName, @@ -194,8 +268,7 @@ App.WizardSelectMpacksController = Em.Controller.extend({ version: mpackVersion.version }) ); - self.set('content.selectedMpacks', selectedMpacks); - self.get('wizardController').setDBProperty('selectedMpacks', selectedMpacks); + this.set('content.selectedMpacks', selectedMpacks); App.router.send('next'); } http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/step2_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step2_controller.js b/ambari-web/app/controllers/wizard/step2_controller.js index 05813e2..dffc17e 100644 --- a/ambari-web/app/controllers/wizard/step2_controller.js +++ b/ambari-web/app/controllers/wizard/step2_controller.js @@ -115,6 +115,14 @@ App.WizardStep2Controller = Em.Controller.extend({ */ hostsError: null, + isSaved: function () { + const wizardController = this.get('wizardController'); + if (wizardController) { + return wizardController.getStepSavedState('step2'); + } + return false; + }.property('wizardController.content.stepsSavedState'), + useSSH: function () { return !App.get('isHadoopWindowsStack'); }.property('App.isHadoopWindowsStack'), @@ -169,6 +177,11 @@ App.WizardStep2Controller = Em.Controller.extend({ */ isSubmitDisabled: Em.computed.or('hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError', 'App.router.btnClickInProgress'), + loadStep: function () { + //save initial hostNames value to check later if changes were made + this.set('initialHostNames', this.get('content.installOptions.hostNames')); + }, + installedHostNames: function () { var installedHostsName = []; var hosts = this.get('content.hosts'); @@ -313,7 +326,7 @@ App.WizardStep2Controller = Em.Controller.extend({ /** * check is there a pattern expression in host name textarea - * push hosts that match pattern in hostNamesArr + * push hosts that match pattern in hostNameArr * @method parseHostNamesAsPatternExpression */ parseHostNamesAsPatternExpression: function () { @@ -546,6 +559,10 @@ App.WizardStep2Controller = Em.Controller.extend({ * @method saveHosts */ saveHosts: function () { + if (this.get('content.installOptions.hostNames') !== this.get('initialHostNames')) { + this.get('wizardController').setStepUnsaved('step2'); + } + var hosts = this.get('content.hosts'); //add previously installed hosts @@ -555,6 +572,7 @@ App.WizardStep2Controller = Em.Controller.extend({ } } + //this.set('content.installOptions.hostNames', this.get('hostNameArr')); this.set('content.hosts', $.extend(hosts, this.getHostInfo())); this.setAmbariJavaHome(); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/step3_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step3_controller.js b/ambari-web/app/controllers/wizard/step3_controller.js index 2c61e02..36bf05a 100644 --- a/ambari-web/app/controllers/wizard/step3_controller.js +++ b/ambari-web/app/controllers/wizard/step3_controller.js @@ -75,6 +75,14 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, App.Check return (this.get('isRegistrationInProgress') || !this.get('isWarningsLoaded')) && !this.get('isBootstrapFailed') || App.get('router.btnClickInProgress'); }.property('isRegistrationInProgress', 'isWarningsLoaded', 'isBootstrapFailed'), + isSaved: function () { + const wizardController = this.get('wizardController'); + if (wizardController) { + return wizardController.getStepSavedState('step3'); + } + return false; + }.property('wizardController.content.stepsSavedState'), + /** * Controller is using in Add Host Wizard * @return {bool} @@ -305,6 +313,7 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, App.Check if (!self.hosts.length) { self.set('isSubmitDisabled', true); } + self.get('wizardController').setStepUnsaved('step3'); }, Em.I18n.t('installer.step3.hosts.remove.popup.body')); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/step5_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step5_controller.js b/ambari-web/app/controllers/wizard/step5_controller.js index 8736652..3ca4165 100644 --- a/ambari-web/app/controllers/wizard/step5_controller.js +++ b/ambari-web/app/controllers/wizard/step5_controller.js @@ -22,6 +22,16 @@ App.WizardStep5Controller = Em.Controller.extend(App.BlueprintMixin, App.AssignM name: "wizardStep5Controller", + stepName: 'step5', + + isSaved: function () { + const wizardController = this.get('wizardController'); + if (wizardController) { + return wizardController.getStepSavedState(this.get('stepName')); + } + return false; + }.property('wizardController.content.stepsSavedState'), + _goNextStepIfValid: function () { App.set('router.nextBtnClickInProgress', false); if (!this.get('submitDisabled')) { http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/step6_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step6_controller.js b/ambari-web/app/controllers/wizard/step6_controller.js index 68ec3ed..b1941f0 100644 --- a/ambari-web/app/controllers/wizard/step6_controller.js +++ b/ambari-web/app/controllers/wizard/step6_controller.js @@ -95,6 +95,18 @@ App.WizardStep6Controller = Em.Controller.extend(App.HostComponentValidationMixi */ isInstallerWizard: Em.computed.equal('content.controllerName', 'installerController'), + isSaved: function () { + const wizardController = this.get('wizardController'); + if (wizardController) { + return wizardController.getStepSavedState('step6'); + } + return false; + }.property('wizardController.content.stepsSavedState'), + + hostsChanged: function () { + this.get('wizardController').setStepUnsaved('step6'); + }, + isAllCheckboxesEmpty: function() { var hosts = this.get('hosts'); for (var i = 0; i < hosts.length; i++) { @@ -267,6 +279,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.HostComponentValidationMixi }); }); this.checkCallback(component); + this.hostsChanged(); }, /** @@ -301,6 +314,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.HostComponentValidationMixi */ loadStep: function () { this.clearStep(); + var parentController = App.router.get(this.get('content.controllerName')); if (parentController && parentController.get('content.componentsFromConfigs')) { parentController.clearConfigActionComponents(); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/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 3def063..4b1eacb 100644 --- a/ambari-web/app/controllers/wizard/step7_controller.js +++ b/ambari-web/app/controllers/wizard/step7_controller.js @@ -477,9 +477,9 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E if (!this.get('isConfigsLoaded')) { return; } + console.time('wizard loadStep: '); this.clearStep(); - var self = this; App.config.setPreDefinedServiceConfigs(this.get('addMiscTabToPage')); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/controllers/wizard/step8_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js index 0c72295..3ad65f1 100644 --- a/ambari-web/app/controllers/wizard/step8_controller.js +++ b/ambari-web/app/controllers/wizard/step8_controller.js @@ -151,14 +151,9 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz }.property(), getSelectedStack: function() { - let selectedStack = this.get('content.selectedStack'); - - if (!selectedStack) { - const stack = this.get('wizardController').getDBProperty('selectedStack'); - selectedStack = this.get('wizardController').getStack(stack.stack_name, stack.stack_version); - } - - return selectedStack; + const selectedStack = this.get('content.selectedStack'); + const stack = this.get('wizardController').getStack(selectedStack.name, selectedStack.version); + return stack; }, installedServices: function() { @@ -651,7 +646,7 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz self.set('isBackBtnDisabled', false); wizardController.setStepsEnable(); if (self.get('isAddService')) { - wizardController.setSkipSlavesStep(wizardController.getDBProperty('selectedServiceNames'), 3); //TODO: something + wizardController.setSkipSlavesStep(wizardController.getDBProperty('selectedServiceNames'), 3); } }); } else { http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 82adc80..c9bae25 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -584,7 +584,9 @@ Em.I18n.translations = { 'installer.header':'Cluster Install Wizard', 'installer.navigation.warning.header':'Navigation Warning', - + 'installer.navigation.warning':'If you make changes to a previous step you will lose any changes saved in subsequent steps.', + 'installer.warning.changes.header':'Warning', + 'installer.warning.changes':'If you make changes to this step you will lose any changes saved in subsequent steps.', 'installer.noHostsAssigned':'No host assigned', 'installer.slaveComponentHosts.selectHosts':'select hosts for this group', 'installer.slaveComponentHostsPopup.header':'Select which hosts should belong to which {0} group', @@ -597,7 +599,7 @@ Em.I18n.translations = { 'installer.controls.serviceConfigMasterHosts.header':'{0} Hosts', 'installer.controls.slaveComponentChangeGroupName.error':'group with this name already exist', - 'installer.selectMpacks.loadSelectionFailed': 'Could not load Management Packs. The software registry may not be available.', + 'installer.selectMpacks.loadRegistryFailed': 'Could not load Management Packs. The software registry may not be available.', 'installer.selectMpacks.header': 'Select Management Packs', 'installer.selectMpacks.body.header': 'Select Management Packs', 'installer.selectMpacks.noMpacksAvailable': 'No management packs are available.', http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/mixins/wizard/assign_master_components.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/wizard/assign_master_components.js b/ambari-web/app/mixins/wizard/assign_master_components.js index 84a56f1..c547b5a 100644 --- a/ambari-web/app/mixins/wizard/assign_master_components.js +++ b/ambari-web/app/mixins/wizard/assign_master_components.js @@ -675,7 +675,7 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A */ createComponentInstallationObjects: function() { var stackMasterComponentsMap = {}, - masterHosts = this.get('content.masterComponentHosts') || this.get('masterComponentHosts'), //saved to local storage info + masterHosts = this.get('content.masterComponentHosts'), servicesToAdd = (this.get('content.services')|| []).filterProperty('isSelected').filterProperty('isInstalled', false).mapProperty('serviceName'), recommendations = this.get('recommendations'), resultComponents = [], @@ -955,13 +955,23 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A assignHostToMaster: function (componentName, selectedHost, serviceComponentId) { var flag = this.isHostNameValid(componentName, selectedHost); var component; + const stepName = this.get('stepName'); + this.updateIsHostNameValidFlag(componentName, serviceComponentId, flag); + if (serviceComponentId) { component = this.get('selectedServicesMasters').filterProperty('component_name', componentName).findProperty("serviceComponentId", serviceComponentId); - if (component) component.set("selectedHost", selectedHost); - } - else { + if (component) { + component.set("selectedHost", selectedHost); + if (stepName) { + this.get('wizardController').setStepUnsaved(stepName); + } + } + } else { this.get('selectedServicesMasters').findProperty("component_name", componentName).set("selectedHost", selectedHost); + if (stepName) { + this.get('wizardController').setStepUnsaved(stepName); + } } }, @@ -1093,6 +1103,12 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A }); this.incrementProperty('rebalanceComponentHostsCounter'); this.toggleProperty('hostNameCheckTrigger'); + + const stepName = this.get('stepName'); + if (stepName) { + this.get('wizardController').setStepUnsaved(stepName); + } + return true; } return false;//if no more zookeepers can be added @@ -1130,6 +1146,12 @@ App.AssignMasterComponents = Em.Mixin.create(App.HostComponentValidationMixin, A }); this.incrementProperty('rebalanceComponentHostsCounter'); this.toggleProperty('hostNameCheckTrigger'); + + const stepName = this.get('stepName'); + if (stepName) { + this.get('wizardController').setStepUnsaved(stepName); + } + return true; }, http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/routes/installer.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/routes/installer.js b/ambari-web/app/routes/installer.js index 5899ff3..9a49c36 100644 --- a/ambari-web/app/routes/installer.js +++ b/ambari-web/app/routes/installer.js @@ -106,14 +106,14 @@ module.exports = Em.Route.extend(App.RouterRedirections, { next: function (router) { console.time('step0 next'); - var installerController = router.get('installerController'); - installerController.save('cluster'); + var controller = router.get('installerController'); + controller.save('cluster'); App.db.setStacks(undefined); App.db.setRepos(undefined); App.db.setLocalRepoVDFData(undefined); App.Stack.find().clear(); - installerController.set('content.stacks',undefined); + controller.set('content.stacks',undefined); router.transitionTo('step2'); console.timeEnd('step0 next'); } @@ -188,8 +188,10 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var controller = router.get('installerController'); var newStepIndex = controller.getStepIndex('step2'); router.setNavigationFlow(newStepIndex); - controller.clearInstallOptions(); + //controller.clearInstallOptions(); controller.setCurrentStep('step2'); + var wizardStep2Controller = router.get('wizardStep2Controller'); + wizardStep2Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { self.scrollTop(); controller.connectOutlet('wizardStep2', controller.get('content')); @@ -205,6 +207,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, { controller.save('installOptions'); //hosts was saved to content.hosts inside wizardStep2Controller controller.save('hosts'); + controller.setStepSaved('step2'); router.transitionTo('step3'); } console.timeEnd('step2 next'); @@ -218,9 +221,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var self = this; var controller = router.get('installerController'); controller.setCurrentStep('step3'); + var wizardStep3Controller = router.get('wizardStep3Controller'); + wizardStep3Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - var wizardStep3Controller = router.get('wizardStep3Controller'); - wizardStep3Controller.set('wizardController', controller); controller.connectOutlet('wizardStep3', controller.get('content')); self.scrollTop(); console.timeEnd('step3 connectOutlets'); @@ -235,14 +238,23 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('step3 next'); if (!router.get('btnClickInProgress')) { App.set('router.nextBtnClickInProgress', true); - var installerController = router.get('installerController'); + var controller = router.get('installerController'); var wizardStep3Controller = router.get('wizardStep3Controller'); - installerController.saveConfirmedHosts(wizardStep3Controller); - installerController.setDBProperties({ - bootStatus: true, - selectedServiceNames: undefined, - installedServiceNames: undefined - }); + controller.saveConfirmedHosts(wizardStep3Controller); + if (!wizardStep3Controller.get('isSaved')) { + App.router.get('wizardSelectMpacksController').clearSelection(); + controller.set('content.selectedServices', undefined); + controller.set('content.selectedServiceNames', undefined); + controller.set('content.selectedMpacks', undefined); + controller.setDBProperties({ + bootStatus: true, + selectedServices: undefined, + selectedServiceNames: undefined, + installedServiceNames: undefined, + selectedMpack: undefined + }); + } + controller.setStepSaved('step3'); router.transitionTo('configureDownload'); console.timeEnd('step3 next'); } @@ -268,12 +280,12 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('configureDownload connectOutlets'); var self = this; var controller = router.get('installerController'); - var configureDownloadController = router.get('wizardConfigureDownloadController'); var newStepIndex = controller.getStepIndex('configureDownload'); router.setNavigationFlow(newStepIndex); controller.setCurrentStep('configureDownload'); + var configureDownloadController = router.get('wizardConfigureDownloadController'); + configureDownloadController.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - configureDownloadController.set('wizardController', controller); controller.connectOutlet('wizardConfigureDownload', controller.get('content')); self.scrollTop(); console.timeEnd('configureDownload connectOutlets'); @@ -286,8 +298,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { return; } App.set('router.nextBtnClickInProgress', true); - var installerController = router.get('installerController'); - installerController.setDBProperty('service', undefined); + var controller = router.get('installerController'); + controller.save('downloadConfig'); + controller.setDBProperty('service', undefined); router.transitionTo('selectMpacks'); console.timeEnd('configureDownload next'); } @@ -301,9 +314,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var self = this; var controller = router.get('installerController'); controller.setCurrentStep('selectMpacks'); + var wizardSelectMpacksController = router.get('wizardSelectMpacksController'); + wizardSelectMpacksController.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - var wizardSelectMpacksController = router.get('wizardSelectMpacksController'); - wizardSelectMpacksController.set('wizardController', controller); controller.connectOutlet('wizardSelectMpacks', controller.get('content')); self.scrollTop(); console.timeEnd('selectMpacks connectOutlets'); @@ -318,6 +331,22 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('selectMpacks next'); if (!router.get('btnClickInProgress')) { App.set('router.nextBtnClickInProgress', true); + var controller = router.get('installerController'); + controller.save('selectedServiceNames'); + controller.save('selectedServices'); + controller.save('selectedMpacks'); + var wizardStep6Controller = router.get('wizardStep6Controller'); + // Clear subsequent settings if user changed service selections + if (!wizardStep6Controller.get('isSaved')) { + router.get('wizardStep5Controller').clearRecommendations(); + controller.setDBProperty('recommendations', undefined); + controller.set('content.masterComponentHosts', undefined); + controller.setDBProperty('masterComponentHosts', undefined); + controller.clearEnhancedConfigs(); + controller.setDBProperty('slaveComponentHosts', undefined); + wizardStep6Controller.set('isClientsSet', false); + } + controller.setStepSaved('selectMpacks'); router.transitionTo('downloadProducts'); console.timeEnd('selectMpacks next'); } @@ -330,12 +359,12 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('downloadProducts connectOutlets'); var self = this; var controller = router.get('installerController'); - var configureDownloadController = router.get('wizardDownloadProductsController'); var newStepIndex = controller.getStepIndex('downloadProducts'); router.setNavigationFlow(newStepIndex); controller.setCurrentStep('downloadProducts'); + var downloadProductsController = router.get('wizardDownloadProductsController'); + downloadProductsController.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - configureDownloadController.set('wizardController', controller); controller.connectOutlet('wizardDownloadProducts', controller.get('content')); self.scrollTop(); console.timeEnd('downloadProducts connectOutlets'); @@ -352,13 +381,6 @@ module.exports = Em.Route.extend(App.RouterRedirections, { return; } App.set('router.nextBtnClickInProgress', true); - router.get('wizardStep5Controller').clearRecommendations(); // Force reload recommendation before step 5 - var controller = router.get('installerController'); - controller.setDBProperties({ - recommendations: undefined, - masterComponentHosts: undefined - }); - controller.clearEnhancedConfigs(); router.transitionTo('step5'); console.timeEnd('downloadProducts next'); } @@ -373,9 +395,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var newStepIndex = controller.getStepIndex('step4'); router.setNavigationFlow(newStepIndex); controller.setCurrentStep('step4'); + var wizardStep4Controller = router.get('wizardStep4Controller'); + wizardStep4Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - var wizardStep4Controller = router.get('wizardStep4Controller'); - wizardStep4Controller.set('wizardController', controller); controller.connectOutlet('wizardStep4', App.StackService.find().filterProperty('isInstallable', true)); self.scrollTop(); console.timeEnd('step4 connectOutlets'); @@ -419,9 +441,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { servicesMasters: [], isInitialLayout: true }); + wizardStep5Controller.set('wizardController', controller); controller.setCurrentStep('step5'); controller.loadAllPriorSteps().done(function () { - wizardStep5Controller.set('wizardController', controller); controller.connectOutlet('wizardStep5', controller.get('content')); self.scrollTop(); console.timeEnd('step5 connectOutlets'); @@ -436,13 +458,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, { App.set('router.nextBtnClickInProgress', true); var controller = router.get('installerController'); var wizardStep5Controller = router.get('wizardStep5Controller'); - var wizardStep6Controller = router.get('wizardStep6Controller'); controller.saveMasterComponentHosts(wizardStep5Controller); - controller.setDBProperties({ - slaveComponentHosts: undefined, - recommendations: wizardStep5Controller.get('content.recommendations') - }); - wizardStep6Controller.set('isClientsSet', false); + controller.setDBProperty('recommendations', wizardStep5Controller.get('content.recommendations')); + // Clear subsequent steps if user made changes + if (!wizardStep5Controller.get('isSaved')) { + controller.setDBProperty('slaveComponentHosts', undefined); + var wizardStep6Controller = router.get('wizardStep6Controller'); + wizardStep6Controller.set('isClientsSet', false); + } + controller.setStepSaved('step5'); router.transitionTo('step6'); } console.timeEnd('step5 next'); @@ -457,8 +481,10 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var controller = router.get('installerController'); var newStepIndex = controller.getStepIndex('step6'); router.setNavigationFlow(newStepIndex); - router.get('wizardStep6Controller').set('hosts', []); controller.setCurrentStep('step6'); + var wizardStep6Controller = router.get('wizardStep6Controller'); + wizardStep6Controller.set('hosts', []); + wizardStep6Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { controller.connectOutlet('wizardStep6', controller.get('content')); self.scrollTop(); @@ -480,13 +506,17 @@ module.exports = Em.Route.extend(App.RouterRedirections, { controller.saveSlaveComponentHosts(wizardStep6Controller); controller.get('content').set('serviceConfigProperties', null); controller.get('content').set('componentsFromConfigs', []); - controller.setDBProperties({ - serviceConfigGroups: null, - recommendationsHostGroups: wizardStep6Controller.get('content.recommendationsHostGroups'), - recommendationsConfigs: null, - componentsFromConfigs: [] - }); - controller.clearServiceConfigProperties(); + // Clear subsequent steps if user made changes + if (!wizardStep6Controller.get('isSaved')) { + controller.setDBProperties({ + serviceConfigGroups: null, + recommendationsHostGroups: wizardStep6Controller.get('content.recommendationsHostGroups'), + recommendationsConfigs: null, + componentsFromConfigs: [] + }); + controller.clearServiceConfigProperties(); + } + controller.setStepSaved('step6'); router.transitionTo('step7'); console.timeEnd('step6 next'); } @@ -511,8 +541,8 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var controller = router.get('installerController'); router.get('preInstallChecksController').loadStep(); var wizardStep7Controller = router.get('wizardStep7Controller'); + wizardStep7Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - wizardStep7Controller.set('wizardController', controller); controller.connectOutlet('wizardStep7', controller.get('content')); self.scrollTop(); console.timeEnd('step7 connectOutlets'); @@ -563,9 +593,9 @@ module.exports = Em.Route.extend(App.RouterRedirections, { var controller = router.get('installerController'); var self = this; controller.setCurrentStep('step8'); + var wizardStep8Controller = router.get('wizardStep8Controller'); + wizardStep8Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { - var wizardStep8Controller = router.get('wizardStep8Controller'); - wizardStep8Controller.set('wizardController', controller); controller.connectOutlet('wizardStep8', controller.get('content')); self.scrollTop(); console.timeEnd('step8 connectOutlets'); @@ -580,13 +610,13 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('step8 next'); if (!router.get('btnClickInProgress')) { App.set('router.nextBtnClickInProgress', true); - var installerController = router.get('installerController'); + var controller = router.get('installerController'); var wizardStep8Controller = router.get('wizardStep8Controller'); // invoke API call to install selected services - installerController.installServices(false, function () { - installerController.setInfoForStep9(); + controller.installServices(false, function () { + controller.setInfoForStep9(); // We need to do recovery based on whether we are in Add Host or Installer wizard - installerController.saveClusterState('CLUSTER_INSTALLING_3'); + controller.saveClusterState('CLUSTER_INSTALLING_3'); wizardStep8Controller.set('servicesInstalled', true); router.transitionTo('step9'); console.timeEnd('step8 next'); @@ -600,15 +630,15 @@ module.exports = Em.Route.extend(App.RouterRedirections, { connectOutlets: function (router, context) { console.time('step9 connectOutlets'); var self = this; - var controller = router.get('installerController'), - wizardStep9Controller = router.get('wizardStep9Controller'); + var controller = router.get('installerController'); + var wizardStep9Controller = router.get('wizardStep9Controller'); + wizardStep9Controller.set('wizardController', controller); controller.loadAllPriorSteps().done(function () { wizardStep9Controller.loadDoServiceChecksFlag().done(function () { controller.setCurrentStep('step9'); if (!App.get('testMode')) { controller.setLowerStepsDisable(9); } - wizardStep9Controller.set('wizardController', controller); controller.connectOutlet('wizardStep9', controller.get('content')); self.scrollTop(); console.timeEnd('step9 connectOutlets'); @@ -618,16 +648,16 @@ module.exports = Em.Route.extend(App.RouterRedirections, { back: Em.Router.transitionTo('step8'), retry: function (router) { console.time('step9 retry'); - var installerController = router.get('installerController'); + var controller = router.get('installerController'); var wizardStep9Controller = router.get('wizardStep9Controller'); if (wizardStep9Controller.get('showRetry')) { if (wizardStep9Controller.get('content.cluster.status') === 'INSTALL FAILED') { var isRetry = true; - installerController.installServices(isRetry, function () { - installerController.setInfoForStep9(); + controller.installServices(isRetry, function () { + controller.setInfoForStep9(); wizardStep9Controller.resetHostsForRetry(); // We need to do recovery based on whether we are in Add Host or Installer wizard - installerController.saveClusterState('CLUSTER_INSTALLING_3'); + controller.saveClusterState('CLUSTER_INSTALLING_3'); wizardStep9Controller.navigateStep(); }); } else { @@ -649,10 +679,10 @@ module.exports = Em.Route.extend(App.RouterRedirections, { console.time('step9 next'); if(!router.get('btnClickInProgress')) { App.set('router.nextBtnClickInProgress', true); - var installerController = router.get('installerController'); + var controller = router.get('installerController'); var wizardStep9Controller = router.get('wizardStep9Controller'); - installerController.saveInstalledHosts(wizardStep9Controller); - installerController.saveClusterState('CLUSTER_INSTALLED_4'); + controller.saveInstalledHosts(wizardStep9Controller); + controller.saveClusterState('CLUSTER_INSTALLED_4'); router.transitionTo('step10'); console.timeEnd('step9 next'); } http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/common/assign_master_components.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/assign_master_components.hbs b/ambari-web/app/templates/common/assign_master_components.hbs index a47e3f6..49eaa10 100644 --- a/ambari-web/app/templates/common/assign_master_components.hbs +++ b/ambari-web/app/templates/common/assign_master_components.hbs @@ -22,6 +22,10 @@ <p class="step-description"> {{{view.alertMessage}}} </p> + {{#if isSaved}} + <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div> + {{/if}} + <div class="panel panel-default"> <div class="panel-body"> {{#each msg in controller.generalErrorMessages}} http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/selectMpacks.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/selectMpacks.hbs b/ambari-web/app/templates/wizard/selectMpacks.hbs index dd55ff3..19855d3 100644 --- a/ambari-web/app/templates/wizard/selectMpacks.hbs +++ b/ambari-web/app/templates/wizard/selectMpacks.hbs @@ -17,14 +17,16 @@ }} <div id="select-mpacks" class="wizard-content col-md-9"> <h4 class="step-title">{{t installer.selectMpacks.body.header}}</h4> - + {{#if isSaved}} + <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div> + {{/if}} <div class="display-flex"> + <!-- Registry --> <div class="panel panel-default col-md-8"> <div class="panel-heading"> <p>{{t installer.selectMpacks.body.options.header}}</p> </div> <div class="panel-body"> - <!-- Registry --> <div class="options-list"> {{#if controller.content.mpacks}} {{#each mpack in controller.content.mpacks}} http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/selectMpacks/mpack.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/selectMpacks/mpack.hbs b/ambari-web/app/templates/wizard/selectMpacks/mpack.hbs index aea598e..9a65baf 100644 --- a/ambari-web/app/templates/wizard/selectMpacks/mpack.hbs +++ b/ambari-web/app/templates/wizard/selectMpacks/mpack.hbs @@ -17,14 +17,20 @@ }} <div class="mpack-body"> <div class="mpack-title" role="tab" id="headingOne"> - <p>{{mpack.name}} {{view.version}}</p> + {{mpack.name}} + <select {{action "changeVersion" on="change" target="view"}}> + {{#each ver in mpack.versions}} + <option {{bindAttr value="ver.id" selected="ver.displayed"}}>{{ver.version}}</option> + {{/each}} + </select> </div> + <div>{{mpack.description}}</div> <div> {{#each service in view.services}} - <button {{bindAttr id="service.name"}} class="capsule" {{action "selectService" service.id target="controller"}}> - {{service.name}} <i class="icon icon-plus"></i> + <button {{bindAttr id="service.name"}} class="capsule" {{action "addService" service.id target="view"}}> + {{service.name}} {{service.version}} <i class="icon icon-plus"></i> <span {{bindAttr class="selected:service-remove:service-add"}} {{bindAttr title="service.version"}}></span> </button> {{/each}} </div> -</div> \ No newline at end of file +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/selectMpacks/selectedMpackVersion.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/selectMpacks/selectedMpackVersion.hbs b/ambari-web/app/templates/wizard/selectMpacks/selectedMpackVersion.hbs index cba1177..05e75ff 100644 --- a/ambari-web/app/templates/wizard/selectMpacks/selectedMpackVersion.hbs +++ b/ambari-web/app/templates/wizard/selectMpacks/selectedMpackVersion.hbs @@ -22,7 +22,7 @@ <div> {{#each service in mpackVersion.services}} {{#if service.selected}} - <button {{bindAttr id="service.name"}} class="capsule" {{action "removeService" service.id target="controller"}}> + <button {{bindAttr id="service.name"}} class="capsule" {{action "removeService" service.id target="view"}}> {{service.name}} <i class="icon">×</i> <span {{bindAttr class="selected:service-remove:service-add" title="service.version"}}></span> </button> http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/step2.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/step2.hbs b/ambari-web/app/templates/wizard/step2.hbs index b4ee25c..685ff79 100644 --- a/ambari-web/app/templates/wizard/step2.hbs +++ b/ambari-web/app/templates/wizard/step2.hbs @@ -19,6 +19,9 @@ <div id="installOptions" class="wizard-content col-md-9"> <h4 class="step-header">{{t installer.step2.header}}</h4> <p class="step-description">{{t installer.step2.body}}</p> + {{#if isSaved}} + <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div> + {{/if}} <div class="panel panel-default"> <div class="panel-body"> http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/step3.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/step3.hbs b/ambari-web/app/templates/wizard/step3.hbs index b480fd3..2f060fc 100644 --- a/ambari-web/app/templates/wizard/step3.hbs +++ b/ambari-web/app/templates/wizard/step3.hbs @@ -19,6 +19,9 @@ <div id="confirm-hosts" class="wizard-content col-md-9"> <h4 class="step-header">{{t installer.step3.header}}</h4> <p class="step-description" {{QAAttr "step3-description"}}>{{t installer.step3.body}}</p> + {{#if isSaved}} + <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div> + {{/if}} <div class="panel panel-default"> <div class="panel-body"> @@ -160,4 +163,4 @@ {{t common.next}} → </button> </div> -</div> \ No newline at end of file +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/templates/wizard/step6.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/step6.hbs b/ambari-web/app/templates/wizard/step6.hbs index 5741f09..8d9e883 100644 --- a/ambari-web/app/templates/wizard/step6.hbs +++ b/ambari-web/app/templates/wizard/step6.hbs @@ -19,6 +19,9 @@ <div id="step6" class="wizard-content col-md-9"> <h4 class="step-header" {{QAAttr "step-title"}}>{{t installer.step6.header}}</h4> <p class="step-description">{{{view.label}}}</p> + {{#if isSaved}} + <div class="alert alert-warning" role="alert"><strong>{{t installer.warning.changes.header}}</strong> {{t installer.warning.changes}}</div> + {{/if}} <div class="panel panel-default"> <div class="panel-body"> http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js index 1ef0b62..8810f13 100644 --- a/ambari-web/app/views.js +++ b/ambari-web/app/views.js @@ -380,8 +380,6 @@ require('views/wizard/step9_view'); require('views/wizard/step9/hostLogPopupBody_view'); require('views/wizard/step10_view'); require('views/wizard/selectMpacks_view'); -require('views/wizard/selectMpacks/mpack_view'); -require('views/wizard/selectMpacks/selectedMpackVersion_view'); require('views/loading'); require('views/experimental'); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views/wizard/selectMpacks/mpack_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/wizard/selectMpacks/mpack_view.js b/ambari-web/app/views/wizard/selectMpacks/mpack_view.js deleted file mode 100644 index 9c22eb9..0000000 --- a/ambari-web/app/views/wizard/selectMpacks/mpack_view.js +++ /dev/null @@ -1,31 +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'); - -App.WizardMpackView = Em.View.extend({ - templateName: require('templates/wizard/selectMpacks/mpack'), - - version: function() { - return this.get('mpack.versions')[0].version; - }.property(), - - services: function () { - return this.get('mpack.versions')[0].services; - }.property() -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views/wizard/selectMpacks/selectedMpackVersion_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/wizard/selectMpacks/selectedMpackVersion_view.js b/ambari-web/app/views/wizard/selectMpacks/selectedMpackVersion_view.js deleted file mode 100644 index ca503d7..0000000 --- a/ambari-web/app/views/wizard/selectMpacks/selectedMpackVersion_view.js +++ /dev/null @@ -1,27 +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'); - -App.WizardSelectedMpackVersionView = Em.View.extend({ - templateName: require('templates/wizard/selectMpacks/selectedMpackVersion'), - - mpack: function () { - return this.get('mpackVersion.mpack.name'); - }.property() -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views/wizard/selectMpacks_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/wizard/selectMpacks_view.js b/ambari-web/app/views/wizard/selectMpacks_view.js index 3dc4ec0..deab12b 100644 --- a/ambari-web/app/views/wizard/selectMpacks_view.js +++ b/ambari-web/app/views/wizard/selectMpacks_view.js @@ -16,7 +16,6 @@ * limitations under the License. */ - var App = require('app'); App.WizardSelectMpacksView = Em.View.extend({ @@ -24,5 +23,57 @@ App.WizardSelectMpacksView = Em.View.extend({ didInsertElement: function () { this.get('controller').loadStep(); + } +}); + +/** + * View for each mpack in the registry + */ +App.WizardMpackView = Em.View.extend({ + templateName: require('templates/wizard/selectMpacks/mpack'), + + services: function () { + return this.get('mpack.versions').filterProperty('displayed')[0].services; + }.property('[email protected]'), + + /** + * Handle mpack version changed + * + * @param {any} event + */ + changeVersion: function (event) { + const versionId = event.target.value; + this.get('controller').displayMpackVersion(versionId); }, + + /** + * Handle add service button clicked + * + * @param {type} event + */ + addService: function (event) { + const serviceId = event.context; + this.get('controller').addServiceHandler(serviceId); + } +}); + +/** + * View for each selected mpack + */ +App.WizardSelectedMpackVersionView = Em.View.extend({ + templateName: require('templates/wizard/selectMpacks/selectedMpackVersion'), + + mpack: function () { + return this.get('mpackVersion.mpack.name'); + }.property(), + + /** + * Handle remove service button clicked. + * + * @param {type} event + */ + removeService: function (event) { + const serviceId = event.context; + this.get('controller').removeServiceHandler(serviceId); + } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views/wizard/step2_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/wizard/step2_view.js b/ambari-web/app/views/wizard/step2_view.js index 6bbda30..e498a2d 100644 --- a/ambari-web/app/views/wizard/step2_view.js +++ b/ambari-web/app/views/wizard/step2_view.js @@ -60,6 +60,7 @@ App.WizardStep2View = Em.View.extend({ //todo: move them to conroller this.set('controller.hostsError', null); this.set('controller.sshKeyError', null); + this.get('controller').loadStep(); }, /** http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/app/views/wizard/step6_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/wizard/step6_view.js b/ambari-web/app/views/wizard/step6_view.js index ab37245..03a4dc1 100644 --- a/ambari-web/app/views/wizard/step6_view.js +++ b/ambari-web/app/views/wizard/step6_view.js @@ -83,6 +83,7 @@ App.WizardStep6View = App.TableView.extend({ Em.set(checkbox, 'checked', !checkbox.checked); this.get('controller').checkCallback(checkbox.component); this.get('controller').callValidation(); + this.get('controller').hostsChanged(); }, columnCount: function() { http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/test/controllers/installer_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js index f581d91..88289b2 100644 --- a/ambari-web/test/controllers/installer_test.js +++ b/ambari-web/test/controllers/installer_test.js @@ -537,11 +537,14 @@ describe('App.InstallerController', function () { }, loadRecommendations: function() { loadRecommendations = true; + }, + getStepIndex: function () { + return 0; } }; beforeEach(function () { - installerController.loadMap['step5'][0].callback.call(checker); + installerController.loadMap['step5'][1].callback.call(checker); }); it('confirmed hosts are loaded', function() { @@ -900,6 +903,7 @@ describe('App.InstallerController', function () { describe('#loadMasterComponentHosts', function() { beforeEach(function () { + installerController.set('content.masterComponentHosts', null); sinon.stub(installerController, 'getDBProperties', function() { return { masterComponentHosts: Em.A([ @@ -925,7 +929,7 @@ describe('App.InstallerController', function () { afterEach(function () { installerController.getDBProperties.restore(); }); - it ('Should load hosts', function() { + it('Should load hosts', function() { installerController.loadMasterComponentHosts(); expect(installerController.get('content.masterComponentHosts')).to.eql([ { @@ -1210,4 +1214,106 @@ describe('App.InstallerController', function () { }); + describe('#setStepSaved', function() { + beforeEach(function() { + installerController.set('steps', [ + "step0", + "step1", + "step2", + "step3", + "step4" + ]); + + installerController.set('content.stepsSavedState', null); + }); + + it('Should save step and unsave all subsequent steps when step is not saved yet', function() { + var expected = Em.Object.create({ + "1": true, + "2": false, + "3": false, + "4": false + }); + + installerController.setStepSaved('step1'); + var actual = installerController.get('content.stepsSavedState'); + expect(actual).to.deep.equal(expected); + expect(installerController.getStepSavedState('step1')).to.be.true; + }); + + it('Should do nothing when step is already saved', function() { + var expected = Em.Object.create({ + "1": true, + "2": true, + "3": true, + "4": true + }) + installerController.set('content.stepsSavedState', expected); + + installerController.setStepSaved('step1'); + var actual = installerController.get('content.stepsSavedState'); + expect(actual).to.deep.equal(expected); + expect(installerController.getStepSavedState('step1')).to.be.true; + }); + }); + + describe('#setStepUnsaved', function() { + beforeEach(function() { + installerController.set('steps', [ + "step0", + "step1", + "step2", + "step3", + "step4" + ]); + + var initial = Em.Object.create({ + "1": true, + "2": true, + "3": true, + "4": true + }) + installerController.set('content.stepsSavedState', initial); + }); + + it('Should set step to unsaved', function() { + var expected = Em.Object.create({ + "1": false, + "2": true, + "3": true, + "4": true + }) + + installerController.setStepUnsaved('step1'); + var actual = installerController.get('content.stepsSavedState'); + expect(actual).to.deep.equal(expected); + expect(installerController.getStepSavedState('step1')).to.be.false; + }); + }); + + describe('#getStepSavedState', function() { + beforeEach(function() { + installerController.set('steps', [ + "step0", + "step1", + "step2", + "step3", + "step4" + ]); + + var initial = Em.Object.create({ + "1": true, + "2": false + }) + installerController.set('content.stepsSavedState', initial); + }); + + it('Should return false for bad step name', function() { + expect(installerController.getStepSavedState('step5')).to.be.false; + }); + + it('Should return false for step that was never saved', function() { + expect(installerController.getStepSavedState('step0')).to.be.false; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/test/controllers/main/host/add_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/host/add_controller_test.js b/ambari-web/test/controllers/main/host/add_controller_test.js index 089d018..15be7ac 100644 --- a/ambari-web/test/controllers/main/host/add_controller_test.js +++ b/ambari-web/test/controllers/main/host/add_controller_test.js @@ -671,7 +671,7 @@ describe('App.AddHostController', function () { )).to.be.true; }); it('setDBProperty called with valid arguments', function () { - expect(controller.setDBProperty.calledWith('clientInfo', ['client'])).to.be.true; + expect(controller.setDBProperty.calledWith('clients', ['client'])).to.be.true; }); it('content.clients are valid', function () { expect(controller.get('content.clients')).to.be.eql(['client']); http://git-wip-us.apache.org/repos/asf/ambari/blob/4087a117/ambari-web/test/controllers/main/service/add_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/service/add_controller_test.js b/ambari-web/test/controllers/main/service/add_controller_test.js index 1119176..6315891 100644 --- a/ambari-web/test/controllers/main/service/add_controller_test.js +++ b/ambari-web/test/controllers/main/service/add_controller_test.js @@ -437,7 +437,7 @@ describe('App.AddServiceController', function() { describe(item.title, function () { beforeEach(function () { - sinon.stub(addServiceController, 'getDBProperty').withArgs('clientInfo').returns(item.clients); + sinon.stub(addServiceController, 'getDBProperty').withArgs('clients').returns(item.clients); sinon.stub(addServiceController, 'saveClients', Em.K); addServiceController.set('content.clients', []); addServiceController.loadClients();
