assign_master_controller.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var stringUtils = require('utils/string_utils');
  19. var numberUtils = require('utils/number_utils');
  20. var blueprintUtils = require('utils/blueprint');
  21. App.AssignMasterOnStep7Controller = Em.Controller.extend(App.BlueprintMixin, App.AssignMasterComponents, {
  22. name: "assignMasterOnStep7Controller",
  23. useServerValidation: false,
  24. showInstalledMastersFirst: false,
  25. configWidgetContext: {},
  26. configActionComponent: {},
  27. content: function () {
  28. return this.get('configWidgetContext.controller.content') || {};
  29. }.property('configWidgetContext.controller.content'),
  30. popup: null,
  31. mastersToCreate: [],
  32. markSavedComponentsAsInstalled: true,
  33. /**
  34. * Array of master component names, that should be addable
  35. * Are used in HA wizards to add components, that are not addable for other wizards
  36. * @type {Array}
  37. * @override
  38. */
  39. mastersAddableInHA: Em.computed.alias('App.components.isMasterAddableOnlyOnHA'),
  40. /**
  41. * Marks component add/delete action to be performed ahead.
  42. * @param context {Object} Context of the calling function
  43. * @param action {String} ADD|DELETE
  44. * @param hostComponent {Object}
  45. * @public
  46. * @method {execute}
  47. */
  48. execute: function (context, action, hostComponent) {
  49. this.set('configWidgetContext', context);
  50. this.set('content', context.get('controller.content'));
  51. this.set('configActionComponent', hostComponent);
  52. switch (action) {
  53. case 'ADD':
  54. this.clearRecommendations();
  55. if (hostComponent.componentName === "HIVE_SERVER_INTERACTIVE") {
  56. this.getPendingBatchRequests(hostComponent);
  57. } else {
  58. this.showPopup(hostComponent);
  59. }
  60. break;
  61. case 'DELETE':
  62. this.set('mastersToCreate', [hostComponent.componentName]);
  63. this.removeMasterComponent();
  64. break;
  65. }
  66. },
  67. getPendingBatchRequests: function(hostComponent) {
  68. var self = this;
  69. // Send Ajax request to get status of pending batch requests
  70. App.ajax.send({
  71. name : 'request_schedule.get.pending',
  72. sender: self,
  73. error : 'pendingBatchRequestsAjaxError',
  74. success: 'pendingBatchRequestsAjaxSuccess',
  75. data: {
  76. hostComponent: hostComponent
  77. }
  78. });
  79. },
  80. pendingBatchRequestsAjaxError: function(data) {
  81. var error = Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error');
  82. if (data && data.responseText) {
  83. try {
  84. var json = JSON.parse(data.responseText);
  85. error += json.message;
  86. } catch (err) {}
  87. }
  88. App.showAlertPopup(Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'), error, null);
  89. },
  90. pendingBatchRequestsAjaxSuccess : function(data, opt, params) {
  91. var self = this;
  92. if (this.shouldShowAlertOnBatchRequest(data)) {
  93. App.showAlertPopup(Em.I18n.t('services.service.actions.hsi.alertPopup.header'),
  94. Em.I18n.t('services.service.actions.hsi.alertPopup.body'), function() {
  95. var configWidgetContext = self.get('configWidgetContext');
  96. var config = configWidgetContext.get('config');
  97. configWidgetContext.toggleProperty('controller.forceUpdateBoundaries');
  98. var value = config.get('initialValue');
  99. config.set('value', value);
  100. configWidgetContext.setValue(value);
  101. configWidgetContext.sendRequestRorDependentConfigs(config);
  102. this.hide();
  103. });
  104. } else {
  105. this.showPopup(params.hostComponent);
  106. }
  107. },
  108. shouldShowAlertOnBatchRequest: function(data) {
  109. var showAlert = false;
  110. if (data.hasOwnProperty('items') && data.items.length > 0) {
  111. data.items.forEach( function(_item) {
  112. _item.RequestSchedule.batch.batch_requests.forEach( function(batchRequest) {
  113. // Check if a DELETE request on HIVE_SERVER_INTERACTIVE is in progress
  114. if (batchRequest.request_type === "DELETE" && batchRequest.request_uri.indexOf("HIVE_SERVER_INTERACTIVE") > -1) {
  115. showAlert = true;
  116. }
  117. });
  118. });
  119. }
  120. return showAlert;
  121. },
  122. showPopup: function(hostComponent) {
  123. var missingDependentServices = this.getAllMissingDependentServices();
  124. var isNonWizardPage = !this.get('content.controllerName');
  125. if (missingDependentServices.length && isNonWizardPage) {
  126. this.showInstallServicesPopup(missingDependentServices);
  127. } else {
  128. this.set('mastersToCreate', [hostComponent.componentName]);
  129. this.showAssignComponentPopup();
  130. }
  131. },
  132. /**
  133. * Used to set showAddControl/showRemoveControl flag
  134. * @param componentName
  135. * @override
  136. */
  137. updateComponent: function(componentName) {
  138. this._super(componentName);
  139. if (!this.get('mastersToCreate').contains(componentName)) {
  140. this.get("selectedServicesMasters").filterProperty("component_name", componentName).forEach(function(c) {
  141. c.set('showAddControl', false);
  142. c.set('showRemoveControl', false);
  143. });
  144. }
  145. },
  146. /**
  147. * Assign Master page will be displayed in the popup
  148. * @private
  149. * @method
  150. */
  151. showAssignComponentPopup: function () {
  152. var self = this;
  153. // Master component hosts should be loaded only when content.controller name is not defined i.e non-wizard pages
  154. if (!this.get('content.controllerName')) {
  155. this.loadMasterComponentHosts();
  156. }
  157. var mastersToCreate = this.get('mastersToCreate');
  158. var masterToCreateDisplayName = App.format.role(mastersToCreate[0]);
  159. var configWidgetContext = this.get('configWidgetContext');
  160. var config = this.get('configWidgetContext.config');
  161. var popup = App.ModalPopup.show({
  162. classNames: ['wizard-modal-wrapper', 'add-service-wizard-modal'],
  163. modalDialogClasses: ['modal-xlg'],
  164. header: Em.I18n.t('assign.master.popup.header').format(masterToCreateDisplayName),
  165. bodyClass: App.AssignMasterOnStep7View.extend({
  166. controller: self
  167. }),
  168. primary: Em.I18n.t('common.select'),
  169. onPrimary: function () {
  170. self.submit();
  171. },
  172. onSecondary: function() {
  173. this.showWarningPopup();
  174. },
  175. onClose: function () {
  176. this.showWarningPopup();
  177. },
  178. showWarningPopup: function() {
  179. var mainPopupContext = this;
  180. App.ModalPopup.show({
  181. encodeBody: false,
  182. header: Em.I18n.t('common.warning'),
  183. primaryClass: 'btn-warning',
  184. body: Em.I18n.t('assign.master.popup.cancel.body').format(masterToCreateDisplayName),
  185. onPrimary: function () {
  186. configWidgetContext.toggleProperty('controller.forceUpdateBoundaries');
  187. var value = config.get('initialValue');
  188. config.set('value', value);
  189. configWidgetContext.setValue(value);
  190. configWidgetContext.sendRequestRorDependentConfigs(config);
  191. this.hide();
  192. mainPopupContext.hide();
  193. }
  194. });
  195. },
  196. didInsertElement: function () {
  197. this._super();
  198. this.fitHeight();
  199. self.set('configWidgetContext.controller.saveInProgress', false);
  200. }
  201. });
  202. this.set('popup', popup);
  203. },
  204. /**
  205. * Displays the popup to install required service dependencies for being added component with this config change
  206. * @param missingDependentServices {String[]} Array of service display names
  207. */
  208. showInstallServicesPopup: function (missingDependentServices) {
  209. var displayServices = stringUtils.getFormattedStringFromArray(missingDependentServices);
  210. var configWidgetContext = this.get('configWidgetContext');
  211. var config = this.get('configWidgetContext.config');
  212. var configDisplayName = config.get('displayName').toLowerCase();
  213. return App.ModalPopup.show({
  214. header: Em.I18n.t('installer.step7.missing.service.header'),
  215. body: Em.I18n.t('installer.step7.missing.service.body').format(displayServices, configDisplayName),
  216. primaryClass: 'btn-danger',
  217. onPrimary: function () {
  218. configWidgetContext.toggleProperty('controller.forceUpdateBoundaries');
  219. var value = config.get('initialValue');
  220. config.set('value', value);
  221. configWidgetContext.setValue(value);
  222. configWidgetContext.sendRequestRorDependentConfigs(config);
  223. this._super();
  224. },
  225. secondary: null,
  226. showCloseButton: false,
  227. didInsertElement: function () {
  228. this._super();
  229. configWidgetContext.set('controller.saveInProgress', false);
  230. }
  231. });
  232. },
  233. /**
  234. * This method is used while installing or adding a service
  235. * Removes the masterComponent that was previously being tracked to be added to the cluster
  236. * @private
  237. * @method {removeMasterComponent}
  238. */
  239. removeMasterComponent: function () {
  240. var componentsToDelete = this.get('mastersToCreate');
  241. var componentsFromConfigs = this.get('content.componentsFromConfigs');
  242. if (this.get('content.controllerName')) {
  243. var masterComponentHosts = this.get('content.masterComponentHosts');
  244. var recommendationsHostGroups = this.get('content.recommendationsHostGroups');
  245. componentsToDelete.forEach(function (_componentName) {
  246. masterComponentHosts = masterComponentHosts.rejectProperty('component', _componentName);
  247. recommendationsHostGroups.blueprint.host_groups.forEach(function(hostGroup){
  248. hostGroup.components = hostGroup.components.rejectProperty('name', _componentName);
  249. }, this);
  250. componentsFromConfigs = componentsFromConfigs.without(_componentName);
  251. }, this);
  252. this.get('content').set('masterComponentHosts', masterComponentHosts);
  253. this.set('content.componentsFromConfigs', componentsFromConfigs);
  254. this.set('content.recommendationsHostGroups', recommendationsHostGroups);
  255. } else {
  256. this.clearComponentsToBeAdded(componentsToDelete[0]);
  257. var hostComponent = App.HostComponent.find().findProperty('componentName', componentsToDelete[0]);
  258. if (hostComponent) {
  259. App.set('componentToBeDeleted', Em.Object.create({
  260. componentName: componentsToDelete[0],
  261. hostName: hostComponent.get('hostName')
  262. }));
  263. }
  264. }
  265. var configActionComponent = this.get('configActionComponent');
  266. this.get('configWidgetContext.config').set('configActionComponent', configActionComponent);
  267. },
  268. /**
  269. * Success callback after loading active host list
  270. * @override
  271. * @method loadWizardHostsSuccessCallback
  272. */
  273. loadWizardHostsSuccessCallback: function (data) {
  274. var parentController = this.get('content.controllerName');
  275. if (parentController) {
  276. this._super(data);
  277. } else {
  278. var result = [];
  279. data.items.forEach(function (host) {
  280. var hostName = host.Hosts.host_name,
  281. cpu = host.Hosts.cpu_count,
  282. memory = host.Hosts.total_mem.toFixed(2);
  283. result.push(Em.Object.create({
  284. host_name: hostName,
  285. cpu: cpu,
  286. memory: memory,
  287. disk_info: host.Hosts.disk_info,
  288. maintenance_state: host.Hosts.maintenance_state,
  289. host_info: Em.I18n.t('installer.step5.hostInfo').fmt(hostName, numberUtils.bytesToSize(memory, 1, 'parseFloat', 1024), cpu)
  290. }));
  291. }, this);
  292. this.set('hosts', result);
  293. this.sortHosts(this.get('hosts'));
  294. this.set('isHostsLoaded', true);
  295. }
  296. },
  297. /**
  298. * This method is called on Service->config page and is responsible to load the "Assign Master popup"
  299. * with the installed master component hosts.
  300. * @private
  301. * @method {loadMasterComponentHosts}
  302. */
  303. loadMasterComponentHosts: function () {
  304. var stackMasterComponents = App.get('components.masters').uniq();
  305. var masterComponentHosts = [];
  306. App.HostComponent.find().filter(function (component) {
  307. return stackMasterComponents.contains(component.get('componentName'));
  308. }).forEach(function (item) {
  309. masterComponentHosts.push({
  310. component: item.get('componentName'),
  311. hostName: item.get('hostName'),
  312. isInstalled: true,
  313. serviceId: item.get('service.id'),
  314. display_name: item.get('displayName')
  315. })
  316. });
  317. this.set("masterComponentHosts", masterComponentHosts);
  318. },
  319. /**
  320. * Returns array of dependent services that are yet not installed in the cluster
  321. * @private
  322. * @method getAllMissingDependentServices
  323. * @return missingDependentServices {Array}
  324. */
  325. getAllMissingDependentServices: function () {
  326. var configActionComponentName = this.get('configActionComponent').componentName;
  327. var componentStackService = App.StackServiceComponent.find(configActionComponentName).get('stackService');
  328. var dependentServices = componentStackService.get('requiredServices');
  329. return dependentServices.filter(function (item) {
  330. return !App.Service.find().findProperty('serviceName', item);
  331. }).map(function (item) {
  332. return App.StackService.find(item).get('displayName');
  333. });
  334. },
  335. /**
  336. * This method saves masterComponent layout that is used on subsequent "Review" and "Install start and Test services" pages.
  337. * @private
  338. * @method {saveMasterComponentHosts}
  339. */
  340. saveMasterComponentHosts: function() {
  341. var controller = App.router.get(this.get('content.controllerName'));
  342. var componentsFromConfigs = this.get('content.componentsFromConfigs');
  343. controller.saveMasterComponentHosts(this, true);
  344. controller.loadMasterComponentHosts(true);
  345. componentsFromConfigs = componentsFromConfigs.concat(this.get('mastersToCreate'));
  346. this.set('content.componentsFromConfigs', componentsFromConfigs);
  347. },
  348. /**
  349. * This method saves host group layout that is used for blueprint validation call made while transitioning to "Review" page.
  350. * @private
  351. * @method {saveRecommendationsHostGroups}
  352. */
  353. saveRecommendationsHostGroups: function() {
  354. var recommendationsHostGroups = this.get('content.recommendationsHostGroups');
  355. var mastersToCreate = this.get('mastersToCreate');
  356. mastersToCreate.forEach(function(componentName) {
  357. var hostName = this.getSelectedHostName(componentName);
  358. if (hostName && recommendationsHostGroups) {
  359. var hostGroups = recommendationsHostGroups.blueprint_cluster_binding.host_groups;
  360. var isHostPresent = false;
  361. var i = 0;
  362. while (i < hostGroups.length) {
  363. var hosts = hostGroups[i].hosts;
  364. isHostPresent = hosts.someProperty('fqdn', hostName);
  365. if (isHostPresent) break;
  366. i++;
  367. }
  368. if (isHostPresent) {
  369. var hostGroupName = hostGroups[i].name;
  370. var hostGroup = recommendationsHostGroups.blueprint.host_groups.findProperty('name', hostGroupName);
  371. var addHostComponentInGroup = !hostGroup.components.someProperty('name', componentName);
  372. if (addHostComponentInGroup) {
  373. hostGroup.components.pushObject({name: componentName});
  374. }
  375. }
  376. }
  377. }, this);
  378. this.set('content.recommendationsHostGroups', recommendationsHostGroups);
  379. },
  380. /**
  381. * Get the fqdn hostname as selected by the user for the component.
  382. * @param componentName
  383. * @return {String}
  384. */
  385. getSelectedHostName: function(componentName) {
  386. var selectedServicesMasters = this.get('selectedServicesMasters');
  387. return selectedServicesMasters.findProperty('component_name', componentName).selectedHost;
  388. },
  389. /**
  390. * set App.componentToBeAdded to use it on subsequent validation call while saving configuration
  391. * @param componentName {String}
  392. * @param hostName {String}
  393. * @method {setGlobalComponentToBeAdded}
  394. */
  395. setGlobalComponentToBeAdded: function(componentName, hostName) {
  396. var componentToBeAdded = Em.Object.create({
  397. componentName: componentName,
  398. hostNames: [hostName]
  399. });
  400. App.set('componentToBeAdded', componentToBeAdded);
  401. },
  402. /**
  403. * clear 'componentToBeDeleted' object
  404. * @param componentName {String}
  405. * @public
  406. * @method {clearComponentsToBeDeleted}
  407. */
  408. clearComponentsToBeDeleted: function(componentName) {
  409. var componentsToBeDeleted = App.get('componentToBeDeleted');
  410. if (!App.isEmptyObject(componentsToBeDeleted) && componentsToBeDeleted.get('componentName') === componentName) {
  411. App.set('componentToBeDeleted', {});
  412. }
  413. },
  414. /**
  415. * clear 'componentToBeAdded' object
  416. * @param componentName {String}
  417. */
  418. clearComponentsToBeAdded: function(componentName) {
  419. var componentsToBeAdded = App.get('componentToBeAdded');
  420. if (!App.isEmptyObject(componentsToBeAdded) && componentsToBeAdded.get('componentName') === componentName) {
  421. App.set('componentToBeAdded', {});
  422. }
  423. },
  424. /**
  425. * Submit button click handler
  426. * @method submit
  427. */
  428. submit: function () {
  429. var self = this;
  430. App.get('router.mainAdminKerberosController').getKDCSessionState(function() {
  431. self.get('popup').hide();
  432. var context = self.get('configWidgetContext');
  433. context.toggleProperty('controller.forceUpdateBoundaries');
  434. var configActionComponent = self.get('configActionComponent');
  435. var componentHostName = self.getSelectedHostName(configActionComponent.componentName);
  436. var config = self.get('configWidgetContext.config');
  437. // TODO remove after stack advisor is able to handle this case
  438. // workaround for hadoop.proxyuser.{{hiveUser}}.hosts after adding Hive Server Interactive from Install Wizard
  439. var serviceConfigs = context.get('controller.stepConfigs').findProperty('serviceName', context.get('controller.selectedService.serviceName')).get('configs');
  440. var dependencies = context.get('config.configAction.dependencies');
  441. if (self.get('content.controllerName')) {
  442. self.saveMasterComponentHosts();
  443. self.saveRecommendationsHostGroups();
  444. // TODO remove after stack advisor is able to handle this case
  445. // workaround for hadoop.proxyuser.{{hiveUser}}.hosts after adding Hive Server Interactive from Install Wizard
  446. var miscConfigs = context.get('controller.stepConfigs').findProperty('serviceName', 'MISC').get('configs');
  447. serviceConfigs = serviceConfigs.concat(miscConfigs);
  448. } else {
  449. self.setGlobalComponentToBeAdded(configActionComponent.componentName, componentHostName);
  450. self.clearComponentsToBeDeleted(configActionComponent.componentName);
  451. }
  452. configActionComponent.hostName = componentHostName;
  453. config.set('configActionComponent', configActionComponent);
  454. /* TODO uncomment after stack advisor is able to handle this case
  455. var oldValueKey = context.get('controller.wizardController.name') === 'installerController' ? 'initialValue' : 'savedValue';
  456. context.get('controller').loadConfigRecommendations([{
  457. type: App.config.getConfigTagFromFileName(config.get('fileName')),
  458. name: config.get('name'),
  459. old_value: config.get(oldValueKey)
  460. }]);
  461. */
  462. self.resolveDependencies(dependencies, serviceConfigs, context);
  463. });
  464. },
  465. /**
  466. * TODO remove after stack advisor is able to handle this case
  467. * workaround for hadoop.proxyuser.{{hiveUser}}.hosts after adding Hive Server Interactive
  468. * @param {object} dependencies
  469. * @param {array} serviceConfigs
  470. * @param {Em.Object} context
  471. */
  472. resolveDependencies: function(dependencies, serviceConfigs, context) {
  473. if (dependencies) {
  474. var foreignKeys = this.getDependenciesForeignKeys(dependencies, serviceConfigs);
  475. if (dependencies.properties && dependencies.initializer) {
  476. var initializer = App.get(dependencies.initializer.name);
  477. var setup = Em.getProperties(foreignKeys, dependencies.initializer.setupKeys);
  478. initializer.setup(setup);
  479. var blueprintObject = {};
  480. dependencies.properties.forEach(function (property) {
  481. var propertyObject = Em.getProperties(property, ['name', 'fileName']);
  482. if (property.nameTemplate) {
  483. var name = property.nameTemplate;
  484. Em.keys(foreignKeys).forEach(function (key) {
  485. name = name.replace('{{' + key + '}}', foreignKeys[key]);
  486. });
  487. propertyObject.name = name;
  488. }
  489. if (!blueprintObject[property.fileName]) {
  490. blueprintObject[property.fileName] = {
  491. properties: {}
  492. };
  493. }
  494. var result = initializer.initialValue(propertyObject, {
  495. masterComponentHosts: this.getMasterComponents(dependencies, context)
  496. });
  497. var propertiesMap = blueprintObject[propertyObject.fileName].properties;
  498. propertiesMap[propertyObject.name] = result.value;
  499. if (property.isHostsList) {
  500. var service = App.config.get('serviceByConfigTypeMap')[propertyObject.fileName];
  501. if (service) {
  502. var serviceName = service.get('serviceName');
  503. var configs = serviceName === context.get('controller.selectedService.serviceName') ? serviceConfigs :
  504. context.get('controller.stepConfigs').findProperty('serviceName', serviceName).get('configs');
  505. var originalFileName = App.config.getOriginalFileName(propertyObject.fileName);
  506. var currentProperty = configs.find(function (configProperty) {
  507. return configProperty.get('filename') === originalFileName && configProperty.get('name') === propertyObject.name;
  508. });
  509. if (currentProperty) {
  510. propertiesMap[propertyObject.name] = currentProperty.get('value');
  511. App.config.updateHostsListValue(propertiesMap, propertyObject.fileName, propertyObject.name, propertyObject.value, property.isHostsArray);
  512. }
  513. }
  514. }
  515. this.saveRecommendations(context, blueprintObject);
  516. initializer.cleanup();
  517. }, this);
  518. }
  519. }
  520. },
  521. /**
  522. *
  523. * @param {Em.Object} context
  524. * @param {object} blueprintObject
  525. */
  526. saveRecommendations: function(context, blueprintObject) {
  527. var oldValueKey = context.get('controller.wizardController.name') === 'installerController' ? 'initialValue' : 'savedValue';
  528. var config = this.get('configWidgetContext.config');
  529. context.get('controller').loadRecommendationsSuccess({
  530. resources: [
  531. {
  532. recommendations: {
  533. blueprint: {
  534. configurations: blueprintObject
  535. }
  536. }
  537. }
  538. ]
  539. }, null, {
  540. dataToSend: {
  541. changed_configurations: [{
  542. type: App.config.getConfigTagFromFileName(config.get('fileName')),
  543. name: config.get('name'),
  544. old_value: config.get(oldValueKey)
  545. }]
  546. }
  547. });
  548. },
  549. /**
  550. *
  551. * @param dependencies
  552. * @param serviceConfigs
  553. * @returns {{}}
  554. */
  555. getDependenciesForeignKeys: function(dependencies, serviceConfigs) {
  556. var foreignKeys = {};
  557. if (dependencies.foreignKeys) {
  558. dependencies.foreignKeys.forEach(function (dependency) {
  559. var matchingProperty = serviceConfigs.find(function (property) {
  560. return property.get('filename') === App.config.getOriginalFileName(dependency.fileName) && property.get('name') === dependency.propertyName;
  561. });
  562. if (matchingProperty) {
  563. foreignKeys[dependency.key] = matchingProperty.get('value');
  564. }
  565. });
  566. }
  567. return foreignKeys;
  568. },
  569. /**
  570. *
  571. * @param dependencies
  572. * @param context
  573. * @returns {Array}
  574. */
  575. getMasterComponents: function(dependencies, context) {
  576. var masterComponents = [];
  577. if (this.get('content.controllerName')) {
  578. var savedMasterComponents = context.get('controller.content.masterComponentHosts').filter(function (componentObject) {
  579. return dependencies.initializer.componentNames.contains(componentObject.component);
  580. });
  581. masterComponents = savedMasterComponents.map(function (componentObject) {
  582. var masterComponent = Em.getProperties(componentObject, ['component', 'hostName']);
  583. masterComponent.isInstalled = true;
  584. return masterComponent;
  585. });
  586. } else {
  587. var hostsMap = blueprintUtils.getComponentForHosts();
  588. Em.keys(hostsMap).forEach(function (hostName) {
  589. hostsMap[hostName].forEach(function (componentName) {
  590. if (dependencies.initializer.componentNames.contains(componentName)) {
  591. masterComponents.push({
  592. component: componentName,
  593. hostName: hostName,
  594. isInstalled: true
  595. });
  596. }
  597. });
  598. });
  599. }
  600. return masterComponents;
  601. },
  602. getHosts: function () {
  603. var result,
  604. parentController = this.get('content.controllerName');
  605. if (parentController) {
  606. result = this._super();
  607. } else {
  608. result = this.get('hosts').mapProperty('host_name');
  609. }
  610. return result;
  611. },
  612. clearStepOnExit: Em.K
  613. });