config_test.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  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/configs_collection');
  21. require('utils/config');
  22. require('models/service/hdfs');
  23. var setups = require('test/init_model_test');
  24. function dummyCopy(val) {
  25. return JSON.parse(JSON.stringify(val));
  26. }
  27. describe('App.config', function () {
  28. describe('#fileConfigsIntoTextarea', function () {
  29. var filename = 'capacity-scheduler.xml';
  30. var configs = [
  31. {
  32. name: 'config1',
  33. value: 'value1',
  34. recommendedValue: 'value1',
  35. filename: 'capacity-scheduler.xml'
  36. },
  37. {
  38. name: 'config2',
  39. value: 'value2',
  40. recommendedValue: 'value2',
  41. filename: 'capacity-scheduler.xml'
  42. }
  43. ];
  44. var c3 = {
  45. name: 'config3',
  46. value: 'value3',
  47. recommendedValue: 'value3',
  48. filename: 'capacity-scheduler.xml'
  49. };
  50. describe('two configs into textarea', function () {
  51. var result;
  52. beforeEach(function () {
  53. result = App.config.fileConfigsIntoTextarea(configs, filename);
  54. });
  55. it('One config is returned', function () {
  56. expect(result.length).to.equal(1);
  57. });
  58. it('value is valid', function () {
  59. expect(result[0].value).to.equal('config1=value1\nconfig2=value2\n');
  60. });
  61. it('recommendedValue is valid', function () {
  62. expect(result[0].recommendedValue).to.equal('config1=value1\nconfig2=value2\n');
  63. });
  64. });
  65. describe('three config into textarea', function () {
  66. var newConfigs = dummyCopy(configs);
  67. newConfigs.push(dummyCopy(c3));
  68. var result;
  69. beforeEach(function () {
  70. result = App.config.fileConfigsIntoTextarea(newConfigs, filename);
  71. });
  72. it('One config is returned', function () {
  73. expect(result.length).to.equal(1);
  74. });
  75. it('valid is valid', function () {
  76. expect(result[0].value).to.equal('config1=value1\nconfig2=value2\nconfig3=value3\n');
  77. });
  78. it('recommendedValue is valid', function () {
  79. expect(result[0].recommendedValue).to.equal('config1=value1\nconfig2=value2\nconfig3=value3\n');
  80. });
  81. });
  82. describe('one of three configs has different filename', function () {
  83. var newConfigs = dummyCopy(configs);
  84. newConfigs.push(dummyCopy(c3));
  85. newConfigs[1].filename = 'another filename';
  86. var result;
  87. beforeEach(function () {
  88. result = App.config.fileConfigsIntoTextarea(newConfigs, filename);
  89. });
  90. it('Two configs are returned', function () {
  91. //result contains two configs: one with different filename and one textarea config
  92. expect(result.length).to.equal(2);
  93. });
  94. it('Value is valid', function () {
  95. expect(result[1].value).to.equal('config1=value1\nconfig3=value3\n');
  96. });
  97. it('RecommendedValue is valid', function () {
  98. expect(result[1].recommendedValue).to.equal('config1=value1\nconfig3=value3\n');
  99. });
  100. });
  101. describe('none configs into empty textarea', function () {
  102. var result;
  103. beforeEach(function () {
  104. result = App.config.fileConfigsIntoTextarea([], 'capacity-scheduler.xml');
  105. });
  106. it('One config is returned', function () {
  107. expect(result.length).to.equal(1);
  108. });
  109. it('value is empty', function () {
  110. expect(result[0].value).to.equal('');
  111. });
  112. it('recommendedValue is none', function () {
  113. expect(Em.isNone(result[0].recommendedValue)).to.be.true;
  114. });
  115. it('savedValue is none', function () {
  116. expect(Em.isNone(result[0].savedValue)).to.be.true;
  117. });
  118. });
  119. describe("filename has configs that shouldn't be included in textarea", function () {
  120. var newConfigs = dummyCopy(configs);
  121. newConfigs.push(dummyCopy(c3));
  122. var result;
  123. beforeEach(function () {
  124. result = App.config.fileConfigsIntoTextarea(newConfigs, 'capacity-scheduler.xml', [c3]);
  125. });
  126. it('Two configs are returned', function () {
  127. expect(result.length).to.equal(2);
  128. });
  129. it('value is correct', function () {
  130. expect(result[1].value).to.equal('config1=value1\nconfig2=value2\n');
  131. });
  132. it('recommendedValue is correct', function () {
  133. expect(result[1].recommendedValue).to.equal('config1=value1\nconfig2=value2\n');
  134. });
  135. it('skipped config is correct', function () {
  136. expect(newConfigs.findProperty('name', 'config3')).to.eql(c3);
  137. });
  138. });
  139. });
  140. describe('#textareaIntoFileConfigs', function () {
  141. var filename = 'capacity-scheduler.xml';
  142. var testData = [
  143. {
  144. configs: [Em.Object.create({
  145. "name": "capacity-scheduler",
  146. "value": "config1=value1",
  147. "filename": "capacity-scheduler.xml",
  148. "isRequiredByAgent": true
  149. })]
  150. },
  151. {
  152. configs: [Em.Object.create({
  153. "name": "capacity-scheduler",
  154. "value": "config1=value1\nconfig2=value2\n",
  155. "filename": "capacity-scheduler.xml",
  156. "isRequiredByAgent": false
  157. })]
  158. },
  159. {
  160. configs: [Em.Object.create({
  161. "name": "capacity-scheduler",
  162. "value": "config1=value1,value2\n",
  163. "filename": "capacity-scheduler.xml",
  164. "isRequiredByAgent": true
  165. })]
  166. },
  167. {
  168. configs: [Em.Object.create({
  169. "name": "capacity-scheduler",
  170. "value": "config1=value1 config2=value2\n",
  171. "filename": "capacity-scheduler.xml",
  172. "isRequiredByAgent": false
  173. })]
  174. }
  175. ];
  176. describe('config1=value1 to one config', function () {
  177. var result;
  178. beforeEach(function () {
  179. result = App.config.textareaIntoFileConfigs(testData[0].configs, filename);
  180. });
  181. it('One config is returned', function () {
  182. expect(result.length).to.equal(1);
  183. });
  184. it('value is correct', function () {
  185. expect(result[0].value).to.equal('value1');
  186. });
  187. it('name is correct', function () {
  188. expect(result[0].name).to.equal('config1');
  189. });
  190. it('isRequiredByAgent is true', function () {
  191. expect(result[0].isRequiredByAgent).to.be.true;
  192. });
  193. });
  194. describe('config1=value1\\nconfig2=value2\\n to two configs', function () {
  195. var result;
  196. beforeEach(function () {
  197. result = App.config.textareaIntoFileConfigs(testData[1].configs, filename);
  198. });
  199. it('Two configs are returned', function (){
  200. expect(result.length).to.equal(2);
  201. });
  202. it('1st value is valid', function (){
  203. expect(result[0].value).to.equal('value1');
  204. });
  205. it('1st name is valid', function (){
  206. expect(result[0].name).to.equal('config1');
  207. });
  208. it('2nd value is valid', function (){
  209. expect(result[1].value).to.equal('value2');
  210. });
  211. it('2nd name is valid', function (){
  212. expect(result[1].name).to.equal('config2');
  213. });
  214. it('1st isRequiredByAgent is false', function (){
  215. expect(result[0].isRequiredByAgent).to.be.false;
  216. });
  217. it('2nd isRequiredByAgent is false', function (){
  218. expect(result[1].isRequiredByAgent).to.be.false;
  219. });
  220. });
  221. describe('config1=value1,value2\n to one config', function () {
  222. var result;
  223. beforeEach(function () {
  224. result = App.config.textareaIntoFileConfigs(testData[2].configs, filename);
  225. });
  226. it('One config is returned', function () {
  227. expect(result.length).to.equal(1);
  228. });
  229. it('value is correct', function () {
  230. expect(result[0].value).to.equal('value1,value2');
  231. });
  232. it('name is correct', function () {
  233. expect(result[0].name).to.equal('config1');
  234. });
  235. it('isRequiredByAgent is true', function () {
  236. expect(result[0].isRequiredByAgent).to.be.true;
  237. });
  238. });
  239. describe('config1=value1 config2=value2 to two configs', function () {
  240. var result;
  241. beforeEach(function () {
  242. result = App.config.textareaIntoFileConfigs(testData[3].configs, filename);
  243. });
  244. it('One config is returned', function () {
  245. expect(result.length).to.equal(1);
  246. });
  247. it('isRequiredByAgent is false', function () {
  248. expect(result[0].isRequiredByAgent).to.be.false;
  249. });
  250. });
  251. });
  252. describe('#trimProperty',function() {
  253. var testMessage = 'displayType `{0}`, value `{1}`{3} should return `{2}`';
  254. var tests = [
  255. {
  256. config: {
  257. displayType: 'directory',
  258. value: ' /a /b /c'
  259. },
  260. e: '/a,/b,/c'
  261. },
  262. {
  263. config: {
  264. displayType: 'directories',
  265. value: ' /a /b '
  266. },
  267. e: '/a,/b'
  268. },
  269. {
  270. config: {
  271. displayType: 'directories',
  272. name: 'dfs.datanode.data.dir',
  273. value: ' [DISK]/a [SSD]/b '
  274. },
  275. e: '[DISK]/a,[SSD]/b'
  276. },
  277. {
  278. config: {
  279. displayType: 'directories',
  280. name: 'dfs.datanode.data.dir',
  281. value: '/a,/b, /c\n/d,\n/e /f'
  282. },
  283. e: '/a,/b,/c,/d,/e,/f'
  284. },
  285. {
  286. config: {
  287. displayType: 'host',
  288. value: ' localhost '
  289. },
  290. e: 'localhost'
  291. },
  292. {
  293. config: {
  294. displayType: 'password',
  295. value: ' passw ord '
  296. },
  297. e: ' passw ord '
  298. },
  299. {
  300. config: {
  301. displayType: 'string',
  302. value: ' value'
  303. },
  304. e: ' value'
  305. },
  306. {
  307. config: {
  308. displayType: 'string',
  309. value: ' value'
  310. },
  311. e: ' value'
  312. },
  313. {
  314. config: {
  315. displayType: 'string',
  316. value: 'http://localhost ',
  317. name: 'javax.jdo.option.ConnectionURL'
  318. },
  319. e: 'http://localhost'
  320. },
  321. {
  322. config: {
  323. displayType: 'string',
  324. value: 'http://localhost ',
  325. name: 'oozie.service.JPAService.jdbc.url'
  326. },
  327. e: 'http://localhost'
  328. },
  329. {
  330. config: {
  331. displayType: 'custom',
  332. value: ' custom value '
  333. },
  334. e: ' custom value'
  335. },
  336. {
  337. config: {
  338. displayType: 'componentHosts',
  339. value: ['host1.com', 'host2.com']
  340. },
  341. e: ['host1.com', 'host2.com']
  342. }
  343. ];
  344. tests.forEach(function(test) {
  345. it(testMessage.format(test.config.displayType, test.config.value, test.e, !!test.config.name ? ', name `' + test.config.name + '`' : ''), function() {
  346. expect(App.config.trimProperty(test.config)).to.eql(test.e);
  347. expect(App.config.trimProperty(Em.Object.create(test.config), true)).to.eql(test.e);
  348. });
  349. });
  350. });
  351. describe('#preDefinedConfigFile', function() {
  352. before(function() {
  353. setups.setupStackVersion(this, 'BIGTOP-0.8');
  354. });
  355. it('bigtop site properties should be ok.', function() {
  356. var bigtopSiteProperties = App.config.preDefinedConfigFile('BIGTOP', 'site_properties');
  357. expect(bigtopSiteProperties).to.be.ok;
  358. });
  359. it('a non-existing file should not be ok.', function () {
  360. var notExistingSiteProperty = App.config.preDefinedConfigFile('notExisting');
  361. expect(notExistingSiteProperty).to.not.be.ok;
  362. });
  363. after(function() {
  364. setups.restoreStackVersion(this);
  365. });
  366. });
  367. describe('#preDefinedSiteProperties-bigtop', function () {
  368. before(function() {
  369. setups.setupStackVersion(this, 'BIGTOP-0.8');
  370. });
  371. it('bigtop should use New PostgreSQL Database as its default hive metastore database', function () {
  372. App.StackService.createRecord({serviceName: 'HIVE'});
  373. expect(App.config.get('preDefinedSiteProperties').findProperty('recommendedValue', 'New PostgreSQL Database')).to.be.ok;
  374. });
  375. after(function() {
  376. setups.restoreStackVersion(this);
  377. });
  378. });
  379. describe('#generateConfigPropertiesByName', function() {
  380. var tests = [
  381. {
  382. names: ['property_1', 'property_2'],
  383. properties: undefined,
  384. e: {
  385. keys: ['name']
  386. },
  387. m: 'Should generate base property object without additional fields'
  388. },
  389. {
  390. names: ['property_1', 'property_2'],
  391. properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' },
  392. e: {
  393. keys: ['name', 'category', 'serviceName']
  394. },
  395. m: 'Should generate base property object without additional fields'
  396. }
  397. ];
  398. tests.forEach(function(test) {
  399. it(test.m, function() {
  400. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length);
  401. expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) {
  402. return Em.keys(property);
  403. }).reduce(function(p, c) {
  404. return p.concat(c);
  405. }).uniq()).to.eql(test.e.keys);
  406. });
  407. });
  408. });
  409. describe('#setPreDefinedServiceConfigs', function() {
  410. beforeEach(function() {
  411. sinon.stub(App.StackService, 'find', function() {
  412. return [
  413. Em.Object.create({
  414. id: 'HDFS',
  415. serviceName: 'HDFS',
  416. configTypes: {
  417. 'hadoop-env': {},
  418. 'hdfs-site': {}
  419. }
  420. }),
  421. Em.Object.create({
  422. id: 'OOZIE',
  423. serviceName: 'OOZIE',
  424. configTypes: {
  425. 'oozie-env': {},
  426. 'oozie-site': {}
  427. }
  428. })
  429. ];
  430. });
  431. App.config.setPreDefinedServiceConfigs(true);
  432. });
  433. afterEach(function() {
  434. App.StackService.find.restore();
  435. });
  436. it('should include service MISC', function() {
  437. expect(App.config.get('preDefinedServiceConfigs').findProperty('serviceName', 'MISC')).to.be.ok;
  438. });
  439. it('should include -env config types according to stack services', function() {
  440. var miscCategory = App.config.get('preDefinedServiceConfigs').findProperty('serviceName', 'MISC');
  441. expect(Em.keys(miscCategory.get('configTypes'))).to.eql(['cluster-env', 'hadoop-env', 'oozie-env']);
  442. });
  443. });
  444. describe('#isManagedMySQLForHiveAllowed', function () {
  445. var cases = [
  446. {
  447. osFamily: 'redhat5',
  448. expected: false
  449. },
  450. {
  451. osFamily: 'redhat6',
  452. expected: true
  453. },
  454. {
  455. osFamily: 'suse11',
  456. expected: false
  457. }
  458. ],
  459. title = 'should be {0} for {1}';
  460. cases.forEach(function (item) {
  461. it(title.format(item.expected, item.osFamily), function () {
  462. expect(App.config.isManagedMySQLForHiveAllowed(item.osFamily)).to.equal(item.expected);
  463. });
  464. });
  465. });
  466. describe('#shouldSupportFinal', function () {
  467. var cases = [
  468. {
  469. shouldSupportFinal: false,
  470. title: 'no service name specified'
  471. },
  472. {
  473. serviceName: 's0',
  474. shouldSupportFinal: false,
  475. title: 'no filename specified'
  476. },
  477. {
  478. serviceName: 'MISC',
  479. shouldSupportFinal: false,
  480. title: 'MISC'
  481. },
  482. {
  483. serviceName: 's0',
  484. filename: 's0-site',
  485. shouldSupportFinal: true,
  486. title: 'final attribute supported'
  487. },
  488. {
  489. serviceName: 's0',
  490. filename: 's0-env',
  491. shouldSupportFinal: false,
  492. title: 'final attribute not supported'
  493. },
  494. {
  495. serviceName: 'Cluster',
  496. filename: 'krb5-conf.xml',
  497. shouldSupportFinal: false,
  498. title: 'kerberos descriptor identities don\'t support final'
  499. }
  500. ];
  501. beforeEach(function () {
  502. sinon.stub(App.StackService, 'find').returns([
  503. {
  504. serviceName: 's0'
  505. }
  506. ]);
  507. sinon.stub(App.config, 'getConfigTypesInfoFromService').returns({
  508. supportsFinal: ['s0-site']
  509. });
  510. });
  511. afterEach(function () {
  512. App.StackService.find.restore();
  513. App.config.getConfigTypesInfoFromService.restore();
  514. });
  515. cases.forEach(function (item) {
  516. it(item.title, function () {
  517. expect(App.config.shouldSupportFinal(item.serviceName, item.filename)).to.equal(item.shouldSupportFinal);
  518. });
  519. });
  520. });
  521. describe('#shouldSupportAddingForbidden', function () {
  522. var cases = [
  523. {
  524. shouldSupportAddingForbidden: false,
  525. title: 'no service name specified'
  526. },
  527. {
  528. serviceName: 's0',
  529. shouldSupportAddingForbidden: false,
  530. title: 'no filename specified'
  531. },
  532. {
  533. serviceName: 'MISC',
  534. shouldSupportAddingForbidden: false,
  535. title: 'MISC'
  536. },
  537. {
  538. serviceName: 's0',
  539. filename: 's0-site',
  540. shouldSupportAddingForbidden: true,
  541. title: 'adding forbidden supported'
  542. },
  543. {
  544. serviceName: 's0',
  545. filename: 's0-properties',
  546. shouldSupportAddingForbidden: false,
  547. title: 'adding forbidden not supported'
  548. }
  549. ];
  550. beforeEach(function () {
  551. sinon.stub(App.StackService, 'find').returns([
  552. Em.Object.create({
  553. serviceName: 's0',
  554. configTypes: {
  555. 's0-size': {},
  556. 's0-properties': {}
  557. }
  558. })
  559. ]);
  560. sinon.stub(App.config, 'getConfigTypesInfoFromService').returns({
  561. supportsAddingForbidden: ['s0-site']
  562. });
  563. });
  564. afterEach(function () {
  565. App.StackService.find.restore();
  566. App.config.getConfigTypesInfoFromService.restore();
  567. });
  568. cases.forEach(function (item) {
  569. it(item.title, function () {
  570. expect(App.config.shouldSupportAddingForbidden(item.serviceName, item.filename)).to.equal(item.shouldSupportAddingForbidden);
  571. });
  572. });
  573. });
  574. describe('#removeRangerConfigs', function () {
  575. it('should remove ranger configs and categories', function () {
  576. var configs = [
  577. Em.Object.create({
  578. configs: [
  579. Em.Object.create({filename: 'filename'}),
  580. Em.Object.create({filename: 'ranger-filename'})
  581. ],
  582. configCategories: [
  583. Em.Object.create({name: 'ranger-name'}),
  584. Em.Object.create({name: 'name'}),
  585. Em.Object.create({name: 'also-ranger-name'})
  586. ]
  587. })
  588. ];
  589. App.config.removeRangerConfigs(configs);
  590. expect(configs).eql(
  591. [
  592. Em.Object.create({
  593. configs: [
  594. Em.Object.create({filename: 'filename'})
  595. ],
  596. configCategories: [
  597. Em.Object.create({name: 'name'})
  598. ]
  599. })
  600. ]
  601. );
  602. });
  603. });
  604. describe("#createOverride", function() {
  605. var template = {
  606. name: "p1",
  607. filename: "f1",
  608. value: "v1",
  609. recommendedValue: "rv1",
  610. savedValue: "sv1",
  611. isFinal: true,
  612. recommendedIsFinal: false,
  613. savedIsFinal: true
  614. };
  615. var configProperty = App.ServiceConfigProperty.create(template);
  616. var group = Em.Object.create({name: "group1"});
  617. Object.keys(template).forEach(function (key) {
  618. it(key, function () {
  619. var override = App.config.createOverride(configProperty, {}, group);
  620. expect(override.get(key)).to.equal(template[key]);
  621. });
  622. });
  623. describe('overrides some values that should be different for override', function() {
  624. var override;
  625. beforeEach(function () {
  626. override = App.config.createOverride(configProperty, {}, group);
  627. });
  628. it('isOriginalSCP is false', function () {
  629. expect(override.get('isOriginalSCP')).to.be.false;
  630. });
  631. it('overrides is null', function () {
  632. expect(override.get('overrides')).to.be.null;
  633. });
  634. it('group is valid', function () {
  635. expect(override.get('group')).to.eql(group);
  636. });
  637. it('parentSCP is valid', function () {
  638. expect(override.get('parentSCP')).to.eql(configProperty);
  639. });
  640. });
  641. var overriddenTemplate = {
  642. value: "v2",
  643. recommendedValue: "rv2",
  644. savedValue: "sv2",
  645. isFinal: true,
  646. recommendedIsFinal: false,
  647. savedIsFinal: true
  648. };
  649. Object.keys(overriddenTemplate).forEach(function (key) {
  650. it('overrides some specific values `' + key + '`', function () {
  651. var override = App.config.createOverride(configProperty, overriddenTemplate, group);
  652. expect(override.get(key)).to.equal(overriddenTemplate[key]);
  653. });
  654. });
  655. it('throws error due to undefined configGroup', function() {
  656. expect(App.config.createOverride.bind(App.config, configProperty, {}, null)).to.throw(Error, 'configGroup can\' be null');
  657. });
  658. it('throws error due to undefined originalSCP', function() {
  659. expect(App.config.createOverride.bind(App.config, null, {}, group)).to.throw(Error, 'serviceConfigProperty can\' be null');
  660. });
  661. describe('updates originalSCP object ', function() {
  662. var overridenTemplate2;
  663. var override;
  664. beforeEach(function () {
  665. configProperty.set('overrides', null);
  666. configProperty.set('overrideValues', []);
  667. configProperty.set('overrideIsFinalValues', []);
  668. overridenTemplate2 = {
  669. value: "v12",
  670. recommendedValue: "rv12",
  671. savedValue: "sv12",
  672. isFinal: true,
  673. recommendedIsFinal: false,
  674. savedIsFinal: false
  675. };
  676. override = App.config.createOverride(configProperty, overridenTemplate2, group);
  677. });
  678. it('overrides.0 is valid', function () {
  679. expect(configProperty.get('overrides')[0]).to.be.eql(override);
  680. });
  681. it('overrideValues is valid', function () {
  682. expect(configProperty.get('overrideValues')).to.be.eql([overridenTemplate2.value]);
  683. });
  684. it('overrideIsFinalValues is valid', function () {
  685. expect(configProperty.get('overrideIsFinalValues')).to.be.eql([overridenTemplate2.isFinal]);
  686. });
  687. });
  688. });
  689. describe('#getIsEditable', function() {
  690. [{
  691. isDefaultGroup: true,
  692. isReconfigurable: true,
  693. canEdit: true,
  694. res: true,
  695. m: "isEditable is true"
  696. },
  697. {
  698. isDefaultGroup: false,
  699. isReconfigurable: true,
  700. canEdit: true,
  701. res: false,
  702. m: "isEditable is false; config group is not default"
  703. },
  704. {
  705. isDefaultGroup: true,
  706. isReconfigurable: false,
  707. canEdit: true,
  708. res: false,
  709. m: "isEditable is true; config is not reconfigurable"
  710. },
  711. {
  712. isDefaultGroup: true,
  713. isReconfigurable: true,
  714. canEdit: false,
  715. res: false,
  716. m: "isEditable is true; edition restricted by controller state"
  717. }].forEach(function(t) {
  718. it(t.m, function() {
  719. var configProperty = Ember.Object.create({isReconfigurable: t.isReconfigurable});
  720. var configGroup = Ember.Object.create({isDefault: t.isDefaultGroup});
  721. var isEditable = App.config.getIsEditable(configProperty, configGroup, t.canEdit);
  722. expect(isEditable).to.equal(t.res);
  723. })
  724. });
  725. });
  726. describe('#getIsSecure', function() {
  727. var secureConfigs = App.config.get('secureConfigs');
  728. before(function() {
  729. App.config.set('secureConfigs', [{name: 'secureConfig'}]);
  730. });
  731. after(function() {
  732. App.config.set('secureConfigs', secureConfigs);
  733. });
  734. it('config is secure', function() {
  735. expect(App.config.getIsSecure('secureConfig')).to.equal(true);
  736. });
  737. it('config is not secure', function() {
  738. expect(App.config.getIsSecure('NotSecureConfig')).to.equal(false);
  739. });
  740. });
  741. describe('#getDefaultCategory', function() {
  742. it('returns custom category', function() {
  743. expect(App.config.getDefaultCategory(null, 'filename.xml')).to.equal('Custom filename');
  744. });
  745. it('returns advanced category', function() {
  746. expect(App.config.getDefaultCategory(Em.Object.create, 'filename.xml')).to.equal('Advanced filename');
  747. });
  748. });
  749. describe('#getDefaultDisplayType', function() {
  750. it('returns singleLine displayType', function() {
  751. expect(App.config.getDefaultDisplayType('v1')).to.equal('string');
  752. });
  753. it('returns multiLine displayType', function() {
  754. expect(App.config.getDefaultDisplayType('v1\nv2')).to.equal('multiLine');
  755. });
  756. });
  757. describe('#formatValue', function() {
  758. it('formatValue for componentHosts', function () {
  759. var serviceConfigProperty = Em.Object.create({'displayType': 'componentHosts', value: "['h1','h2']"});
  760. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.eql(['h1','h2']);
  761. });
  762. it('formatValue for int', function () {
  763. var serviceConfigProperty = Em.Object.create({'displayType': 'int', value: '4.0'});
  764. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.equal('4');
  765. });
  766. it('formatValue for int with m', function () {
  767. var serviceConfigProperty = Em.Object.create({'displayType': 'int', value: '4m'});
  768. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.equal('4');
  769. });
  770. it('formatValue for float', function () {
  771. var serviceConfigProperty = Em.Object.create({'displayType': 'float', value: '0.40'});
  772. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.equal('0.4');
  773. });
  774. it('formatValue for kdc_type', function () {
  775. var serviceConfigProperty = Em.Object.create({'name': 'kdc_type', value: 'mit-kdc'});
  776. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.equal(Em.I18n.t('admin.kerberos.wizard.step1.option.kdc'));
  777. });
  778. it('don\'t format value', function () {
  779. var serviceConfigProperty = Em.Object.create({'name': 'any', displayType: 'any', value: 'any'});
  780. expect(App.config.formatPropertyValue(serviceConfigProperty)).to.equal('any');
  781. });
  782. });
  783. describe('#getPropertyIfExists', function() {
  784. [
  785. {
  786. propertyName: 'someProperty',
  787. defaultValue: 'default',
  788. firstObject: { someProperty: '1' },
  789. secondObject: { someProperty: '2' },
  790. res: '1',
  791. m: 'use value from first object'
  792. },
  793. {
  794. propertyName: 'someProperty',
  795. defaultValue: 'default',
  796. firstObject: { someOtherProperty: '1' },
  797. secondObject: { someProperty: '2' },
  798. res: '2',
  799. m: 'use value from second object'
  800. },
  801. {
  802. propertyName: 'someProperty',
  803. defaultValue: 'default',
  804. firstObject: { someOtherProperty: '1' },
  805. secondObject: { someOtherProperty: '2' },
  806. res: 'default',
  807. m: 'use default value'
  808. },
  809. {
  810. propertyName: 'someProperty',
  811. defaultValue: 'default',
  812. res: 'default',
  813. m: 'use default value'
  814. },
  815. {
  816. propertyName: 'someProperty',
  817. defaultValue: true,
  818. firstObject: { someProperty: false },
  819. secondObject: { someProperty: true },
  820. res: false,
  821. m: 'use value from first object, check booleans'
  822. },
  823. {
  824. propertyName: 'someProperty',
  825. defaultValue: true,
  826. firstObject: { someProperty: 0 },
  827. secondObject: { someProperty: 1 },
  828. res: 0,
  829. m: 'use value from first object, check 0'
  830. },
  831. {
  832. propertyName: 'someProperty',
  833. defaultValue: true,
  834. firstObject: { someProperty: '' },
  835. secondObject: { someProperty: '1' },
  836. res: '',
  837. m: 'use value from first object, check empty string'
  838. }
  839. ].forEach(function (t) {
  840. it(t.m, function () {
  841. expect(App.config.getPropertyIfExists(t.propertyName, t.defaultValue, t.firstObject, t.secondObject)).to.equal(t.res);
  842. })
  843. });
  844. });
  845. describe('#createDefaultConfig', function() {
  846. before(function() {
  847. sinon.stub(App.config, 'getDefaultDisplayType', function() {
  848. return 'pDisplayType';
  849. });
  850. sinon.stub(App.config, 'getDefaultCategory', function() {
  851. return 'pCategory';
  852. });
  853. sinon.stub(App.config, 'getIsSecure', function() {
  854. return false;
  855. });
  856. sinon.stub(App.config, 'shouldSupportFinal', function() {
  857. return true;
  858. });
  859. });
  860. after(function() {
  861. App.config.getDefaultDisplayType.restore();
  862. App.config.getDefaultCategory.restore();
  863. App.config.getIsSecure.restore();
  864. App.config.shouldSupportFinal.restore();
  865. });
  866. var res = {
  867. /** core properties **/
  868. id: "pName__pFileName",
  869. name: 'pName',
  870. filename: 'pFileName.xml',
  871. value: '',
  872. savedValue: null,
  873. isFinal: false,
  874. savedIsFinal: null,
  875. /** UI and Stack properties **/
  876. recommendedValue: null,
  877. recommendedIsFinal: null,
  878. supportsFinal: true,
  879. supportsAddingForbidden: false,
  880. serviceName: 'pServiceName',
  881. displayName: 'pName',
  882. displayType: 'pDisplayType',
  883. description: '',
  884. category: 'pCategory',
  885. isSecureConfig: false,
  886. showLabel: true,
  887. isVisible: true,
  888. isUserProperty: false,
  889. isRequired: true,
  890. group: null,
  891. isRequiredByAgent: true,
  892. isReconfigurable: true,
  893. unit: null,
  894. hasInitialValue: false,
  895. isOverridable: true,
  896. index: Infinity,
  897. dependentConfigPattern: null,
  898. options: null,
  899. radioName: null,
  900. widgetType: null
  901. };
  902. it('create default config object', function () {
  903. expect(App.config.createDefaultConfig('pName', 'pServiceName', 'pFileName', true)).to.eql(res);
  904. });
  905. it('getDefaultDisplayType is called', function() {
  906. expect(App.config.getDefaultDisplayType.called).to.be.true;
  907. });
  908. it('getDefaultCategory is called with correct arguments', function() {
  909. expect(App.config.getDefaultCategory.calledWith(true, 'pFileName')).to.be.true;
  910. });
  911. it('getIsSecure is called with correct arguments', function() {
  912. expect(App.config.getIsSecure.calledWith('pName')).to.be.true;
  913. });
  914. it('shouldSupportFinal is called with correct arguments', function() {
  915. expect(App.config.shouldSupportFinal.calledWith('pServiceName', 'pFileName')).to.be.true;
  916. });
  917. });
  918. describe('#mergeStackConfigsWithUI', function() {
  919. beforeEach(function() {
  920. sinon.stub(App.config, 'getPropertyIfExists', function(key, value) {return 'res_' + value});
  921. });
  922. afterEach(function() {
  923. App.config.getPropertyIfExists.restore();
  924. });
  925. var template = {
  926. name: 'pName',
  927. filename: 'pFileName',
  928. value: 'pValue',
  929. savedValue: 'pValue',
  930. isFinal: true,
  931. savedIsFinal: true,
  932. serviceName: 'pServiceName',
  933. displayName: 'pDisplayName',
  934. displayType: 'pDisplayType',
  935. category: 'pCategory'
  936. };
  937. var result = {
  938. name: 'pName',
  939. filename: 'pFileName',
  940. value: 'pValue',
  941. savedValue: 'pValue',
  942. isFinal: true,
  943. savedIsFinal: true,
  944. serviceName: 'res_pServiceName',
  945. displayName: 'res_pDisplayName',
  946. displayType: 'res_pDisplayType',
  947. category: 'res_pCategory'
  948. };
  949. it('called generate property object', function () {
  950. expect(App.config.mergeStaticProperties(template, {}, {})).to.eql(result);
  951. });
  952. });
  953. describe('#updateHostsListValue', function() {
  954. var tests = [
  955. {
  956. siteConfigs: {
  957. 'hadoop.registry.zk.quorum': 'host1,host2'
  958. },
  959. propertyName: 'hadoop.registry.zk.quorum',
  960. hostsList: 'host1',
  961. e: 'host1'
  962. },
  963. {
  964. siteConfigs: {
  965. 'hadoop.registry.zk.quorum': 'host1:10,host2:10'
  966. },
  967. propertyName: 'hadoop.registry.zk.quorum',
  968. hostsList: 'host2:10,host1:10',
  969. e: 'host1:10,host2:10'
  970. },
  971. {
  972. siteConfigs: {
  973. 'hadoop.registry.zk.quorum': 'host1:10,host2:10,host3:10'
  974. },
  975. propertyName: 'hadoop.registry.zk.quorum',
  976. hostsList: 'host2:10,host1:10',
  977. e: 'host2:10,host1:10'
  978. },
  979. {
  980. siteConfigs: {
  981. 'hadoop.registry.zk.quorum': 'host1:10,host2:10,host3:10'
  982. },
  983. propertyName: 'hadoop.registry.zk.quorum',
  984. hostsList: 'host2:10,host1:10,host3:10,host4:11',
  985. e: 'host2:10,host1:10,host3:10,host4:11'
  986. },
  987. {
  988. siteConfigs: {
  989. 'hive.zookeeper.quorum': 'host1'
  990. },
  991. propertyName: 'some.new.property',
  992. hostsList: 'host2,host1:10',
  993. e: 'host2,host1:10'
  994. }
  995. ];
  996. tests.forEach(function(test) {
  997. it('ZK located on {0}, current prop value is "{1}" "{2}" value should be "{3}"'.format(test.hostsList, ''+test.siteConfigs[test.propertyName], test.propertyName, test.e), function() {
  998. var result = App.config.updateHostsListValue(test.siteConfigs, test.propertyName, test.hostsList);
  999. expect(result).to.be.eql(test.e);
  1000. expect(test.siteConfigs[test.propertyName]).to.be.eql(test.e);
  1001. });
  1002. });
  1003. });
  1004. describe('#createHostNameProperty', function() {
  1005. it('create host property', function() {
  1006. expect(App.config.createHostNameProperty('service1', 'component1', ['host1'], Em.Object.create({
  1007. isMultipleAllowed: false,
  1008. displayName: 'display name'
  1009. }))).to.eql({
  1010. "name": 'component1_host',
  1011. "displayName": 'display name host',
  1012. "value": ['host1'],
  1013. "recommendedValue": ['host1'],
  1014. "description": "The host that has been assigned to run display name",
  1015. "displayType": "componentHost",
  1016. "isOverridable": false,
  1017. "isRequiredByAgent": false,
  1018. "serviceName": 'service1',
  1019. "filename": "service1-site.xml",
  1020. "category": 'component1',
  1021. "index": 0
  1022. })
  1023. });
  1024. it('create hosts property', function() {
  1025. expect(App.config.createHostNameProperty('service1', 'component1', ['host1'], Em.Object.create({
  1026. isMultipleAllowed: true,
  1027. displayName: 'display name'
  1028. }))).to.eql({
  1029. "name": 'component1_hosts',
  1030. "displayName": 'display name host',
  1031. "value": ['host1'],
  1032. "recommendedValue": ['host1'],
  1033. "description": "The hosts that has been assigned to run display name",
  1034. "displayType": "componentHosts",
  1035. "isOverridable": false,
  1036. "isRequiredByAgent": false,
  1037. "serviceName": 'service1',
  1038. "filename": "service1-site.xml",
  1039. "category": 'component1',
  1040. "index": 0
  1041. })
  1042. });
  1043. });
  1044. describe("#restrictSecureProperties()", function() {
  1045. var testCases = [
  1046. {
  1047. input: {
  1048. isSecureConfig: true,
  1049. isKerberosEnabled: true,
  1050. isReconfigurable: false,
  1051. isOverridable: false
  1052. },
  1053. expected: {
  1054. isReconfigurable: false,
  1055. isOverridable: false
  1056. }
  1057. },
  1058. {
  1059. input: {
  1060. isSecureConfig: true,
  1061. isKerberosEnabled: true,
  1062. isReconfigurable: true,
  1063. isOverridable: true
  1064. },
  1065. expected: {
  1066. isReconfigurable: false,
  1067. isOverridable: false
  1068. }
  1069. },
  1070. {
  1071. input: {
  1072. isSecureConfig: true,
  1073. isKerberosEnabled: false,
  1074. isReconfigurable: true,
  1075. isOverridable: true
  1076. },
  1077. expected: {
  1078. isReconfigurable: true,
  1079. isOverridable: true
  1080. }
  1081. },
  1082. {
  1083. input: {
  1084. isSecureConfig: false,
  1085. isReconfigurable: false,
  1086. isOverridable: false
  1087. },
  1088. expected: {
  1089. isReconfigurable: false,
  1090. isOverridable: false
  1091. }
  1092. },
  1093. {
  1094. input: {
  1095. isSecureConfig: false,
  1096. isReconfigurable: true,
  1097. isOverridable: true
  1098. },
  1099. expected: {
  1100. isReconfigurable: true,
  1101. isOverridable: true
  1102. }
  1103. }
  1104. ];
  1105. testCases.forEach(function(test) {
  1106. it("isSecureConfig = " + test.input.isSecureConfig + "; isKerberosEnabled = " + test.input.isKerberosEnabled, function() {
  1107. var config = {
  1108. isSecureConfig: test.input.isSecureConfig,
  1109. isReconfigurable: test.input.isReconfigurable,
  1110. isOverridable: test.input.isOverridable
  1111. };
  1112. App.set('isKerberosEnabled', !!test.input.isKerberosEnabled);
  1113. App.config.restrictSecureProperties(config);
  1114. expect(config.isReconfigurable).to.equal(test.expected.isReconfigurable);
  1115. expect(config.isOverridable).to.equal(test.expected.isOverridable);
  1116. });
  1117. });
  1118. });
  1119. describe("#truncateGroupName()", function() {
  1120. it("name is empty", function() {
  1121. expect(App.config.truncateGroupName('')).to.be.empty;
  1122. });
  1123. it("name has less than max chars", function() {
  1124. expect(App.config.truncateGroupName('group1')).to.equal('group1');
  1125. });
  1126. it("name has more than max chars", function() {
  1127. expect(App.config.truncateGroupName('group_has_more_than_max_characters')).to.equal('group_has...haracters');
  1128. });
  1129. });
  1130. });