step4_controller.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  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 App = require('app');
  19. require('controllers/wizard/step7_controller');
  20. App.KerberosWizardStep4Controller = App.WizardStep7Controller.extend(App.AddSecurityConfigs, App.ToggleIsRequiredMixin, App.KDCCredentialsControllerMixin, {
  21. name: 'kerberosWizardStep4Controller',
  22. isWithinAddService: Em.computed.equal('wizardController.name', 'addServiceController'),
  23. // stores configurations loaded by ConfigurationsController.getConfigsByTags
  24. servicesConfigurations: null,
  25. clearStep: function() {
  26. this.set('isRecommendedLoaded', false);
  27. this.set('selectedService', null);
  28. this.set('stepConfigs', []);
  29. },
  30. loadStep: function() {
  31. var self, stored;
  32. if (this.get('wizardController.skipConfigureIdentitiesStep')) {
  33. App.router.send('next');
  34. return;
  35. }
  36. self = this;
  37. this.clearStep();
  38. stored = this.get('wizardController').loadCachedStepConfigValues(this) || [];
  39. this.getDescriptor().then(function (kerberosDescriptor) {
  40. var stepConfigs = self.setStepConfigs(self.createServicesStackDescriptorConfigs(kerberosDescriptor));
  41. self.set('stepConfigs', stepConfigs);
  42. // when configurations were stored no need to apply recommendations again
  43. if (App.get('supports.kerberosStackAdvisor') && !stored.length) {
  44. self.bootstrapRecommendationPayload(kerberosDescriptor).then(function(recommendations) {
  45. self.loadServerSideConfigsRecommendations(recommendations).done(function() {
  46. self.applyServiceConfigs(stepConfigs);
  47. });
  48. });
  49. } else {
  50. self.applyServiceConfigs(stepConfigs);
  51. }
  52. }, function() {
  53. self.set('isRecommendedLoaded', true);
  54. });
  55. },
  56. /**
  57. * Get descriptor configs from API endpoint.
  58. * On <b>Enable Kerberos</b> loads descriptor from cluster STACK resource.
  59. * On <b>Add Service Wizard</b> first check for cluster's artifacts descriptor and
  60. * save it presence status, then loads from cluster COMPOSITE resource.
  61. * Check for cluster/artifacts/kerberos_descriptor is necessary to determine updating or creation
  62. * kerberos descriptor.
  63. *
  64. * @returns {$.Deferred}
  65. */
  66. getDescriptor: function() {
  67. var self = this;
  68. var dfd = $.Deferred();
  69. var successCallback = function(data) {
  70. dfd.resolve(data);
  71. };
  72. var checkDescriptor = function() {
  73. if (self.get('isWithinAddService')) {
  74. return App.ajax.send({
  75. sender: self,
  76. name: 'admin.kerberize.cluster_descriptor_artifact'
  77. });
  78. }
  79. return $.Deferred().resolve().promise();
  80. };
  81. checkDescriptor().always(function(data, status) {
  82. self.storeClusterDescriptorStatus(status === 'success');
  83. self.loadClusterDescriptorConfigs(self.get('isWithinAddService') ? self.get('selectedServiceNames') : false).then(successCallback);
  84. });
  85. return dfd.promise();
  86. },
  87. /**
  88. * Create service config object for Kerberos service.
  89. *
  90. * @param {App.ServiceConfigProperty[]} configs
  91. * @returns {Em.Object}
  92. */
  93. createServiceConfig: function(configs) {
  94. // Identity configs related to user principal
  95. var clusterConfigs = configs.filterProperty('serviceName','Cluster');
  96. // storm user principal is not required for ambari operation
  97. var userConfigs = configs.filterProperty('identityType','user');
  98. var generalConfigs = clusterConfigs.concat(userConfigs).uniq('name');
  99. var advancedConfigs = configs.filter(function(element){
  100. return !generalConfigs.findProperty('name', element.get('name'));
  101. });
  102. var categoryForGeneralConfigs = [
  103. App.ServiceConfigCategory.create({ name: 'Global', displayName: 'Global'}),
  104. App.ServiceConfigCategory.create({ name: 'Ambari Principals', displayName: 'Ambari Principals'})
  105. ];
  106. var categoryForAdvancedConfigs = this.createCategoryForServices();
  107. return [
  108. App.ServiceConfig.create({
  109. displayName: 'General',
  110. name: 'GENERAL',
  111. serviceName: 'KERBEROS_GENERAL',
  112. configCategories: categoryForGeneralConfigs,
  113. configs: generalConfigs,
  114. configGroups: [],
  115. showConfig: true
  116. }),
  117. App.ServiceConfig.create({
  118. displayName: 'Advanced',
  119. name: 'ADVANCED',
  120. serviceName: 'KERBEROS_ADVANCED',
  121. configCategories: categoryForAdvancedConfigs,
  122. configs: advancedConfigs,
  123. configGroups: [],
  124. showConfig: true
  125. })
  126. ];
  127. },
  128. /**
  129. * creates categories for advanced secure configs
  130. * @returns {[App.ServiceConfigCategory]}
  131. */
  132. createCategoryForServices: function() {
  133. var services = [];
  134. if (this.get('wizardController.name') === 'addServiceController') {
  135. services = App.StackService.find().filter(function(item) {
  136. return item.get('isInstalled') || item.get('isSelected');
  137. });
  138. } else {
  139. services = App.Service.find();
  140. }
  141. return services.map(function(item) {
  142. return App.ServiceConfigCategory.create({ name: item.get('serviceName'), displayName: item.get('displayName'), collapsedByDefault: true});
  143. });
  144. },
  145. /**
  146. * Prepare step configs using stack descriptor properties.
  147. *
  148. * @param {App.ServiceConfigProperty[]} configs
  149. * @param {App.ServiceConfigProperty[]} stackConfigs converted kerberos descriptor
  150. */
  151. setStepConfigs: function(configs, stackConfigs) {
  152. var configProperties = this.prepareConfigProperties(configs),
  153. stackConfigProperties = stackConfigs ? this.prepareConfigProperties(stackConfigs) : [],
  154. alterProperties = ['value','initialValue', 'defaultValue'];
  155. if (this.get('wizardController.name') === 'addServiceController') {
  156. // config properties for installed services should be disabled on Add Service Wizard
  157. configProperties.forEach(function(item) {
  158. if (this.get('installedServiceNames').contains(item.get('serviceName')) || item.get('serviceName') == 'Cluster') {
  159. item.set('isEditable', false);
  160. } else if (stackConfigs) {
  161. var stackConfigProperty = stackConfigProperties.filterProperty('filename', item.get('filename')).findProperty('name', item.get('name'));
  162. if (stackConfigProperty) {
  163. alterProperties.forEach(function (alterProperty) {
  164. item.set(alterProperty, stackConfigProperty.get(alterProperty));
  165. });
  166. }
  167. }
  168. }, this);
  169. // Concat properties that are present in the stack's kerberos descriptor but not in the cluster kerberos descriptor
  170. stackConfigProperties.forEach(function(_stackConfigProperty){
  171. var isPropertyInClusterDescriptor = configProperties.filterProperty('filename', _stackConfigProperty.get('filename')).someProperty('name', _stackConfigProperty.get('name'));
  172. if (!isPropertyInClusterDescriptor) {
  173. if (this.get('installedServiceNames').contains(_stackConfigProperty.get('serviceName')) || _stackConfigProperty.get('serviceName') === 'Cluster') {
  174. _stackConfigProperty.set('isEditable', false);
  175. }
  176. configProperties.pushObject(_stackConfigProperty);
  177. }
  178. }, this);
  179. }
  180. configProperties = App.config.sortConfigs(configProperties);
  181. var stepConfigs = this.createServiceConfig(configProperties);
  182. this.set('selectedService', stepConfigs[0]);
  183. this.get('stepConfigs').pushObjects(stepConfigs);
  184. return stepConfigs;
  185. },
  186. /**
  187. * Filter configs by installed services for Kerberos Wizard or by installed + selected services
  188. * for Add Service Wizard.
  189. * Set property value observer.
  190. * Set realm property with value from previous configuration step.
  191. * Set appropriate category for all configs.
  192. * Hide KDC related credentials properties if kerberos was manually enabled.
  193. *
  194. * @param {App.ServiceConfigProperty[]} configs
  195. * @returns {App.ServiceConfigProperty[]}
  196. */
  197. prepareConfigProperties: function(configs) {
  198. var self = this;
  199. // stored configs from previous steps (Configure Kerberos or Customize Services for ASW)
  200. var storedServiceConfigs = this.get('wizardController').getDBProperty('serviceConfigProperties');
  201. var installedServiceNames = ['Cluster'].concat(App.Service.find().mapProperty('serviceName'));
  202. var configProperties = configs.slice(0);
  203. var siteProperties = App.configsCollection.getAll();
  204. var realmValue;
  205. // override stored values
  206. App.config.mergeStoredValue(configProperties, this.get('wizardController').loadCachedStepConfigValues(this));
  207. // show admin properties in add service wizard
  208. if (this.get('isWithinAddService')) {
  209. installedServiceNames = installedServiceNames.concat(this.get('selectedServiceNames'));
  210. }
  211. configProperties = configProperties.filter(function(item) {
  212. return installedServiceNames.contains(item.get('serviceName'));
  213. });
  214. if (this.get('wizardController.name') !== 'addServiceController') {
  215. realmValue = storedServiceConfigs.findProperty('name', 'realm').value;
  216. configProperties.findProperty('name', 'realm').set('value', realmValue);
  217. configProperties.findProperty('name', 'realm').set('savedValue', realmValue);
  218. configProperties.findProperty('name', 'realm').set('recommendedValue', realmValue);
  219. }
  220. configProperties.setEach('isSecureConfig', false);
  221. configProperties.forEach(function(property, item, allConfigs) {
  222. if (['spnego_keytab', 'spnego_principal'].contains(property.get('name'))) {
  223. property.addObserver('value', self, 'spnegoPropertiesObserver');
  224. }
  225. if (property.get('observesValueFrom') && allConfigs.someProperty('name', property.get('observesValueFrom'))) {
  226. var observedValue = Em.get(allConfigs.findProperty('name', property.get('observesValueFrom')), 'value');
  227. property.set('value', observedValue);
  228. property.set('recommendedValue', observedValue);
  229. property.set('isVisible', true);
  230. }
  231. if (property.get('serviceName') === 'Cluster') {
  232. property.set('category', 'Global');
  233. }
  234. else {
  235. property.set('category', property.get('serviceName'));
  236. }
  237. // All user identity except storm should be grouped under "Ambari Principals" category
  238. if (property.get('identityType') == 'user') property.set('category', 'Ambari Principals');
  239. var siteProperty = siteProperties.findProperty('name', property.get('name'));
  240. if (siteProperty) {
  241. if (siteProperty.category === property.get('category')) {
  242. property.set('displayName',siteProperty.displayName);
  243. if (siteProperty.index) {
  244. property.set('index', siteProperty.index);
  245. }
  246. }
  247. if (siteProperty.displayType) {
  248. property.set('displayType', siteProperty.displayType);
  249. }
  250. }
  251. this.tweakConfigProperty(property);
  252. },this);
  253. return configProperties;
  254. },
  255. /**
  256. * Function to override kerberos descriptor's property values
  257. */
  258. tweakConfigProperty: function(config) {
  259. var defaultHiveMsPort = "9083",
  260. hiveMSHosts,
  261. port,
  262. hiveMSHostNames,
  263. configValue;
  264. if (config.name === 'templeton.hive.properties') {
  265. hiveMSHosts = App.HostComponent.find().filterProperty('componentName', 'HIVE_METASTORE');
  266. if (hiveMSHosts.length > 1) {
  267. hiveMSHostNames = hiveMSHosts.mapProperty('hostName');
  268. port = config.value.match(/:[0-9]{2,4}/);
  269. port = port ? port[0].slice(1) : defaultHiveMsPort;
  270. for (var i = 0; i < hiveMSHostNames.length; i++) {
  271. hiveMSHostNames[i] = "thrift://" + hiveMSHostNames[i] + ":" + port;
  272. }
  273. configValue = config.value.replace(/thrift.+[0-9]{2,},/i, hiveMSHostNames.join('\\,') + ",");
  274. config.set('value', configValue);
  275. config.set('recommendedValue', configValue);
  276. }
  277. }
  278. },
  279. /**
  280. * Sync up values between inherited property and its reference.
  281. *
  282. * @param {App.ServiceConfigProperty} configProperty
  283. */
  284. spnegoPropertiesObserver: function(configProperty) {
  285. var stepConfig = this.get('stepConfigs').findProperty('name', 'ADVANCED');
  286. stepConfig.get('configs').forEach(function(config) {
  287. if (config.get('observesValueFrom') === configProperty.get('name')) {
  288. Em.run.once(this, function() {
  289. config.set('value', configProperty.get('value'));
  290. config.set('recommendedValue', configProperty.get('value'));
  291. });
  292. }
  293. }, this);
  294. },
  295. submit: function() {
  296. this.saveConfigurations();
  297. App.router.send('next');
  298. },
  299. saveConfigurations: function() {
  300. var kerberosDescriptor = this.get('kerberosDescriptor');
  301. var configs = [];
  302. this.get('stepConfigs').forEach(function(_stepConfig){
  303. configs = configs.concat(_stepConfig.get('configs'));
  304. });
  305. this.updateKerberosDescriptor(kerberosDescriptor, configs);
  306. App.get('router.kerberosWizardController').saveKerberosDescriptorConfigs(kerberosDescriptor);
  307. },
  308. /**
  309. * Add/update property in `properties` object for each config type with
  310. * associated kerberos descriptor config value.
  311. *
  312. * @private
  313. * @param {object[]} configurations
  314. * @param {App.ServiceConfigProperty[]} kerberosDescriptor
  315. * @returns {object[]}
  316. */
  317. mergeDescriptorToConfigurations: function(configurations, kerberosDescriptor) {
  318. return configurations.map(function(configType) {
  319. var properties = $.extend({}, configType.properties);
  320. var filteredDescriptor = kerberosDescriptor.filterProperty('filename', configType.type);
  321. if (filteredDescriptor.length) {
  322. filteredDescriptor.forEach(function(descriptorConfig) {
  323. var configName = Em.get(descriptorConfig, 'name');
  324. properties[configName] = Em.get(descriptorConfig, 'value');
  325. });
  326. }
  327. return {
  328. type: configType.type,
  329. version: configType.version,
  330. tag: configType.tag,
  331. properties: properties
  332. };
  333. });
  334. },
  335. loadServerSideConfigsRecommendations: function(recommendations) {
  336. return App.ajax.send({
  337. 'name': 'config.recommendations',
  338. 'sender': this,
  339. 'data': {
  340. stackVersionUrl: App.get('stackVersionURL'),
  341. dataToSend: {
  342. recommend: 'configurations',
  343. hosts: this.get('hostNames'),
  344. services: this.get('serviceNames'),
  345. recommendations: recommendations
  346. }
  347. },
  348. 'success': 'loadRecommendationsSuccess',
  349. 'error': 'loadRecommendationsError'
  350. });
  351. },
  352. applyServiceConfigs: function(stepConfigs) {
  353. this.set('isRecommendedLoaded', true);
  354. this.set('selectedService', stepConfigs[0]);
  355. },
  356. /**
  357. * Callback executed when all configs specified by tags are loaded.
  358. * Here we handle configurations for instlled services and Kerberos.
  359. * Gather needed info for recommendation request such as configurations object.
  360. *
  361. * @override
  362. */
  363. getConfigTagsSuccess: function(data) {
  364. // here we get all installed services including KERBEROS
  365. var serviceNames = App.Service.find().mapProperty('serviceName').concat(['KERBEROS']).uniq();
  366. // collect all config types for selected services
  367. var installedServiceSites = Array.prototype.concat.apply([], App.config.get('preDefinedServiceConfigs').filter(function(serviceConfig) {
  368. return serviceNames.contains(Em.get(serviceConfig, 'serviceName'));
  369. }).map(function (service) {
  370. // when service have no configs return <code>null</code> instead return config types
  371. if (!service.get('configTypes')) return null;
  372. return Object.keys(service.get('configTypes'));
  373. }, this).compact()).uniq(); // cleanup <code>null</code>
  374. // take all configs for selected services by config types recieved from API response
  375. var serviceConfigTags = Em.keys(data.Clusters.desired_configs).reduce(function(tags, site) {
  376. if (data.Clusters.desired_configs.hasOwnProperty(site)) {
  377. // push cluster-env.xml also since it not associated with any service but need to further processing
  378. if (installedServiceSites.contains(site) || site === 'cluster-env') {
  379. tags.push({
  380. siteName: site,
  381. tagName: data.Clusters.desired_configs[site].tag,
  382. newTagName: null
  383. });
  384. }
  385. }
  386. return tags;
  387. }, []);
  388. // store configurations
  389. this.set('serviceConfigTags', serviceConfigTags);
  390. this.set('isAppliedConfigLoaded', true);
  391. },
  392. /**
  393. * Prepare all necessary data for recommendations payload.
  394. *
  395. * #mutates initialConfigValues
  396. * @returns {$.Deferred.promise()}
  397. */
  398. bootstrapRecommendationPayload: function(kerberosDescriptor) {
  399. var dfd = $.Deferred();
  400. var self = this;
  401. this.getServicesConfigurations().then(function(configurations) {
  402. var recommendations = self.getBlueprintPayloadObject(configurations, kerberosDescriptor);
  403. self.set('servicesConfigurations', configurations);
  404. self.set('initialConfigValues', recommendations.blueprint.configurations);
  405. dfd.resolve(recommendations);
  406. });
  407. return dfd.promise();
  408. },
  409. getServicesConfigurations: function() {
  410. var dfd = $.Deferred();
  411. var self = this;
  412. var configs, servicesConfigurations;
  413. if (this.get('isWithinAddService')) {
  414. configs = this.get('wizardController').getDBProperty('serviceConfigProperties');
  415. servicesConfigurations = configs.reduce(function(configTags, property) {
  416. var fileName = App.config.getConfigTagFromFileName(property.filename),
  417. configType;
  418. if (!configTags.someProperty('type', fileName)) {
  419. configTags.push({
  420. type: fileName,
  421. properties: {}
  422. });
  423. }
  424. configType = configTags.findProperty('type', fileName);
  425. configType.properties[property.name] = property.value;
  426. return configTags;
  427. }, []);
  428. dfd.resolve(servicesConfigurations);
  429. } else {
  430. this.getConfigTags().then(function() {
  431. App.router.get('configurationController').getConfigsByTags(self.get('serviceConfigTags')).done(function (configurations) {
  432. dfd.resolve(configurations);
  433. });
  434. });
  435. }
  436. return dfd.promise();
  437. },
  438. /**
  439. * Returns payload for recommendations request.
  440. * Takes services' configurations and merge them with kerberos descriptor properties.
  441. *
  442. * @param {object[]} configurations services' configurations fetched from API
  443. * @param {App.ServiceConfigProperty[]} kerberosDescriptor descriptor configs
  444. * @returns {object} payload for recommendations request
  445. */
  446. getBlueprintPayloadObject: function(configurations, kerberosDescriptor) {
  447. var recommendations = this.get('hostGroups');
  448. var mergedConfigurations = this.mergeDescriptorToConfigurations(configurations, this.createServicesStackDescriptorConfigs(kerberosDescriptor));
  449. recommendations.blueprint.configurations = mergedConfigurations.reduce(function(p, c) {
  450. p[c.type] = {};
  451. p[c.type].properties = c.properties;
  452. return p;
  453. }, {});
  454. return recommendations;
  455. },
  456. /**
  457. * @override
  458. */
  459. _saveRecommendedValues: function(data) {
  460. var recommendedConfigurations = Em.getWithDefault(data, 'resources.0.recommendations.blueprint.configurations', {});
  461. var allConfigs = Array.prototype.concat.apply([], this.get('stepConfigs').mapProperty('configs'));
  462. var self = this;
  463. // iterate by each config file name e.g. hdfs-site
  464. var groupedProperties = this.groupRecommendationProperties(recommendedConfigurations, this.get('servicesConfigurations'), allConfigs);
  465. var newProperties = [];
  466. Em.keys(groupedProperties.add).forEach(function(fileName) {
  467. var serviceName = self.getServiceByFilename(fileName);
  468. Em.keys(groupedProperties.add[fileName]).forEach(function(propertyName) {
  469. var property = self._createNewProperty(propertyName, fileName, serviceName, groupedProperties.add[fileName][propertyName]);
  470. property.set('category', serviceName);
  471. property.set('isOverridable', false);
  472. property.set('supportsFinal', false);
  473. property.set('isUserProperty', false);
  474. property.set('filename', fileName);
  475. newProperties.push(property);
  476. });
  477. });
  478. Array.prototype.push.apply(self.getServicesConfigObject().get('configs'), newProperties);
  479. Em.keys(groupedProperties.update).forEach(function(fileName) {
  480. Em.keys(groupedProperties.update[fileName]).forEach(function(propertyName) {
  481. var configProperty = allConfigs.filterProperty('filename', fileName).findProperty('name', propertyName);
  482. if (configProperty) {
  483. self._updateConfigByRecommendation(configProperty, groupedProperties.update[fileName][propertyName], true, false);
  484. }
  485. });
  486. });
  487. Em.keys(groupedProperties.delete).forEach(function(fileName) {
  488. Em.keys(groupedProperties.delete[fileName]).forEach(function(propertyName) {
  489. var servicesConfigs = self.getServicesConfigObject().get('configs');
  490. servicesConfigs.removeObject(servicesConfigs.filterProperty('filename', fileName).findProperty('name', propertyName));
  491. });
  492. });
  493. },
  494. /**
  495. * Returns category where services' configuration located.
  496. *
  497. * @returns {App.ServiceConfig}
  498. */
  499. getServicesConfigObject: function() {
  500. return this.get('stepConfigs').findProperty('name', 'ADVANCED');
  501. },
  502. /**
  503. * Returns map with appropriate action and properties to process with.
  504. * Key is an action e.g. `add`, `update`, `delete` and value is an object `fileName` -> `propertyName`: `propertyValue`.
  505. *
  506. * @param {object} recommendedConfigurations
  507. * @param {object[]} servicesConfigurations services' configurations fetched from API
  508. * @param {App.ServiceConfigProperty[]} allConfigs all current configurations stored in controller, basically kerberos descriptor
  509. * @returns {object}
  510. */
  511. groupRecommendationProperties: function(recommendedConfigurations, servicesConfigurations, allConfigs) {
  512. var resultMap = {
  513. update: {},
  514. add: {},
  515. delete: {}
  516. };
  517. /**
  518. * Adds property to associated group `add`,`delete`,`update`.
  519. *
  520. * @param {object} propertyMap <code>resultMap</code> object
  521. * @param {string} name property name
  522. * @param {string} propertyValue property value
  523. * @param {string} fileName property file name
  524. * @return {object} <code>resultMap</code>
  525. * @param {string} group, `add`,`delete`,`update`
  526. */
  527. var addProperty = function(propertyMap, name, propertyValue, fileName, group) {
  528. var ret = $.extend(true, {}, propertyMap);
  529. if (ret.hasOwnProperty(group)) {
  530. if (!ret[group].hasOwnProperty(fileName)) {
  531. ret[group][fileName] = {};
  532. }
  533. ret[group][fileName][name] = propertyValue;
  534. }
  535. return ret;
  536. };
  537. return Em.keys(recommendedConfigurations || {}).reduce(function(acc, fileName) {
  538. var propertyMap = acc;
  539. var recommendedProperties = Em.getWithDefault(recommendedConfigurations, fileName + '.properties', {});
  540. var recommendedAttributes = Em.getWithDefault(recommendedConfigurations, fileName + '.property_attributes', {});
  541. // check for properties that should be delted
  542. Em.keys(recommendedAttributes).forEach(function(propertyName) {
  543. var attribute = recommendedAttributes[propertyName];
  544. // delete properties which are present in kerberos descriptor
  545. if (attribute.hasOwnProperty('delete') && allConfigs.filterProperty('filename', fileName).someProperty('name', propertyName)) {
  546. propertyMap = addProperty(propertyMap, propertyName, '', fileName, 'delete');
  547. }
  548. });
  549. return Em.keys(recommendedProperties).reduce(function(a, propertyName) {
  550. var propertyValue = recommendedProperties[propertyName];
  551. // check if property exist in saved configurations on server
  552. var isExist = Em.getWithDefault(servicesConfigurations.findProperty('type', fileName) || {}, 'properties', {}).hasOwnProperty(propertyName);
  553. if (!isExist) {
  554. return addProperty(a, propertyName, propertyValue, fileName, 'add');
  555. }
  556. // when property exist check that it present in current step configs (kerberos descriptor)
  557. // and add it as property to `update`
  558. if (allConfigs.filterProperty('filename', fileName).someProperty('name', propertyName)) {
  559. return addProperty(a, propertyName, propertyValue, fileName, 'update');
  560. }
  561. return a;
  562. }, propertyMap);
  563. }, resultMap);
  564. },
  565. /**
  566. *
  567. * @method getServiceByFilename
  568. * @param {string}fileName
  569. * @returns {string}
  570. */
  571. getServiceByFilename: function(fileName) {
  572. // core-site properties goes to HDFS
  573. if (fileName === 'core-site' && App.Service.find().someProperty('serviceName', 'HDFS')) {
  574. return 'HDFS';
  575. }
  576. var associatedService = App.StackService.find().filter(function(service) {
  577. return Em.keys(service.get('configTypes')).contains(fileName);
  578. })[0];
  579. return associatedService ? associatedService.get('serviceName') : '';
  580. }
  581. });