config_test.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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('config');
  20. require('utils/config');
  21. require('models/service/hdfs');
  22. var setups = require('test/init_model_test');
  23. var modelSetup = setups.configs;
  24. describe('App.config', function () {
  25. var loadServiceSpecificConfigs = function(context, serviceName) {
  26. context.configGroups = modelSetup.setupConfigGroupsObject(serviceName);
  27. context.advancedConfigs = modelSetup.setupAdvancedConfigsObject();
  28. context.tags = modelSetup.setupServiceConfigTagsObject(serviceName);
  29. context.result = App.config.mergePreDefinedWithLoaded(context.configGroups, context.advancedConfigs, context.tags, App.Service.find().findProperty('id', serviceName).get('serviceName'));
  30. };
  31. var loadAllServicesConfigs = function(context, serviceNames) {
  32. context.configGroups = modelSetup.setupConfigGroupsObject();
  33. }
  34. var loadServiceModelsData = function(serviceNames) {
  35. serviceNames.forEach(function(serviceName) {
  36. App.store.load(App.Service, {
  37. id: serviceName,
  38. service_name: serviceName
  39. });
  40. });
  41. };
  42. var setupContentForMergeWithStored = function(context) {
  43. loadServiceModelsData(context.installedServiceNames);
  44. loadAllServicesConfigs(context);
  45. setups.setupStackVersion(this, 'HDP-2.1');
  46. context.result = App.config.mergePreDefinedWithStored(context.storedConfigs, modelSetup.setupAdvancedConfigsObject(), context.installedServiceNames);
  47. };
  48. var removeServiceModelData = function(serviceIds) {
  49. serviceIds.forEach(function(serviceId) {
  50. var record = App.Service.find(serviceId);
  51. record.deleteRecord();
  52. record.get('stateManager').transitionTo('loading');
  53. });
  54. };
  55. describe('#handleSpecialProperties', function () {
  56. var config = {};
  57. it('value should be transformed to "1024" from "1024m"', function () {
  58. config = {
  59. displayType: 'int',
  60. value: '1024m',
  61. defaultValue: '1024m'
  62. };
  63. App.config.handleSpecialProperties(config);
  64. expect(config.value).to.equal('1024');
  65. expect(config.defaultValue).to.equal('1024');
  66. });
  67. it('value should be transformed to true from "true"', function () {
  68. config = {
  69. displayType: 'checkbox',
  70. value: 'true',
  71. defaultValue: 'true'
  72. };
  73. App.config.handleSpecialProperties(config);
  74. expect(config.value).to.equal(true);
  75. expect(config.defaultValue).to.equal(true);
  76. });
  77. it('value should be transformed to false from "false"', function () {
  78. config = {
  79. displayType: 'checkbox',
  80. value: 'false',
  81. defaultValue: 'false'
  82. };
  83. App.config.handleSpecialProperties(config);
  84. expect(config.value).to.equal(false);
  85. expect(config.defaultValue).to.equal(false);
  86. });
  87. });
  88. describe('#capacitySchedulerFilter', function() {
  89. var testMessage = 'filter should {0} detect `{1}` property';
  90. describe('Stack version >= 2.0', function() {
  91. before(function() {
  92. setups.setupStackVersion(this, 'HDP-2.1');
  93. });
  94. var tests = [
  95. {
  96. config: {
  97. name: 'yarn.scheduler.capacity.maximum-am-resource-percent'
  98. },
  99. e: false
  100. },
  101. {
  102. config: {
  103. name: 'yarn.scheduler.capacity.root.capacity'
  104. },
  105. e: false
  106. },
  107. {
  108. config: {
  109. name: 'yarn.scheduler.capacity.root.default.capacity'
  110. },
  111. e: true
  112. }
  113. ];
  114. tests.forEach(function(test){
  115. it(testMessage.format( !!test.e ? '' : 'not', test.config.name), function() {
  116. expect(App.config.get('capacitySchedulerFilter')(test.config)).to.eql(test.e);
  117. });
  118. });
  119. after(function() {
  120. setups.restoreStackVersion(this);
  121. })
  122. });
  123. describe('Stack version < 2.0', function() {
  124. before(function() {
  125. setups.setupStackVersion(this, 'HDP-1.3');
  126. });
  127. var tests = [
  128. {
  129. config: {
  130. name: 'mapred.capacity-scheduler.maximum-system-jobs'
  131. },
  132. e: false
  133. },
  134. {
  135. config: {
  136. name: 'yarn.scheduler.capacity.root.capacity'
  137. },
  138. e: false
  139. },
  140. {
  141. config: {
  142. name: 'mapred.capacity-scheduler.queue.default.capacity'
  143. },
  144. e: true
  145. },
  146. {
  147. config: {
  148. name: 'mapred.queue.default.acl-administer-jobs'
  149. },
  150. e: true
  151. }
  152. ];
  153. tests.forEach(function(test){
  154. it(testMessage.format( !!test.e ? '' : 'not', test.config.name), function() {
  155. expect(App.config.get('capacitySchedulerFilter')(test.config)).to.eql(test.e);
  156. });
  157. });
  158. after(function() {
  159. setups.restoreStackVersion(this);
  160. });
  161. });
  162. });
  163. describe('#fileConfigsIntoTextarea', function () {
  164. var filename = 'capacity-scheduler.xml';
  165. var configs = [
  166. {
  167. name: 'config1',
  168. value: 'value1',
  169. defaultValue: 'value1',
  170. filename: 'capacity-scheduler.xml'
  171. },
  172. {
  173. name: 'config2',
  174. value: 'value2',
  175. defaultValue: 'value2',
  176. filename: 'capacity-scheduler.xml'
  177. }
  178. ];
  179. it('two configs into textarea', function () {
  180. var result = App.config.fileConfigsIntoTextarea.call(App.config, configs, filename);
  181. expect(result.length).to.equal(1);
  182. expect(result[0].value).to.equal('config1=value1\nconfig2=value2\n');
  183. expect(result[0].defaultValue).to.equal('config1=value1\nconfig2=value2\n');
  184. });
  185. it('three config into textarea', function () {
  186. configs.push({
  187. name: 'config3',
  188. value: 'value3',
  189. defaultValue: 'value3',
  190. filename: 'capacity-scheduler.xml'
  191. });
  192. var result = App.config.fileConfigsIntoTextarea.call(App.config, configs, filename);
  193. expect(result.length).to.equal(1);
  194. expect(result[0].value).to.equal('config1=value1\nconfig2=value2\nconfig3=value3\n');
  195. expect(result[0].defaultValue).to.equal('config1=value1\nconfig2=value2\nconfig3=value3\n');
  196. });
  197. it('one of three configs has different filename', function () {
  198. configs[1].filename = 'another filename';
  199. var result = App.config.fileConfigsIntoTextarea.call(App.config, configs, filename);
  200. //result contains two configs: one with different filename and one textarea config
  201. expect(result.length).to.equal(2);
  202. expect(result[1].value).to.equal('config1=value1\nconfig3=value3\n');
  203. expect(result[1].defaultValue).to.equal('config1=value1\nconfig3=value3\n');
  204. });
  205. it('none configs into empty textarea', function () {
  206. filename = 'capacity-scheduler.xml';
  207. configs.clear();
  208. var result = App.config.fileConfigsIntoTextarea.call(App.config, configs, filename);
  209. expect(result.length).to.equal(1);
  210. expect(result[0].value).to.equal('');
  211. expect(result[0].defaultValue).to.equal('');
  212. });
  213. });
  214. describe('#textareaIntoFileConfigs', function () {
  215. var filename = 'capacity-scheduler.xml';
  216. var testData = [
  217. {
  218. configs: [Em.Object.create({
  219. "name": "capacity-scheduler",
  220. "value": "config1=value1",
  221. "filename": "capacity-scheduler.xml"
  222. })]
  223. },
  224. {
  225. configs: [Em.Object.create({
  226. "name": "capacity-scheduler",
  227. "value": "config1=value1\nconfig2=value2\n",
  228. "filename": "capacity-scheduler.xml"
  229. })]
  230. },
  231. {
  232. configs: [Em.Object.create({
  233. "name": "capacity-scheduler",
  234. "value": "config1=value1,value2\n",
  235. "filename": "capacity-scheduler.xml"
  236. })]
  237. },
  238. {
  239. configs: [Em.Object.create({
  240. "name": "capacity-scheduler",
  241. "value": "config1=value1 config2=value2\n",
  242. "filename": "capacity-scheduler.xml"
  243. })]
  244. }
  245. ];
  246. it('config1=value1 to one config', function () {
  247. var result = App.config.textareaIntoFileConfigs.call(App.config, testData[0].configs, filename);
  248. expect(result.length).to.equal(1);
  249. expect(result[0].value).to.equal('value1');
  250. expect(result[0].name).to.equal('config1');
  251. });
  252. it('config1=value1\\nconfig2=value2\\n to two configs', function () {
  253. var result = App.config.textareaIntoFileConfigs.call(App.config, testData[1].configs, filename);
  254. expect(result.length).to.equal(2);
  255. expect(result[0].value).to.equal('value1');
  256. expect(result[0].name).to.equal('config1');
  257. expect(result[1].value).to.equal('value2');
  258. expect(result[1].name).to.equal('config2');
  259. });
  260. it('config1=value1,value2\n to one config', function () {
  261. var result = App.config.textareaIntoFileConfigs.call(App.config, testData[2].configs, filename);
  262. expect(result.length).to.equal(1);
  263. expect(result[0].value).to.equal('value1,value2');
  264. expect(result[0].name).to.equal('config1');
  265. });
  266. it('config1=value1 config2=value2 to two configs', function () {
  267. var result = App.config.textareaIntoFileConfigs.call(App.config, testData[3].configs, filename);
  268. expect(result.length).to.equal(1);
  269. });
  270. });
  271. describe('#addAvancedConfigs()', function() {
  272. beforeEach(function() {
  273. this.storedConfigs = modelSetup.setupStoredConfigsObject();
  274. });
  275. it('`custom.zoo.cfg` absent in stored configs', function() {
  276. expect(this.storedConfigs.findProperty('name', 'custom.zoo.cfg')).to.be.undefined;
  277. });
  278. it('`custom.zoo.cfg.` from advanced configs should be added to stored configs', function() {
  279. App.config.addAdvancedConfigs(this.storedConfigs, modelSetup.setupAdvancedConfigsObject(), 'ZOOKEEPER');
  280. var property = this.storedConfigs.findProperty('name', 'custom.zoo.cfg');
  281. expect(property).to.be.ok;
  282. expect(property.category).to.eql('Advanced zoo.cfg');
  283. });
  284. it('`capacity-scheduler.xml` property with name `content` should have `displayType` `multiLine`', function() {
  285. App.config.addAdvancedConfigs(this.storedConfigs, modelSetup.setupAdvancedConfigsObject(), 'YARN');
  286. expect(this.storedConfigs.filterProperty('filename', 'capacity-scheduler.xml').findProperty('name','content').displayType).to.eql('multiLine');
  287. });
  288. it('storing different configs with the same name', function () {
  289. App.config.addAdvancedConfigs(this.storedConfigs, modelSetup.setupAdvancedConfigsObject(), 'HBASE');
  290. var properties = this.storedConfigs.filterProperty('name', 'hbase_log_dir');
  291. var hbaseProperty = properties.findProperty('filename', 'hbase-env.xml');
  292. var amsProperty = properties.findProperty('filename', 'ams-hbase-env.xml');
  293. expect(properties).to.have.length(2);
  294. expect(hbaseProperty.serviceName).to.equal('HBASE');
  295. expect(hbaseProperty.value).to.equal('/hadoop/hbase');
  296. expect(amsProperty.serviceName).to.equal('AMS');
  297. expect(amsProperty.value).to.equal('/hadoop/ams-hbase');
  298. });
  299. });
  300. describe('#trimProperty',function() {
  301. var testMessage = 'displayType `{0}`, value `{1}`{3} should return `{2}`';
  302. var tests = [
  303. {
  304. config: {
  305. displayType: 'directory',
  306. value: ' /a /b /c'
  307. },
  308. e: '/a,/b,/c'
  309. },
  310. {
  311. config: {
  312. displayType: 'directories',
  313. value: ' /a /b '
  314. },
  315. e: '/a,/b'
  316. },
  317. {
  318. config: {
  319. displayType: 'datanodedirs',
  320. value: ' [DISK]/a [SSD]/b '
  321. },
  322. e: '[DISK]/a,[SSD]/b'
  323. },
  324. {
  325. config: {
  326. displayType: 'host',
  327. value: ' localhost '
  328. },
  329. e: 'localhost'
  330. },
  331. {
  332. config: {
  333. displayType: 'password',
  334. value: ' passw ord '
  335. },
  336. e: ' passw ord '
  337. },
  338. {
  339. config: {
  340. displayType: 'advanced',
  341. value: ' value'
  342. },
  343. e: ' value'
  344. },
  345. {
  346. config: {
  347. displayType: 'advanced',
  348. value: ' value'
  349. },
  350. e: ' value'
  351. },
  352. {
  353. config: {
  354. displayType: 'advanced',
  355. value: 'http://localhost ',
  356. name: 'javax.jdo.option.ConnectionURL'
  357. },
  358. e: 'http://localhost'
  359. },
  360. {
  361. config: {
  362. displayType: 'advanced',
  363. value: 'http://localhost ',
  364. name: 'oozie.service.JPAService.jdbc.url'
  365. },
  366. e: 'http://localhost'
  367. },
  368. {
  369. config: {
  370. displayType: 'custom',
  371. value: ' custom value '
  372. },
  373. e: ' custom value'
  374. },
  375. {
  376. config: {
  377. displayType: 'masterHosts',
  378. value: ['host1.com', 'host2.com']
  379. },
  380. e: ['host1.com', 'host2.com']
  381. }
  382. ];
  383. tests.forEach(function(test) {
  384. it(testMessage.format(test.config.displayType, test.config.value, test.e, !!test.config.name ? ', name `' + test.config.name + '`' : ''), function() {
  385. expect(App.config.trimProperty(test.config)).to.eql(test.e);
  386. expect(App.config.trimProperty(Em.Object.create(test.config), true)).to.eql(test.e);
  387. });
  388. });
  389. });
  390. describe('#OnNnHAHideSnn()', function() {
  391. it('`SNameNode` category present in `ServiceConfig`. It should be removed.', function() {
  392. App.store.load(App.HDFSService, {
  393. 'id': 'HDFS'
  394. });
  395. var ServiceConfig = Em.Object.create({
  396. configCategories: [ { name: 'SNameNode' } ]
  397. });
  398. expect(ServiceConfig.get('configCategories').findProperty('name','SNameNode')).to.ok;
  399. App.config.OnNnHAHideSnn(ServiceConfig);
  400. expect(ServiceConfig.get('configCategories').findProperty('name','SNameNode')).to.undefined;
  401. var record = App.HDFSService.find('HDFS');
  402. record.deleteRecord();
  403. record.get('stateManager').transitionTo('loading');
  404. });
  405. it('`SNameNode` category absent in `ServiceConfig`. Nothing to do.', function() {
  406. App.store.load(App.HDFSService, {
  407. 'id': 'HDFS'
  408. });
  409. var ServiceConfig = Em.Object.create({
  410. configCategories: [ { name: 'DataNode' } ]
  411. });
  412. App.config.OnNnHAHideSnn(ServiceConfig);
  413. expect(ServiceConfig.get('configCategories').findProperty('name','DataNode')).to.ok;
  414. expect(ServiceConfig.get('configCategories.length')).to.eql(1);
  415. });
  416. });
  417. describe('#preDefinedConfigFile', function() {
  418. before(function() {
  419. setups.setupStackVersion(this, 'BIGTOP-0.8');
  420. });
  421. it('bigtop site properties should be ok.', function() {
  422. var bigtopSiteProperties = App.config.preDefinedConfigFile('site_properties');
  423. expect(bigtopSiteProperties).to.be.ok;
  424. });
  425. it('a non-existing file should not be ok.', function () {
  426. var notExistingSiteProperty = App.config.preDefinedConfigFile('notExisting');
  427. expect(notExistingSiteProperty).to.not.be.ok;
  428. });
  429. after(function() {
  430. setups.restoreStackVersion(this);
  431. });
  432. });
  433. describe('#preDefinedSiteProperties-bigtop', function () {
  434. before(function() {
  435. setups.setupStackVersion(this, 'BIGTOP-0.8');
  436. });
  437. it('bigtop should use New PostgreSQL Database as its default hive metastore database', function () {
  438. expect(App.config.get('preDefinedSiteProperties').findProperty('defaultValue', 'New PostgreSQL Database')).to.be.ok;
  439. });
  440. after(function() {
  441. setups.restoreStackVersion(this);
  442. });
  443. });
  444. describe('#preDefinedSiteProperties-hdp2', function () {
  445. before(function() {
  446. setups.setupStackVersion(this, 'HDP-2.0');
  447. });
  448. it('HDP2 should use New MySQL Database as its default hive metastore database', function () {
  449. expect(App.config.get('preDefinedSiteProperties').findProperty('defaultValue', 'New MySQL Database')).to.be.ok;
  450. });
  451. after(function() {
  452. setups.restoreStackVersion(this);
  453. });
  454. });
  455. describe('#generateConfigPropertiesByName', function() {
  456. var tests = [
  457. {
  458. names: ['property_1', 'property_2'],
  459. properties: undefined,
  460. e: {
  461. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  462. },
  463. m: 'Should generate base property object without additional fields'
  464. },
  465. {
  466. names: ['property_1', 'property_2'],
  467. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  468. e: {
  469. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  470. },
  471. m: 'Should generate base property object without additional fields'
  472. }
  473. ];
  474. tests.forEach(function(test) {
  475. it(test.m, function() {
  476. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  477. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  478. return Em.keys(property);
  479. }).reduce(function(p, c) {
  480. return p.concat(c);
  481. }).uniq()).to.eql(test.e.keys);
  482. });
  483. });
  484. });
  485. describe('#generateConfigPropertiesByName', function() {
  486. var tests = [
  487. {
  488. names: ['property_1', 'property_2'],
  489. properties: undefined,
  490. e: {
  491. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  492. },
  493. m: 'Should generate base property object without additional fields'
  494. },
  495. {
  496. names: ['property_1', 'property_2'],
  497. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  498. e: {
  499. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  500. },
  501. m: 'Should generate base property object without additional fields'
  502. }
  503. ];
  504. tests.forEach(function(test) {
  505. it(test.m, function() {
  506. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  507. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  508. return Em.keys(property);
  509. }).reduce(function(p, c) {
  510. return p.concat(c);
  511. }).uniq()).to.eql(test.e.keys);
  512. });
  513. });
  514. });
  515. describe('#generateConfigPropertiesByName', function() {
  516. var tests = [
  517. {
  518. names: ['property_1', 'property_2'],
  519. properties: undefined,
  520. e: {
  521. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  522. },
  523. m: 'Should generate base property object without additional fields'
  524. },
  525. {
  526. names: ['property_1', 'property_2'],
  527. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  528. e: {
  529. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  530. },
  531. m: 'Should generate base property object without additional fields'
  532. }
  533. ];
  534. tests.forEach(function(test) {
  535. it(test.m, function() {
  536. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  537. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  538. return Em.keys(property);
  539. }).reduce(function(p, c) {
  540. return p.concat(c);
  541. }).uniq()).to.eql(test.e.keys);
  542. });
  543. });
  544. });
  545. describe('#isManagedMySQLForHiveAllowed', function () {
  546. var cases = [
  547. {
  548. osType: 'redhat5',
  549. expected: false
  550. },
  551. {
  552. osType: 'redhat6',
  553. expected: true
  554. },
  555. {
  556. osType: 'suse11',
  557. expected: false
  558. }
  559. ],
  560. title = 'should be {0} for {1}';
  561. cases.forEach(function (item) {
  562. it(title.format(item.expected, item.osType), function () {
  563. expect(App.config.isManagedMySQLForHiveAllowed(item.osType)).to.equal(item.expected);
  564. });
  565. });
  566. });
  567. });