step5_test.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  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/step5_controller');
  20. var modelSetup = require('test/init_model_test');
  21. require('utils/ajax/ajax');
  22. var c;
  23. describe('App.WizardStep5Controller', function () {
  24. beforeEach(function () {
  25. c = App.WizardStep5Controller.create();
  26. });
  27. var controller = App.WizardStep5Controller.create();
  28. controller.set('content', {});
  29. controller.set('content', {});
  30. describe('#sortHosts', function () {
  31. var tests = Em.A([
  32. {
  33. hosts: [
  34. Em.Object.create({memory: 4, cpu: 1, host_name: 'host1', id: 1}),
  35. Em.Object.create({memory: 3, cpu: 1, host_name: 'host2', id: 2}),
  36. Em.Object.create({memory: 2, cpu: 1, host_name: 'host3', id: 3}),
  37. Em.Object.create({memory: 1, cpu: 1, host_name: 'host4', id: 4})
  38. ],
  39. m: 'memory',
  40. e: [1, 2, 3, 4]
  41. },
  42. {
  43. hosts: [
  44. Em.Object.create({memory: 1, cpu: 4, host_name: 'host1', id: 1}),
  45. Em.Object.create({memory: 1, cpu: 3, host_name: 'host2', id: 2}),
  46. Em.Object.create({memory: 1, cpu: 2, host_name: 'host3', id: 3}),
  47. Em.Object.create({memory: 1, cpu: 1, host_name: 'host4', id: 4})
  48. ],
  49. m: 'cpu',
  50. e: [1, 2, 3, 4]
  51. },
  52. {
  53. hosts: [
  54. Em.Object.create({memory: 1, cpu: 1, host_name: 'host4', id: 1}),
  55. Em.Object.create({memory: 1, cpu: 1, host_name: 'host2', id: 2}),
  56. Em.Object.create({memory: 1, cpu: 1, host_name: 'host3', id: 3}),
  57. Em.Object.create({memory: 1, cpu: 1, host_name: 'host1', id: 4})
  58. ],
  59. m: 'host_name',
  60. e: [4, 2, 3, 1]
  61. },
  62. {
  63. hosts: [
  64. Em.Object.create({memory: 2, cpu: 1, host_name: 'host1', id: 1}),
  65. Em.Object.create({memory: 1, cpu: 2, host_name: 'host3', id: 2}),
  66. Em.Object.create({memory: 1, cpu: 1, host_name: 'host4', id: 3}),
  67. Em.Object.create({memory: 1, cpu: 1, host_name: 'host2', id: 4})
  68. ],
  69. m: 'mix',
  70. e: [1, 2, 4, 3]
  71. }
  72. ]);
  73. tests.forEach(function (test) {
  74. it(test.m, function () {
  75. var hosts = Em.copy(test.hosts);
  76. controller.sortHosts(hosts);
  77. expect(Em.A(hosts).mapProperty('id')).to.eql(test.e);
  78. });
  79. });
  80. });
  81. describe('#renderHostInfo', function () {
  82. var tests = Em.A([
  83. {
  84. hosts: {
  85. h1: {memory: 4, cpu: 1, name: 'host1', bootStatus: 'INIT'},
  86. h2: {memory: 3, cpu: 1, name: 'host2', bootStatus: 'INIT'},
  87. h3: {memory: 2, cpu: 1, name: 'host3', bootStatus: 'INIT'},
  88. h4: {memory: 1, cpu: 1, name: 'host4', bootStatus: 'INIT'}
  89. },
  90. m: 'no one host is REGISTERED',
  91. e: []
  92. },
  93. {
  94. hosts: {
  95. h1: {memory: 4, cpu: 1, name: 'host1', bootStatus: 'REGISTERED'},
  96. h2: {memory: 3, cpu: 1, name: 'host2', bootStatus: 'REGISTERED'},
  97. h3: {memory: 2, cpu: 1, name: 'host3', bootStatus: 'REGISTERED'},
  98. h4: {memory: 1, cpu: 1, name: 'host4', bootStatus: 'REGISTERED'}
  99. },
  100. m: 'all hosts are REGISTERED, memory',
  101. e: ['host1', 'host2', 'host3', 'host4']
  102. },
  103. {
  104. hosts: {
  105. h1: {memory: 1, cpu: 4, name: 'host1', bootStatus: 'REGISTERED'},
  106. h2: {memory: 1, cpu: 3, name: 'host2', bootStatus: 'REGISTERED'},
  107. h3: {memory: 1, cpu: 2, name: 'host3', bootStatus: 'REGISTERED'},
  108. h4: {memory: 1, cpu: 1, name: 'host4', bootStatus: 'REGISTERED'}
  109. },
  110. m: 'all hosts are REGISTERED, cpu',
  111. e: ['host1', 'host2', 'host3', 'host4']
  112. },
  113. {
  114. hosts: {
  115. h1: {memory: 1, cpu: 1, name: 'host4', bootStatus: 'REGISTERED'},
  116. h2: {memory: 1, cpu: 1, name: 'host2', bootStatus: 'REGISTERED'},
  117. h3: {memory: 1, cpu: 1, name: 'host3', bootStatus: 'REGISTERED'},
  118. h4: {memory: 1, cpu: 1, name: 'host1', bootStatus: 'REGISTERED'}
  119. },
  120. m: 'all hosts are REGISTERED, host_name',
  121. e: ['host1', 'host2', 'host3', 'host4']
  122. },
  123. {
  124. hosts: {
  125. h1: {memory: 2, cpu: 1, name: 'host1', bootStatus: 'REGISTERED'},
  126. h2: {memory: 1, cpu: 2, name: 'host3', bootStatus: 'INIT'},
  127. h3: {memory: 1, cpu: 1, name: 'host4', bootStatus: 'REGISTERED'},
  128. h4: {memory: 1, cpu: 1, name: 'host2', bootStatus: 'INIT'}
  129. },
  130. m: 'mix',
  131. e: ['host1', 'host4']
  132. }
  133. ]);
  134. tests.forEach(function (test) {
  135. it(test.m, function () {
  136. controller.set('content', {hosts: test.hosts});
  137. controller.renderHostInfo();
  138. var r = controller.get('hosts');
  139. expect(Em.A(r).mapProperty('host_name')).to.eql(test.e);
  140. });
  141. });
  142. });
  143. describe('#last', function () {
  144. var tests = Em.A([
  145. {
  146. selectedServicesMasters: Em.A([
  147. {component_name: 'c1', indx: 1},
  148. {component_name: 'c2', indx: 2},
  149. {component_name: 'c1', indx: 2}
  150. ]),
  151. m: 'Components exists',
  152. c: 'c1',
  153. e: 2
  154. },
  155. {
  156. selectedServicesMasters: Em.A([
  157. {component_name: 'c1', indx: 1},
  158. {component_name: 'c2', indx: 2},
  159. {component_name: 'c1', indx: 2}
  160. ]),
  161. m: 'Components don\'t exists',
  162. c: 'c3',
  163. e: null
  164. }
  165. ]);
  166. tests.forEach(function (test) {
  167. it(test.m, function () {
  168. controller.set('selectedServicesMasters', test.selectedServicesMasters);
  169. if (!Em.isNone(test.e)) {
  170. expect(controller.last(test.c).indx).to.equal(test.e);
  171. }
  172. else {
  173. expect(Em.isNone(controller.last(test.c))).to.equal(true);
  174. }
  175. })
  176. });
  177. });
  178. describe('#remainingHosts', function () {
  179. it('should show count of hosts without masters', function () {
  180. c.reopen({masterHostMapping: [
  181. {}
  182. ]});
  183. c.set('hosts', [
  184. {},
  185. {},
  186. {}
  187. ]);
  188. expect(c.get('remainingHosts')).to.equal(2);
  189. });
  190. });
  191. describe('#clearStep', function () {
  192. var tests = Em.A([
  193. {p: 'hosts'},
  194. {p: 'selectedServicesMasters'},
  195. {p: 'servicesMasters'}
  196. ]);
  197. tests.forEach(function (test) {
  198. it('should cleanup ' + test.p, function () {
  199. c.set(test.p, [Em.Object.create({}), Em.Object.create({})]);
  200. c.clearStep();
  201. expect(c.get(test.p).length).to.equal(0);
  202. });
  203. });
  204. });
  205. describe('#updateComponent', function () {
  206. var tests = Em.A([
  207. {
  208. componentName: 'HBASE_SERVER',
  209. serviceComponents: [
  210. Em.Object.create({
  211. componentName: 'HBASE_SERVER',
  212. stackService: Em.Object.create({isInstalled: true, serviceName: 'HBASE'})
  213. })
  214. ],
  215. selectedServicesMasters: Em.A([
  216. Em.Object.create({showAddControl: false, showRemoveControl: true, component_name: 'HBASE_SERVER'}),
  217. Em.Object.create({showAddControl: true, showRemoveControl: false, component_name: 'HBASE_SERVER'})
  218. ]),
  219. hosts: Em.A([
  220. Em.Object.create({})
  221. ]),
  222. controllerName: 'addServiceController',
  223. m: 'service is installed',
  224. e: {
  225. showAddControl: true,
  226. showRemoveControl: false
  227. }
  228. },
  229. {
  230. componentName: 'HBASE_SERVER',
  231. serviceComponents: [
  232. Em.Object.create({
  233. componentName: 'HBASE_SERVER',
  234. stackService: Em.Object.create({isInstalled: false, serviceName: 'HBASE'})
  235. })
  236. ],
  237. selectedServicesMasters: Em.A([
  238. Em.Object.create({showAddControl: true, showRemoveControl: false, component_name: 'HBASE_SERVER'})
  239. ]),
  240. hosts: Em.A([
  241. Em.Object.create({})
  242. ]),
  243. controllerName: 'addServiceController',
  244. m: 'service not installed, but all host already have provided component',
  245. e: {
  246. showAddControl: true,
  247. showRemoveControl: false
  248. }
  249. },
  250. {
  251. componentName: 'HBASE_SERVER',
  252. serviceComponents: [
  253. Em.Object.create({
  254. componentName: 'HBASE_SERVER',
  255. stackService: Em.Object.create({isInstalled: false, serviceName: 'HBASE'})
  256. })
  257. ],
  258. selectedServicesMasters: Em.A([
  259. Em.Object.create({showAddControl: false, showRemoveControl: true, component_name: 'HBASE_SERVER'})
  260. ]),
  261. hosts: Em.A([
  262. Em.Object.create({}),
  263. Em.Object.create({})
  264. ]),
  265. controllerName: 'reassignMasterController',
  266. m: 'service not installed, not all host already have provided component, but is reassignMasterController',
  267. e: {
  268. showAddControl: false,
  269. showRemoveControl: false
  270. }
  271. }
  272. ]);
  273. tests.forEach(function (test) {
  274. describe(test.m, function () {
  275. beforeEach(function () {
  276. sinon.stub(App.StackServiceComponent, 'find', function () {
  277. return test.serviceComponents;
  278. });
  279. c.reopen({
  280. content: Em.Object.create({
  281. controllerName: test.controllerName
  282. }),
  283. selectedServicesMasters: test.selectedServicesMasters,
  284. hosts: test.hosts
  285. });
  286. c.updateComponent(test.componentName);
  287. });
  288. afterEach(function () {
  289. App.StackServiceComponent.find.restore();
  290. });
  291. Em.keys(test.e).forEach(function (k) {
  292. it(k, function () {
  293. expect(c.last(test.componentName).get(k)).to.equal(test.e[k]);
  294. });
  295. });
  296. });
  297. });
  298. });
  299. describe('#renderComponents', function () {
  300. var tests = Em.A([
  301. {
  302. masterComponents: Em.A([
  303. {component_name: 'ZOOKEEPER_SERVER'}
  304. ]),
  305. services: Em.A([
  306. Em.Object.create({serviceName: 'ZOOKEEPER', isInstalled: false, isSelected: true})
  307. ]),
  308. controllerName: 'reassignMasterController',
  309. m: 'One component',
  310. isHaEnabled: false,
  311. component_name: 'ZOOKEEPER_SERVER',
  312. e: {
  313. selectedServicesMasters: ['ZOOKEEPER_SERVER'],
  314. servicesMasters: ['ZOOKEEPER_SERVER'],
  315. showRemoveControl: [false],
  316. isInstalled: [false],
  317. serviceComponentId: [1]
  318. }
  319. },
  320. {
  321. masterComponents: Em.A([
  322. {component_name: 'ZOOKEEPER_SERVER'}
  323. ]),
  324. services: Em.A([
  325. Em.Object.create({serviceName: 'ZOOKEEPER', isInstalled: false, isSelected: true})
  326. ]),
  327. controllerName: 'addServiceController',
  328. m: 'One component, service is not installed',
  329. component_name: 'ZOOKEEPER_SERVER',
  330. e: {
  331. selectedServicesMasters: ['ZOOKEEPER_SERVER'],
  332. servicesMasters: ['ZOOKEEPER_SERVER'],
  333. showRemoveControl: [false],
  334. serviceComponentId: [1]
  335. }
  336. },
  337. {
  338. masterComponents: Em.A([
  339. {component_name: 'ZOOKEEPER_SERVER'},
  340. {component_name: 'ZOOKEEPER_SERVER'}
  341. ]),
  342. services: Em.A([
  343. Em.Object.create({serviceName: 'ZOOKEEPER', isInstalled: true})
  344. ]),
  345. controllerName: 'addServiceController',
  346. m: 'Two components, but service is installed',
  347. component_name: 'ZOOKEEPER_SERVER',
  348. e: {
  349. selectedServicesMasters: ['ZOOKEEPER_SERVER', 'ZOOKEEPER_SERVER'],
  350. servicesMasters: ['ZOOKEEPER_SERVER', 'ZOOKEEPER_SERVER'],
  351. showRemoveControl: [false, false],
  352. serviceComponentId: [1, 2]
  353. }
  354. }
  355. ]);
  356. tests.forEach(function (test) {
  357. describe(test.m, function () {
  358. beforeEach(function () {
  359. sinon.stub(App, 'get').withArgs('isHaEnabled').returns(test.isHaEnabled);
  360. sinon.stub(App.StackService, 'find', function () {
  361. return test.services;
  362. });
  363. modelSetup.setupStackServiceComponent();
  364. c.reopen({
  365. content: Em.Object.create({
  366. services: test.services,
  367. controllerName: test.controllerName,
  368. reassign: {component_name: test.component_name}
  369. })
  370. });
  371. c.renderComponents(test.masterComponents);
  372. });
  373. afterEach(function () {
  374. App.get.restore();
  375. App.StackService.find.restore();
  376. modelSetup.cleanStackServiceComponent();
  377. });
  378. it('all selectedServicesMasters.component_name are valid', function () {
  379. expect(c.get('selectedServicesMasters').mapProperty('component_name')).to.eql(test.e.selectedServicesMasters);
  380. });
  381. it('all servicesMasters.component_name are valid', function () {
  382. expect(c.get('servicesMasters').mapProperty('component_name')).to.eql(test.e.servicesMasters);
  383. });
  384. it('all showRemoveControl are valid', function () {
  385. expect(c.get('selectedServicesMasters').mapProperty('showRemoveControl')).to.eql(test.e.showRemoveControl);
  386. });
  387. it('all serviceComponentId are valid', function () {
  388. expect(c.get('selectedServicesMasters').mapProperty('serviceComponentId')).to.eql(test.e.serviceComponentId);
  389. });
  390. it('servicesMasters.@each.isInstalled is valid', function () {
  391. if (c.get('isReasignController')) {
  392. expect(c.get('servicesMasters').mapProperty('isInstalled')).to.eql(test.e.isInstalled);
  393. }
  394. });
  395. });
  396. });
  397. });
  398. describe('#assignHostToMaster', function () {
  399. var tests = Em.A([
  400. {
  401. componentName: 'c1',
  402. selectedHost: 'h2',
  403. serviceComponentId: '1',
  404. e: {
  405. indx: 0
  406. }
  407. },
  408. {
  409. componentName: 'c2',
  410. selectedHost: 'h3',
  411. serviceComponentId: '2',
  412. e: {
  413. indx: 3
  414. }
  415. },
  416. {
  417. componentName: 'c3',
  418. selectedHost: 'h1',
  419. e: {
  420. indx: 2
  421. }
  422. },
  423. {
  424. componentName: 'c2',
  425. selectedHost: 'h4',
  426. e: {
  427. indx: 1
  428. }
  429. }
  430. ]),
  431. selectedServicesMasters = Em.A([
  432. Em.Object.create({component_name: 'c1', serviceComponentId: '1', selectedHost: 'h1'}),
  433. Em.Object.create({component_name: 'c2', serviceComponentId: '1', selectedHost: 'h1'}),
  434. Em.Object.create({component_name: 'c3', serviceComponentId: '1', selectedHost: 'h3'}),
  435. Em.Object.create({component_name: 'c2', serviceComponentId: '2', selectedHost: 'h2'})
  436. ]);
  437. tests.forEach(function (test) {
  438. it(test.componentName + ' ' + test.selectedHost + ' ' + test.serviceComponentId, function () {
  439. c.set('selectedServicesMasters', selectedServicesMasters);
  440. c.assignHostToMaster(test.componentName, test.selectedHost, test.serviceComponentId);
  441. expect(c.get('selectedServicesMasters').objectAt(test.e.indx).get('selectedHost')).to.equal(test.selectedHost);
  442. })
  443. });
  444. });
  445. describe('#removeComponent', function () {
  446. beforeEach(function () {
  447. sinon.stub(c, 'getMaxNumberOfMasters', function () {
  448. return Infinity;
  449. });
  450. });
  451. afterEach(function(){
  452. c.getMaxNumberOfMasters.restore();
  453. });
  454. var tests = Em.A([
  455. {
  456. componentName: 'c1',
  457. serviceComponentId: 1,
  458. selectedServicesMasters: Em.A([]),
  459. hosts: [],
  460. m: 'empty selectedServicesMasters',
  461. e: false
  462. },
  463. {
  464. componentName: 'ZOOKEPEER_SERVER',
  465. serviceComponentId: 1,
  466. selectedServicesMasters: Em.A([
  467. Em.Object.create({serviceComponentId: 1, component_name: 'HBASE_SERVER'})
  468. ]),
  469. hosts: [],
  470. m: 'no such components',
  471. e: false
  472. },
  473. {
  474. componentName: 'ZOOKEPEER_SERVER',
  475. serviceComponentId: 1,
  476. selectedServicesMasters: Em.A([
  477. Em.Object.create({serviceComponentId: 1, component_name: 'ZOOKEPEER_SERVER'})
  478. ]),
  479. hosts: [],
  480. m: 'component is only 1',
  481. e: false
  482. },
  483. {
  484. componentName: 'ZOOKEPEER_SERVER',
  485. serviceComponentId: 2,
  486. selectedServicesMasters: Em.A([
  487. Em.Object.create({serviceComponentId: 1, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false}),
  488. Em.Object.create({serviceComponentId: 2, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false})
  489. ]),
  490. hosts: [
  491. {},
  492. {}
  493. ],
  494. m: 'two components, add allowed, remove not allowed',
  495. e: true,
  496. showAddControl: true,
  497. showRemoveControl: false
  498. },
  499. {
  500. componentName: 'ZOOKEPEER_SERVER',
  501. serviceComponentId: 2,
  502. selectedServicesMasters: Em.A([
  503. Em.Object.create({serviceComponentId: 1, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false}),
  504. Em.Object.create({serviceComponentId: 2, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false}),
  505. Em.Object.create({serviceComponentId: 3, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: true})
  506. ]),
  507. hosts: [
  508. {},
  509. {},
  510. {}
  511. ],
  512. m: 'three components, add allowed, remove allowed',
  513. e: true,
  514. showAddControl: true,
  515. showRemoveControl: true
  516. }
  517. ]);
  518. tests.forEach(function (test) {
  519. describe(test.m, function () {
  520. beforeEach(function () {
  521. c.set('selectedServicesMasters', JSON.parse(JSON.stringify(test.selectedServicesMasters)));
  522. c.set('hosts', test.hosts);
  523. this.result = c.removeComponent(test.componentName, test.serviceComponentId);
  524. });
  525. it('removeComponent returns ' + test.e, function () {
  526. expect(this.result).to.equal(test.e);
  527. });
  528. if (test.e) {
  529. it('showRemoveControl is correct', function () {
  530. expect(c.get('selectedServicesMasters.lastObject.showRemoveControl')).to.equal(test.showRemoveControl);
  531. });
  532. it('showAddControl is correct', function () {
  533. expect(c.get('selectedServicesMasters.lastObject.showAddControl')).to.equal(test.showAddControl);
  534. });
  535. it('componentToRebalance is correct', function () {
  536. expect(c.get('componentToRebalance')).to.equal(test.componentName);
  537. });
  538. it('lastChangedComponent is correct', function () {
  539. expect(c.get('lastChangedComponent')).to.equal(test.componentName);
  540. });
  541. }
  542. })
  543. });
  544. });
  545. describe('#addComponent', function () {
  546. beforeEach(function () {
  547. sinon.stub(c, 'getMaxNumberOfMasters', function () {
  548. return Infinity;
  549. });
  550. });
  551. afterEach(function(){
  552. c.getMaxNumberOfMasters.restore();
  553. });
  554. var tests = Em.A([
  555. {
  556. componentName: 'c1',
  557. selectedServicesMasters: Em.A([]),
  558. hosts: [],
  559. m: 'empty selectedServicesMasters',
  560. e: false
  561. },
  562. {
  563. componentName: 'ZOOKEPEER_SERVER',
  564. selectedServicesMasters: Em.A([
  565. Em.Object.create({serviceComponentId: 1, component_name: 'HBASE_SERVER'})
  566. ]),
  567. hosts: [],
  568. m: 'no such components',
  569. e: false
  570. },
  571. {
  572. componentName: 'ZOOKEPEER_SERVER',
  573. selectedServicesMasters: Em.A([
  574. Em.Object.create({serviceComponentId: 1, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false}),
  575. Em.Object.create({serviceComponentId: 2, component_name: 'ZOOKEPEER_SERVER', showAddControl: false, showRemoveControl: false})
  576. ]),
  577. hosts: [Em.Object.create({}), Em.Object.create({}), Em.Object.create({})],
  578. m: 'two components, 3 hosts',
  579. e: true
  580. }
  581. ]);
  582. tests.forEach(function (test) {
  583. it(test.m, function () {
  584. c.set('selectedServicesMasters', test.selectedServicesMasters);
  585. c.set('hosts', test.hosts);
  586. expect(c.addComponent(test.componentName)).to.equal(test.e);
  587. if (test.e) {
  588. expect(c.get('componentToRebalance')).to.equal(test.componentName);
  589. expect(c.get('lastChangedComponent')).to.equal(test.componentName);
  590. }
  591. });
  592. });
  593. });
  594. describe('#masterHostMapping', function () {
  595. Em.A([
  596. {
  597. selectedServicesMasters: [
  598. Em.Object.create({selectedHost: 'h1'}),
  599. Em.Object.create({selectedHost: 'h2'}),
  600. Em.Object.create({selectedHost: 'h1'})
  601. ],
  602. hosts: [
  603. Em.Object.create({host_name: 'h1', host_info: {}}),
  604. Em.Object.create({host_name: 'h2', host_info: {}})
  605. ],
  606. m: 'Two hosts',
  607. e: [
  608. {host_name: 'h1', hostInfo: {}, masterServices: [
  609. {},
  610. {}
  611. ]},
  612. {host_name: 'h2', hostInfo: {}, masterServices: [
  613. {}
  614. ]}
  615. ]
  616. },
  617. {
  618. selectedServicesMasters: [],
  619. hosts: [],
  620. m: 'No hosts',
  621. e: []
  622. },
  623. {
  624. selectedServicesMasters: [
  625. Em.Object.create({selectedHost: 'h1'}),
  626. Em.Object.create({selectedHost: 'h1'})
  627. ],
  628. hosts: [
  629. Em.Object.create({host_name: 'h1', host_info: {}})
  630. ],
  631. m: 'One host',
  632. e: [
  633. {host_name: 'h1', hostInfo: {}, masterServices: [
  634. {},
  635. {}
  636. ]}
  637. ]
  638. }
  639. ]).forEach(function (test) {
  640. describe(test.m, function () {
  641. var result;
  642. beforeEach(function () {
  643. c.reopen({
  644. selectedServicesMasters: test.selectedServicesMasters,
  645. hosts: test.hosts
  646. });
  647. result = c.get('masterHostMapping');
  648. });
  649. it('all needed hosts are mapped', function () {
  650. expect(result.length).to.equal(test.e.length);
  651. });
  652. it('all needed hosts have valid data', function () {
  653. result.forEach(function (r, i) {
  654. expect(r.get('host_name')).to.equal(test.e[i].host_name);
  655. expect(r.get('masterServices.length')).to.equal(test.e[i].masterServices.length);
  656. expect(r.get('hostInfo')).to.be.an.object;
  657. });
  658. });
  659. });
  660. });
  661. });
  662. describe('#anyError', function () {
  663. Em.A([
  664. {
  665. servicesMasters: [
  666. Em.Object.create({errorMessage: 'some message'}),
  667. Em.Object.create({errorMessage: ''})
  668. ],
  669. generalErrorMessages: [],
  670. e: true
  671. },
  672. {
  673. servicesMasters: [
  674. Em.Object.create({errorMessage: ''}),
  675. Em.Object.create({errorMessage: ''})
  676. ],
  677. generalErrorMessages: [],
  678. e: false
  679. },
  680. {
  681. servicesMasters: [
  682. Em.Object.create({errorMessage: 'some message'}),
  683. Em.Object.create({errorMessage: 'some message 2'})
  684. ],
  685. generalErrorMessages: ['some message'],
  686. e: true
  687. },
  688. {
  689. servicesMasters: [
  690. Em.Object.create({errorMessage: ''}),
  691. Em.Object.create({errorMessage: ''})
  692. ],
  693. generalErrorMessages: ['some message'],
  694. e: true
  695. }
  696. ]).forEach(function (test, i) {
  697. it('test #' + i.toString(), function () {
  698. c.setProperties({
  699. servicesMasters: test.servicesMasters,
  700. generalErrorMessages: test.generalErrorMessages
  701. });
  702. expect(c.get('anyError')).to.equal(test.e);
  703. });
  704. });
  705. });
  706. describe('#anyWarning', function () {
  707. Em.A([
  708. {
  709. servicesMasters: [
  710. Em.Object.create({warnMessage: 'some message'}),
  711. Em.Object.create({warnMessage: ''})
  712. ],
  713. generalWarningMessages: [],
  714. e: true
  715. },
  716. {
  717. servicesMasters: [
  718. Em.Object.create({warnMessage: ''}),
  719. Em.Object.create({warnMessage: ''})
  720. ],
  721. generalWarningMessages: [],
  722. e: false
  723. },
  724. {
  725. servicesMasters: [
  726. Em.Object.create({warnMessage: 'some message'}),
  727. Em.Object.create({warnMessage: 'some message 2'})
  728. ],
  729. generalWarningMessages: ['some message'],
  730. e: true
  731. },
  732. {
  733. servicesMasters: [
  734. Em.Object.create({warnMessage: ''}),
  735. Em.Object.create({warnMessage: ''})
  736. ],
  737. generalWarningMessages: ['some message'],
  738. e: true
  739. }
  740. ]).forEach(function (test, i) {
  741. it('test #' + i.toString(), function () {
  742. c.setProperties({
  743. servicesMasters: test.servicesMasters,
  744. generalWarningMessages: test.generalWarningMessages
  745. });
  746. expect(c.get('anyWarning')).to.equal(test.e);
  747. });
  748. });
  749. });
  750. describe('#clearRecommendations', function () {
  751. it('should clear content.recommendations', function () {
  752. c.set('content', {recommendations: {'s': {}}});
  753. c.clearRecommendations();
  754. expect(c.get('content.recommendations')).to.be.null;
  755. });
  756. });
  757. describe('#updateIsSubmitDisabled', function () {
  758. var clearCases = [
  759. {
  760. isHostNameValid: true,
  761. isInitialLayout: true,
  762. isInitialLayoutResulting: false,
  763. clearRecommendationsCallCount: 0,
  764. recommendAndValidateCallCount: 1,
  765. title: 'initial masters-hosts layout'
  766. },
  767. {
  768. isHostNameValid: true,
  769. isInitialLayout: false,
  770. isInitialLayoutResulting: false,
  771. clearRecommendationsCallCount: 1,
  772. recommendAndValidateCallCount: 1,
  773. title: 'master-hosts layout changed'
  774. },
  775. {
  776. isHostNameValid: false,
  777. isInitialLayout: false,
  778. isInitialLayoutResulting: false,
  779. clearRecommendationsCallCount: 0,
  780. recommendAndValidateCallCount: 0,
  781. title: 'invalid host name specified'
  782. }
  783. ];
  784. beforeEach(function () {
  785. c.set('selectedServicesMasters', [
  786. {isInstalled: false}
  787. ]);
  788. sinon.stub(c, 'clearRecommendations', Em.K);
  789. sinon.stub(c, 'recommendAndValidate', Em.K);
  790. });
  791. afterEach(function () {
  792. c.clearRecommendations.restore();
  793. c.recommendAndValidate.restore();
  794. });
  795. it('shouldn\'t change submitDisabled if thereIsNoMasters returns false', function () {
  796. c.set('selectedServicesMasters', [
  797. {isInstalled: true}
  798. ]);
  799. c.set('submitDisabled', false);
  800. c.updateIsSubmitDisabled();
  801. expect(c.get('submitDisabled')).to.equal(false);
  802. });
  803. it('should check servicesMasters.@each.isHostNameValid if useServerValidation is false', function () {
  804. c.set('useServerValidation', false);
  805. c.set('servicesMasters', [
  806. {isHostNameValid: false},
  807. {isHostNameValid: true}
  808. ]);
  809. c.updateIsSubmitDisabled();
  810. expect(c.get('submitDisabled')).to.equal(true);
  811. c.set('servicesMasters', [
  812. {isHostNameValid: true},
  813. {isHostNameValid: true}
  814. ]);
  815. c.updateIsSubmitDisabled();
  816. expect(c.get('submitDisabled')).to.equal(false);
  817. });
  818. clearCases.forEach(function (item) {
  819. it(item.title, function () {
  820. c.setProperties({
  821. isInitialLayout: item.isInitialLayout,
  822. servicesMasters: [{
  823. isHostNameValid: item.isHostNameValid
  824. }]
  825. });
  826. expect(c.get('isInitialLayout')).to.equal(item.isInitialLayoutResulting);
  827. expect(c.clearRecommendations.callCount).to.equal(item.clearRecommendationsCallCount);
  828. expect(c.recommendAndValidate.callCount).to.equal(item.recommendAndValidateCallCount);
  829. });
  830. });
  831. });
  832. describe('#isHostNameValid', function () {
  833. beforeEach(function () {
  834. c.setProperties({
  835. hosts: [
  836. {host_name: 'h1'},
  837. {host_name: 'h2'},
  838. {host_name: 'h3'}
  839. ],
  840. selectedServicesMasters: [
  841. {component_name: 'c1', selectedHost: 'h1'},
  842. {component_name: 'c2', selectedHost: 'h2'},
  843. {component_name: 'c3', selectedHost: 'h3'},
  844. {component_name: 'c3', selectedHost: 'h1'}
  845. ]
  846. });
  847. });
  848. Em.A([
  849. {
  850. componentName: 'c1',
  851. selectedHost: ' ',
  852. m: 'empty hostName is invalid',
  853. e: false
  854. },
  855. {
  856. componentName: 'c1',
  857. selectedHost: 'h4',
  858. m: 'hostName not exists',
  859. e: false
  860. },
  861. {
  862. componentName: 'c4',
  863. selectedHost: 'h3',
  864. m: 'component not exists on host',
  865. e: true
  866. }
  867. ]).forEach(function (test) {
  868. it(test.m, function () {
  869. expect(c.isHostNameValid(test.componentName, test.selectedHost)).to.equal(test.e);
  870. });
  871. });
  872. });
  873. describe('#createComponentInstallationObject', function () {
  874. afterEach(function () {
  875. App.StackServiceComponent.find.restore();
  876. });
  877. Em.A([
  878. {
  879. fullComponent: Em.Object.create({
  880. componentName: 'c1',
  881. serviceName: 's1'
  882. }),
  883. hostName: 'h1',
  884. mastersToMove: ['c1'],
  885. savedComponent: {
  886. hostName: 'h2',
  887. isInstalled: true
  888. },
  889. stackServiceComponents: [Em.Object.create({componentName: 'c1', isCoHostedComponent: true})],
  890. e: {
  891. component_name: 'c1',
  892. display_name: 'C1',
  893. serviceId: 's1',
  894. selectedHost: 'h2',
  895. isInstalled: true,
  896. isServiceCoHost: false
  897. }
  898. },
  899. {
  900. fullComponent: Em.Object.create({
  901. componentName: 'c1',
  902. serviceName: 's1'
  903. }),
  904. hostName: 'h1',
  905. mastersToMove: [],
  906. stackServiceComponents: [Em.Object.create({componentName: 'c1', isCoHostedComponent: false})],
  907. e: {
  908. component_name: 'c1',
  909. display_name: 'C1',
  910. serviceId: 's1',
  911. selectedHost: 'h1',
  912. isInstalled: false,
  913. isServiceCoHost: false
  914. }
  915. },
  916. {
  917. fullComponent: Em.Object.create({
  918. componentName: 'c1',
  919. serviceName: 's1'
  920. }),
  921. hostName: 'h1',
  922. mastersToMove: [],
  923. stackServiceComponents: [Em.Object.create({componentName: 'c1', isCoHostedComponent: true})],
  924. e: {
  925. component_name: 'c1',
  926. display_name: 'C1',
  927. serviceId: 's1',
  928. selectedHost: 'h1',
  929. isInstalled: false,
  930. isServiceCoHost: true
  931. }
  932. }
  933. ]).forEach(function (test, i) {
  934. describe('test #' + i, function () {
  935. beforeEach(function () {
  936. sinon.stub(App.StackServiceComponent, 'find', function () {
  937. return test.stackServiceComponents;
  938. });
  939. c.set('mastersToMove', test.mastersToMove);
  940. c.set('content', {controllerName: test.controllerName});
  941. });
  942. it('component-object is valid', function () {
  943. expect(c.createComponentInstallationObject(test.fullComponent, test.hostName, test.savedComponent)).to.eql(test.e);
  944. });
  945. });
  946. });
  947. });
  948. describe('#createComponentInstallationObjects', function () {
  949. beforeEach(function() {
  950. sinon.stub(App.StackServiceComponent, 'find', function() {
  951. return [
  952. Em.Object.create({isShownOnAddServiceAssignMasterPage: true, componentName: 'c1', serviceName: 's1'}),
  953. Em.Object.create({isShownOnAddServiceAssignMasterPage: true, componentName: 'c2', serviceName: 's2'}),
  954. Em.Object.create({isShownOnAddServiceAssignMasterPage: true, componentName: 'c4', serviceName: 's2'}),
  955. Em.Object.create({isShownOnInstallerAssignMasterPage: true, componentName: 'c1', serviceName: 's1'}),
  956. Em.Object.create({isShownOnInstallerAssignMasterPage: true, componentName: 'c2', serviceName: 's2'}),
  957. Em.Object.create({isShownOnInstallerAssignMasterPage: true, componentName: 'c4', serviceName: 's2'})
  958. ];
  959. });
  960. c.set('content', {
  961. masterComponentHosts: [],
  962. services: [
  963. {serviceName: 's1', isSelected: true, isInstalled: false},
  964. {serviceName: 's2', isSelected: true, isInstalled: false}
  965. ],
  966. recommendations: {
  967. "blueprint": {
  968. "host_groups": [
  969. {
  970. "name": "host-group-1",
  971. "components": [ {"name": "c1"}, {"name": "c2"} ]
  972. },
  973. {
  974. "name": "host-group-2",
  975. "components": [ {"name": "c1"}, {"name": "c2"} ]
  976. },
  977. {
  978. "name": "host-group-3",
  979. "components": [ {"name": "c1"} ]
  980. }
  981. ]
  982. },
  983. "blueprint_cluster_binding": {
  984. "host_groups": [
  985. {
  986. "name": "host-group-1",
  987. "hosts": [ {"fqdn": "h1"} ]
  988. },
  989. {
  990. "name": "host-group-2",
  991. "hosts": [ {"fqdn": "h2"} ]
  992. },
  993. {
  994. "name": "host-group-3",
  995. "hosts": [ {"fqdn": "h3"} ]
  996. }
  997. ]
  998. }
  999. }
  1000. });
  1001. });
  1002. afterEach(function() {
  1003. App.StackServiceComponent.find.restore();
  1004. });
  1005. it('simple map without nothing stored/saved etc', function() {
  1006. var r = c.createComponentInstallationObjects();
  1007. expect(r.mapProperty('component_name')).to.eql(['c1', 'c2', 'c1', 'c2', 'c1']);
  1008. expect(r.mapProperty('serviceId')).to.eql(['s1', 's2', 's1', 's2', 's1']);
  1009. expect(r.mapProperty('selectedHost')).to.eql(['h1', 'h1', 'h2', 'h2', 'h3']);
  1010. });
  1011. describe('some saved components exist', function() {
  1012. beforeEach(function () {
  1013. c.set('content.controllerName', 'addServiceController');
  1014. c.get('multipleComponents').push('c4');
  1015. c.set('content.masterComponentHosts', [
  1016. {hostName: 'h3', component: 'c4'}
  1017. ]);
  1018. c.get('content.recommendations.blueprint.host_groups')[2].components.push({name: 'c4'});
  1019. });
  1020. it('data contains save components', function () {
  1021. var r = c.createComponentInstallationObjects();
  1022. expect(r.mapProperty('component_name')).to.eql(['c1', 'c2', 'c1', 'c2', 'c1', 'c4']);
  1023. expect(r.mapProperty('serviceId')).to.eql(['s1', 's2', 's1', 's2', 's1', 's2']);
  1024. expect(r.mapProperty('selectedHost')).to.eql(['h1', 'h1', 'h2', 'h2', 'h3', 'h3']);
  1025. });
  1026. });
  1027. });
  1028. describe('#getCurrentBlueprint', function () {
  1029. beforeEach(function() {
  1030. sinon.stub(c, 'getCurrentSlaveBlueprint', function() {
  1031. return {
  1032. blueprint_cluster_binding: {
  1033. host_groups: []
  1034. },
  1035. blueprint: {
  1036. host_groups: []
  1037. }
  1038. };
  1039. });
  1040. });
  1041. afterEach(function() {
  1042. c.getCurrentSlaveBlueprint.restore();
  1043. });
  1044. it('should map masterHostMapping', function () {
  1045. c.reopen({masterHostMapping: [
  1046. {host_name: 'h1', hostInfo:{}, masterServices: [
  1047. {serviceId: 's1', component_name: 'c1'},
  1048. {serviceId: 's2', component_name: 'c2'}
  1049. ]},
  1050. {host_name: 'h2', hostInfo:{}, masterServices: [
  1051. {serviceId: 's1', component_name: 'c1'},
  1052. {serviceId: 's3', component_name: 'c3'}
  1053. ]}
  1054. ]});
  1055. var r = c.getCurrentBlueprint();
  1056. expect(r).to.eql({"blueprint": {"host_groups": [
  1057. {"name": "host-group-1", "components": [
  1058. {"name": "c1"},
  1059. {"name": "c2"}
  1060. ]},
  1061. {"name": "host-group-2", "components": [
  1062. {"name": "c1"},
  1063. {"name": "c3"}
  1064. ]}
  1065. ]}, "blueprint_cluster_binding": {"host_groups": [
  1066. {"name": "host-group-1", "hosts": [
  1067. {"fqdn": "h1"}
  1068. ]},
  1069. {"name": "host-group-2", "hosts": [
  1070. {"fqdn": "h2"}
  1071. ]}
  1072. ]}}
  1073. );
  1074. });
  1075. });
  1076. describe('#updateValidationsSuccessCallback', function() {
  1077. beforeEach(function() {
  1078. sinon.stub(App.HostComponent, 'find', function() {
  1079. return [];
  1080. });
  1081. });
  1082. afterEach(function() {
  1083. App.HostComponent.find.restore();
  1084. });
  1085. describe('should map messages to generalErrorMessages, generalWarningMessages', function() {
  1086. var data = [
  1087. {
  1088. type: 'host-component',
  1089. 'component-name': 'c1',
  1090. host: 'h1',
  1091. level: 'ERROR',
  1092. message: 'm1'
  1093. },
  1094. {
  1095. type: 'host-component',
  1096. 'component-name': 'c2',
  1097. host: 'h2',
  1098. level: 'WARN',
  1099. message: 'm2'
  1100. },
  1101. {
  1102. type: 'host-component',
  1103. 'component-name': 'c3',
  1104. host: 'h3',
  1105. level: 'ERROR',
  1106. message: 'm3'
  1107. },
  1108. {
  1109. type: 'host-component',
  1110. 'component-name': 'c4',
  1111. host: 'h4',
  1112. level: 'WARN',
  1113. message: 'm4'
  1114. }
  1115. ],
  1116. servicesMasters = [
  1117. Em.Object.create({selectedHost: 'h1', component_name: 'c1'}),
  1118. Em.Object.create({selectedHost: 'h2', component_name: 'c2'})
  1119. ];
  1120. beforeEach(function () {
  1121. c.set('servicesMasters', servicesMasters);
  1122. c.updateValidationsSuccessCallback({resources: [{items: data}]});
  1123. });
  1124. it('submitDisabled is false', function () {
  1125. expect(c.get('submitDisabled')).to.equal(false);
  1126. });
  1127. it('errorMessage for c1 is `m1`', function () {
  1128. expect(c.get('servicesMasters').findProperty('component_name', 'c1').get('errorMessage')).to.equal('m1');
  1129. });
  1130. it('errorMessage for c2 is `m2`', function () {
  1131. expect(c.get('servicesMasters').findProperty('component_name', 'c2').get('warnMessage')).to.equal('m2');
  1132. });
  1133. it('no general errors', function () {
  1134. expect(c.get('generalErrorMessages')).to.be.empty;
  1135. });
  1136. it('no general warnings', function () {
  1137. expect(c.get('generalWarningMessages')).to.be.empty;
  1138. });
  1139. });
  1140. });
  1141. describe('#sortComponentsByServiceName', function () {
  1142. var components = [{
  1143. "component_name": "METRICS_COLLECTOR",
  1144. "serviceId": "AMBARI_METRICS"
  1145. }, {"component_name": "ZOOKEEPER_SERVER", "serviceId": "ZOOKEEPER"}, {
  1146. "component_name": "NAMENODE",
  1147. "serviceId": "HDFS"
  1148. }, {"component_name": "DRPC_SERVER", "serviceId": "STORM"}, {
  1149. "component_name": "APP_TIMELINE_SERVER",
  1150. "serviceId": "YARN"
  1151. }, {"component_name": "RESOURCEMANAGER", "serviceId": "YARN"}, {
  1152. "component_name": "SECONDARY_NAMENODE",
  1153. "serviceId": "HDFS"
  1154. }, {"component_name": "ZOOKEEPER_SERVER", "serviceId": "ZOOKEEPER"}, {
  1155. "component_name": "HISTORYSERVER",
  1156. "serviceId": "MAPREDUCE2"
  1157. }, {"component_name": "NIMBUS", "serviceId": "STORM"}, {"component_name": "STORM_UI_SERVER", "serviceId": "STORM"}];
  1158. it('ZKS should be one after anothert', function () {
  1159. var sorted = c.sortComponentsByServiceName(components);
  1160. expect(sorted.mapProperty('component_name').join('|').contains('ZOOKEEPER_SERVER|ZOOKEEPER_SERVER')).to.be.true;
  1161. });
  1162. });
  1163. });