update_controller_test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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('utils/updater');
  20. require('controllers/global/update_controller');
  21. var testHelpers = require('test/helpers');
  22. var c;
  23. describe('App.UpdateController', function () {
  24. var controller = App.UpdateController.create({
  25. clusterName: '',
  26. location: '',
  27. updateServiceMetric: function(){}
  28. });
  29. beforeEach(function () {
  30. c = App.UpdateController.create();
  31. });
  32. App.TestAliases.testAsComputedAlias(App.UpdateController.create(), 'clusterName', 'App.router.clusterController.clusterName', 'string');
  33. App.TestAliases.testAsComputedAnd(App.UpdateController.create(), 'updateAlertInstances', ['isWorking', '!App.router.mainAlertInstancesController.isUpdating']);
  34. describe('#getUrl()', function () {
  35. it('testMode = false', function () {
  36. expect(controller.getUrl('test', '/real')).to.equal('/api/v1/clusters//real');
  37. });
  38. it('testMode = false (2)', function () {
  39. controller.set('clusterName', 'mycluster');
  40. expect(controller.getUrl('test', '/real')).to.equal('/api/v1/clusters/mycluster/real');
  41. });
  42. });
  43. describe('#updateAll()', function () {
  44. it('isWorking = false', function () {
  45. controller.set('isWorking', false);
  46. expect(App.updater.run.called).to.equal(false);
  47. });
  48. it('isWorking = true', function () {
  49. controller.set('isWorking', true);
  50. expect(App.updater.run.callCount).to.equal(12);
  51. });
  52. });
  53. describe('#getConditionalFields()', function () {
  54. var testCases = [
  55. {
  56. title: 'No services exist',
  57. services: [],
  58. result: ['metrics/1']
  59. },
  60. {
  61. title: 'HDFS service',
  62. services: [
  63. {
  64. ServiceInfo: {
  65. service_name: 'HDFS'
  66. }
  67. }
  68. ],
  69. result: ['metrics/1']
  70. },
  71. {
  72. title: 'FLUME service',
  73. services: [
  74. {
  75. ServiceInfo: {
  76. service_name: 'FLUME'
  77. }
  78. }
  79. ],
  80. result: ['metrics/1', "host_components/processes/HostComponentProcess"]
  81. },
  82. {
  83. title: 'YARN service',
  84. services: [
  85. {
  86. ServiceInfo: {
  87. service_name: 'YARN'
  88. }
  89. }
  90. ],
  91. result: ['metrics/1', "host_components/metrics/yarn/Queue," +
  92. "host_components/metrics/yarn/ClusterMetrics/NumActiveNMs," +
  93. "host_components/metrics/yarn/ClusterMetrics/NumLostNMs," +
  94. "host_components/metrics/yarn/ClusterMetrics/NumUnhealthyNMs," +
  95. "host_components/metrics/yarn/ClusterMetrics/NumRebootedNMs," +
  96. "host_components/metrics/yarn/ClusterMetrics/NumDecommissionedNMs"]
  97. },
  98. {
  99. title: 'HBASE service',
  100. services: [
  101. {
  102. ServiceInfo: {
  103. service_name: 'HBASE'
  104. }
  105. }
  106. ],
  107. result: ['metrics/1', "host_components/metrics/hbase/master/IsActiveMaster," +
  108. "host_components/metrics/hbase/master/MasterStartTime," +
  109. "host_components/metrics/hbase/master/MasterActiveTime," +
  110. "host_components/metrics/hbase/master/AverageLoad," +
  111. "host_components/metrics/master/AssignmentManger/ritCount"]
  112. },
  113. {
  114. title: 'STORM service',
  115. services: [
  116. {
  117. ServiceInfo: {
  118. service_name: 'STORM'
  119. }
  120. }
  121. ],
  122. result: ['metrics/1', "metrics/api/v1/cluster/summary," +
  123. "metrics/api/v1/topology/summary," +
  124. "metrics/api/v1/nimbus/summary"]
  125. }
  126. ];
  127. var testCasesByStackVersion = [
  128. {
  129. title: 'STORM service stack 2.1',
  130. services: [
  131. {
  132. ServiceInfo: {
  133. service_name: 'STORM'
  134. }
  135. }
  136. ],
  137. stackVersionNumber: '2.1',
  138. result: ['metrics/1', "metrics/api/cluster/summary"]
  139. },
  140. {
  141. title: 'STORM service stack 2.2',
  142. services: [
  143. {
  144. ServiceInfo: {
  145. service_name: 'STORM'
  146. }
  147. }
  148. ],
  149. stackVersionNumber: '2.2',
  150. result: ['metrics/1', "metrics/api/v1/cluster/summary,metrics/api/v1/topology/summary"]
  151. },
  152. {
  153. title: 'STORM service stack 2.3',
  154. services: [
  155. {
  156. ServiceInfo: {
  157. service_name: 'STORM'
  158. }
  159. }
  160. ],
  161. stackVersionNumber: '2.3',
  162. result: ['metrics/1', "metrics/api/v1/cluster/summary,metrics/api/v1/topology/summary,metrics/api/v1/nimbus/summary"]
  163. }
  164. ];
  165. beforeEach(function () {
  166. this.mock = sinon.stub(App, 'get');
  167. controller.set('serviceComponentMetrics', ['metrics/1']);
  168. });
  169. afterEach(function () {
  170. this.mock.restore();
  171. });
  172. testCases.forEach(function (test) {
  173. it(test.title, function () {
  174. App.cache.services = test.services;
  175. this.mock.withArgs('router.clusterController.isServiceMetricsLoaded').returns(true);
  176. expect(controller.getConditionalFields()).to.eql(test.result);
  177. });
  178. });
  179. testCasesByStackVersion.forEach(function (test) {
  180. it(test.title, function () {
  181. App.cache.services = test.services;
  182. this.mock.withArgs('currentStackVersionNumber').returns(test.stackVersionNumber);
  183. this.mock.withArgs('router.clusterController.isServiceMetricsLoaded').returns(true);
  184. expect(controller.getConditionalFields()).to.eql(test.result);
  185. });
  186. });
  187. it('FLUME service, first load', function () {
  188. App.cache.services = [
  189. {
  190. ServiceInfo: {
  191. service_name: 'FLUME'
  192. }
  193. }
  194. ];
  195. this.mock.withArgs('router.clusterController.isServiceMetricsLoaded').returns(false);
  196. expect(controller.getConditionalFields()).to.eql(["host_components/processes/HostComponentProcess"]);
  197. });
  198. });
  199. describe("#getComplexUrl()", function () {
  200. beforeEach(function () {
  201. sinon.stub(App, 'get').returns('mock');
  202. sinon.stub(controller, 'computeParameters').returns('params');
  203. });
  204. afterEach(function () {
  205. App.get.restore();
  206. controller.computeParameters.restore();
  207. });
  208. it("queryParams is empty", function () {
  209. expect(controller.getComplexUrl('<parameters>')).to.equal('mock/clusters/mock');
  210. });
  211. it("queryParams is present", function () {
  212. var queryParams = [
  213. {
  214. type: "EQUAL",
  215. key: "key",
  216. value: "value"
  217. }
  218. ];
  219. expect(controller.getComplexUrl('<parameters>', queryParams)).to.equal('mock/clusters/mockparams&');
  220. });
  221. });
  222. describe("#addParamsToHostsUrl()", function () {
  223. beforeEach(function () {
  224. sinon.stub(App, 'get').returns('mock');
  225. sinon.stub(controller, 'computeParameters').returns('params');
  226. });
  227. afterEach(function () {
  228. App.get.restore();
  229. controller.computeParameters.restore();
  230. });
  231. it("valid params are added", function () {
  232. expect(controller.addParamsToHostsUrl([], [], 'url')).to.equal('mock/clusters/mockurl&params&params');
  233. });
  234. });
  235. describe("#loadHostsMetric()", function () {
  236. beforeEach(function () {
  237. this.mock = sinon.stub(App.Service, 'find');
  238. sinon.stub(controller, 'computeParameters');
  239. sinon.stub(controller, 'addParamsToHostsUrl');
  240. });
  241. afterEach(function () {
  242. App.Service.find.restore();
  243. controller.computeParameters.restore();
  244. controller.addParamsToHostsUrl.restore();
  245. });
  246. it("AMBARI_METRICS is not started", function () {
  247. this.mock.returns(Em.Object.create({isStarted: false}));
  248. expect(controller.loadHostsMetric([])).to.be.null;
  249. var args = testHelpers.findAjaxRequest('name', 'hosts.metrics.lazy_load');
  250. expect(args).to.not.exists;
  251. });
  252. it("AMBARI_METRICS is started", function () {
  253. this.mock.returns(Em.Object.create({isStarted: true}));
  254. expect(controller.loadHostsMetric([])).to.be.object;
  255. var args = testHelpers.findAjaxRequest('name', 'hosts.metrics.lazy_load');
  256. expect(args).to.exists;
  257. });
  258. });
  259. describe("#loadHostsMetricSuccessCallback()", function () {
  260. beforeEach(function () {
  261. sinon.stub(App.hostsMapper, 'setMetrics');
  262. });
  263. afterEach(function () {
  264. App.hostsMapper.setMetrics.restore();
  265. });
  266. it("setMetrics called with valid arguments", function () {
  267. controller.loadHostsMetricSuccessCallback({});
  268. expect(App.hostsMapper.setMetrics.calledWith({})).to.be.true;
  269. });
  270. });
  271. describe('#updateUpgradeState()', function () {
  272. var cases = [
  273. {
  274. currentStateName: 'versions',
  275. parentStateName: 'stackAndUpgrade',
  276. wizardIsNotFinished: true,
  277. isLoadUpgradeDataPending: true,
  278. loadUpgradeDataCallCount: 0,
  279. callbackCallCount: 1,
  280. title: 'stack versions page'
  281. },
  282. {
  283. currentStateName: 'stackUpgrade',
  284. parentStateName: 'admin',
  285. wizardIsNotFinished: true,
  286. isLoadUpgradeDataPending: true,
  287. loadUpgradeDataCallCount: 0,
  288. callbackCallCount: 1,
  289. title: 'upgrade popup open'
  290. },
  291. {
  292. currentStateName: 'versions',
  293. parentStateName: 'admin',
  294. wizardIsNotFinished: true,
  295. isLoadUpgradeDataPending: false,
  296. loadUpgradeDataCallCount: 1,
  297. callbackCallCount: 0,
  298. title: 'another page with \'versions\' name'
  299. },
  300. {
  301. currentStateName: 'versions',
  302. parentStateName: 'admin',
  303. wizardIsNotFinished: false,
  304. isLoadUpgradeDataPending: false,
  305. loadUpgradeDataCallCount: 0,
  306. callbackCallCount: 1,
  307. title: 'another page with \'versions\' name, upgrade finished'
  308. },
  309. {
  310. currentStateName: 'versions',
  311. parentStateName: 'admin',
  312. wizardIsNotFinished: true,
  313. isLoadUpgradeDataPending: true,
  314. loadUpgradeDataCallCount: 0,
  315. callbackCallCount: 1,
  316. title: 'another page with \'versions\' name, another update upgrade request not completed'
  317. },
  318. {
  319. currentStateName: 'services',
  320. parentStateName: 'stackAndUpgrade',
  321. wizardIsNotFinished: true,
  322. isLoadUpgradeDataPending: false,
  323. loadUpgradeDataCallCount: 1,
  324. callbackCallCount: 0,
  325. title: 'another page from \'Stack and Versions\' section'
  326. },
  327. {
  328. currentStateName: 'services',
  329. parentStateName: 'stackAndUpgrade',
  330. wizardIsNotFinished: false,
  331. isLoadUpgradeDataPending: false,
  332. loadUpgradeDataCallCount: 0,
  333. callbackCallCount: 1,
  334. title: 'another page from \'Stack and Versions\' section, upgrade finished'
  335. },
  336. {
  337. currentStateName: 'services',
  338. parentStateName: 'stackAndUpgrade',
  339. wizardIsNotFinished: true,
  340. isLoadUpgradeDataPending: true,
  341. loadUpgradeDataCallCount: 0,
  342. callbackCallCount: 1,
  343. title: 'another page from \'Stack and Versions\' section, another update upgrade request not completed'
  344. },
  345. {
  346. currentStateName: 'widgets',
  347. parentStateName: 'dashboard',
  348. wizardIsNotFinished: true,
  349. isLoadUpgradeDataPending: false,
  350. loadUpgradeDataCallCount: 1,
  351. callbackCallCount: 0,
  352. title: 'not \'Stack and Versions\' section'
  353. },
  354. {
  355. currentStateName: 'widgets',
  356. parentStateName: 'dashboard',
  357. wizardIsNotFinished: false,
  358. isLoadUpgradeDataPending: false,
  359. loadUpgradeDataCallCount: 0,
  360. callbackCallCount: 1,
  361. title: 'not \'Stack and Versions\' section, upgrade finished'
  362. },
  363. {
  364. currentStateName: 'widgets',
  365. parentStateName: 'dashboard',
  366. wizardIsNotFinished: true,
  367. isLoadUpgradeDataPending: true,
  368. loadUpgradeDataCallCount: 0,
  369. callbackCallCount: 1,
  370. title: 'not \'Stack and Versions\' section, another update upgrade request not completed'
  371. }
  372. ],
  373. mock = {
  374. callback: Em.K,
  375. loadUpgradeData: function () {
  376. return {
  377. done: Em.K
  378. };
  379. }
  380. },
  381. appGetMock;
  382. beforeEach(function () {
  383. sinon.spy(mock, 'callback');
  384. sinon.spy(mock, 'loadUpgradeData');
  385. appGetMock = sinon.stub(App, 'get');
  386. });
  387. afterEach(function () {
  388. mock.callback.restore();
  389. mock.loadUpgradeData.restore();
  390. App.get.restore();
  391. appGetMock.restore();
  392. });
  393. cases.forEach(function (item) {
  394. describe(item.title, function () {
  395. beforeEach(function () {
  396. appGetMock.withArgs('router.mainAdminStackAndUpgradeController').returns(Em.Object.create({
  397. loadUpgradeData: mock.loadUpgradeData,
  398. isLoadUpgradeDataPending: item.isLoadUpgradeDataPending
  399. })).withArgs('wizardIsNotFinished').returns(item.wizardIsNotFinished)
  400. .withArgs('router.currentState.name').returns(item.currentStateName)
  401. .withArgs('router.currentState.parentState.name').returns(item.parentStateName);
  402. controller.updateUpgradeState(mock.callback);
  403. });
  404. it('loadUpgradeData is called ' + item.loadUpgradeDataCallCount + ' times', function () {
  405. expect(mock.loadUpgradeData.callCount).to.equal(item.loadUpgradeDataCallCount);
  406. });
  407. it('callback is called ' + item.callbackCallCount + ' times', function () {
  408. expect(mock.callback.callCount).to.equal(item.callbackCallCount);
  409. });
  410. });
  411. });
  412. });
  413. describe('#computeParameters', function () {
  414. Em.A([
  415. {
  416. q: [{
  417. type: 'EQUAL',
  418. key: 'k',
  419. value: [1, 2]
  420. }],
  421. result: 'k.in(1,2)'
  422. },
  423. {
  424. q: [{
  425. type: 'MULTIPLE',
  426. key: 'k',
  427. value: [1, 2]
  428. }],
  429. result: 'k.in(1,2)'
  430. },
  431. {
  432. q: [{
  433. type: 'EQUAL',
  434. key: 'k',
  435. value: 1
  436. }],
  437. result: 'k=1'
  438. },
  439. {
  440. q: [
  441. {
  442. type: 'LESS',
  443. key: 'k',
  444. value: '1'
  445. }
  446. ],
  447. result: 'k<1'
  448. },
  449. {
  450. q: [
  451. {
  452. type: 'MORE',
  453. key: 'k',
  454. value: '1'
  455. }
  456. ],
  457. result: 'k>1'
  458. },
  459. {
  460. q: [
  461. {
  462. type: 'SORT',
  463. key: 'k',
  464. value: 'f'
  465. }
  466. ],
  467. result: 'sortBy=k.f'
  468. },
  469. {
  470. q: [
  471. {
  472. type: 'MATCH',
  473. key: 'k',
  474. value: 'abc'
  475. }
  476. ],
  477. result: 'k.matches(abc)'
  478. },
  479. {
  480. q: [
  481. {
  482. type: 'MATCH',
  483. key: 'k',
  484. value: ['a', 'b', 'c']
  485. }
  486. ],
  487. result: '(k.matches(a)|k.matches(b)|k.matches(c))'
  488. },
  489. {
  490. q: [
  491. {type: 'EQUAL', key: 'k1', value: [1,2]},
  492. {type: 'EQUAL', key: 'k2', value: 'abc'},
  493. {type: 'LESS', key: 'k3', value: 1},
  494. {type: 'MORE', key: 'k4', value: 1},
  495. {type: 'MATCH', key: 'k5', value: ['a', 'b', 'c']}
  496. ],
  497. result: 'k1.in(1,2)&k2=abc&k3<1&k4>1&(k5.matches(a)|k5.matches(b)|k5.matches(c))'
  498. }
  499. ]).forEach(function (test, index) {
  500. it('test#' + index, function () {
  501. var result = c.computeParameters(test.q);
  502. expect(result).to.be.equal(test.result);
  503. });
  504. });
  505. });
  506. });