config_test.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  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. before(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. expect(this.storedConfigs.filterProperty('filename', 'capacity-scheduler.xml').findProperty('name','content').displayType).to.eql('multiLine');
  286. });
  287. });
  288. describe('#trimProperty',function() {
  289. var testMessage = 'displayType `{0}`, value `{1}`{3} should return `{2}`';
  290. var tests = [
  291. {
  292. config: {
  293. displayType: 'directory',
  294. value: ' /a /b /c'
  295. },
  296. e: '/a,/b,/c'
  297. },
  298. {
  299. config: {
  300. displayType: 'directories',
  301. value: ' /a /b '
  302. },
  303. e: '/a,/b'
  304. },
  305. {
  306. config: {
  307. displayType: 'datanodedirs',
  308. value: ' [DISK]/a [SSD]/b '
  309. },
  310. e: '[DISK]/a,[SSD]/b'
  311. },
  312. {
  313. config: {
  314. displayType: 'host',
  315. value: ' localhost '
  316. },
  317. e: 'localhost'
  318. },
  319. {
  320. config: {
  321. displayType: 'password',
  322. value: ' passw ord '
  323. },
  324. e: ' passw ord '
  325. },
  326. {
  327. config: {
  328. displayType: 'advanced',
  329. value: ' value'
  330. },
  331. e: ' value'
  332. },
  333. {
  334. config: {
  335. displayType: 'advanced',
  336. value: ' value'
  337. },
  338. e: ' value'
  339. },
  340. {
  341. config: {
  342. displayType: 'advanced',
  343. value: 'http://localhost ',
  344. name: 'javax.jdo.option.ConnectionURL'
  345. },
  346. e: 'http://localhost'
  347. },
  348. {
  349. config: {
  350. displayType: 'advanced',
  351. value: 'http://localhost ',
  352. name: 'oozie.service.JPAService.jdbc.url'
  353. },
  354. e: 'http://localhost'
  355. },
  356. {
  357. config: {
  358. displayType: 'custom',
  359. value: ' custom value '
  360. },
  361. e: ' custom value'
  362. },
  363. {
  364. config: {
  365. displayType: 'masterHosts',
  366. value: ['host1.com', 'host2.com']
  367. },
  368. e: ['host1.com', 'host2.com']
  369. }
  370. ];
  371. tests.forEach(function(test) {
  372. it(testMessage.format(test.config.displayType, test.config.value, test.e, !!test.config.name ? ', name `' + test.config.name + '`' : ''), function() {
  373. expect(App.config.trimProperty(test.config)).to.eql(test.e);
  374. expect(App.config.trimProperty(Em.Object.create(test.config), true)).to.eql(test.e);
  375. });
  376. });
  377. });
  378. describe('#OnNnHAHideSnn()', function() {
  379. it('`SNameNode` category present in `ServiceConfig`. It should be removed.', function() {
  380. App.store.load(App.HDFSService, {
  381. 'id': 'HDFS'
  382. });
  383. var ServiceConfig = Em.Object.create({
  384. configCategories: [ { name: 'SNameNode' } ]
  385. });
  386. expect(ServiceConfig.get('configCategories').findProperty('name','SNameNode')).to.ok;
  387. App.config.OnNnHAHideSnn(ServiceConfig);
  388. expect(ServiceConfig.get('configCategories').findProperty('name','SNameNode')).to.undefined;
  389. var record = App.HDFSService.find('HDFS');
  390. record.deleteRecord();
  391. record.get('stateManager').transitionTo('loading');
  392. });
  393. it('`SNameNode` category absent in `ServiceConfig`. Nothing to do.', function() {
  394. App.store.load(App.HDFSService, {
  395. 'id': 'HDFS'
  396. });
  397. var ServiceConfig = Em.Object.create({
  398. configCategories: [ { name: 'DataNode' } ]
  399. });
  400. App.config.OnNnHAHideSnn(ServiceConfig);
  401. expect(ServiceConfig.get('configCategories').findProperty('name','DataNode')).to.ok;
  402. expect(ServiceConfig.get('configCategories.length')).to.eql(1);
  403. });
  404. });
  405. describe('#preDefinedConfigFile', function() {
  406. before(function() {
  407. setups.setupStackVersion(this, 'BIGTOP-0.8');
  408. });
  409. it('bigtop site properties should be ok.', function() {
  410. var bigtopSiteProperties = App.config.preDefinedConfigFile('site_properties');
  411. expect(bigtopSiteProperties).to.be.ok;
  412. });
  413. it('a non-existing file should not be ok.', function () {
  414. var notExistingSiteProperty = App.config.preDefinedConfigFile('notExisting');
  415. expect(notExistingSiteProperty).to.not.be.ok;
  416. });
  417. after(function() {
  418. setups.restoreStackVersion(this);
  419. });
  420. });
  421. describe('#preDefinedSiteProperties-bigtop', function () {
  422. before(function() {
  423. setups.setupStackVersion(this, 'BIGTOP-0.8');
  424. });
  425. it('bigtop should use New PostgreSQL Database as its default hive metastore database', function () {
  426. expect(App.config.get('preDefinedSiteProperties').findProperty('defaultValue', 'New PostgreSQL Database')).to.be.ok;
  427. });
  428. after(function() {
  429. setups.restoreStackVersion(this);
  430. });
  431. });
  432. describe('#preDefinedSiteProperties-hdp2', function () {
  433. before(function() {
  434. setups.setupStackVersion(this, 'HDP-2.0');
  435. });
  436. it('HDP2 should use New MySQL Database as its default hive metastore database', function () {
  437. expect(App.config.get('preDefinedSiteProperties').findProperty('defaultValue', 'New MySQL Database')).to.be.ok;
  438. });
  439. after(function() {
  440. setups.restoreStackVersion(this);
  441. });
  442. });
  443. describe('#generateConfigPropertiesByName', function() {
  444. var tests = [
  445. {
  446. names: ['property_1', 'property_2'],
  447. properties: undefined,
  448. e: {
  449. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  450. },
  451. m: 'Should generate base property object without additional fields'
  452. },
  453. {
  454. names: ['property_1', 'property_2'],
  455. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  456. e: {
  457. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  458. },
  459. m: 'Should generate base property object without additional fields'
  460. }
  461. ];
  462. tests.forEach(function(test) {
  463. it(test.m, function() {
  464. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  465. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  466. return Em.keys(property);
  467. }).reduce(function(p, c) {
  468. return p.concat(c);
  469. }).uniq()).to.eql(test.e.keys);
  470. });
  471. });
  472. });
  473. describe('#generateConfigPropertiesByName', function() {
  474. var tests = [
  475. {
  476. names: ['property_1', 'property_2'],
  477. properties: undefined,
  478. e: {
  479. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  480. },
  481. m: 'Should generate base property object without additional fields'
  482. },
  483. {
  484. names: ['property_1', 'property_2'],
  485. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  486. e: {
  487. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  488. },
  489. m: 'Should generate base property object without additional fields'
  490. }
  491. ];
  492. tests.forEach(function(test) {
  493. it(test.m, function() {
  494. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  495. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  496. return Em.keys(property);
  497. }).reduce(function(p, c) {
  498. return p.concat(c);
  499. }).uniq()).to.eql(test.e.keys);
  500. });
  501. });
  502. });
  503. describe('#generateConfigPropertiesByName', function() {
  504. var tests = [
  505. {
  506. names: ['property_1', 'property_2'],
  507. properties: undefined,
  508. e: {
  509. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable']
  510. },
  511. m: 'Should generate base property object without additional fields'
  512. },
  513. {
  514. names: ['property_1', 'property_2'],
  515. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  516. e: {
  517. keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName']
  518. },
  519. m: 'Should generate base property object without additional fields'
  520. }
  521. ];
  522. tests.forEach(function(test) {
  523. it(test.m, function() {
  524. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  525. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  526. return Em.keys(property);
  527. }).reduce(function(p, c) {
  528. return p.concat(c);
  529. }).uniq()).to.eql(test.e.keys);
  530. });
  531. });
  532. });
  533. describe('#isManagedMySQLForHiveAllowed', function () {
  534. var cases = [
  535. {
  536. osType: 'redhat5',
  537. expected: false
  538. },
  539. {
  540. osType: 'redhat6',
  541. expected: true
  542. },
  543. {
  544. osType: 'sles11',
  545. expected: false
  546. }
  547. ],
  548. title = 'should be {0} for {1}';
  549. cases.forEach(function (item) {
  550. it(title.format(item.expected, item.osType), function () {
  551. expect(App.config.isManagedMySQLForHiveAllowed(item.osType)).to.equal(item.expected);
  552. });
  553. });
  554. });
  555. });