workflow.models.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. // Since knockout maps arrays without calling "update" nor "create"
  17. // Provide a JSON string that will be parsed in custom 'create' and 'update' functions.
  18. // These serialized values are also stored in the backend.
  19. var MODEL_FIELDS_JSON = ['parameters', 'job_properties', 'files', 'archives', 'prepares', 'params',
  20. 'deletes', 'mkdirs', 'moves', 'chmods', 'touchzs'];
  21. var DEFAULT_SLA = [
  22. {'key': 'enabled', 'value': false},
  23. {'key': 'nominal-time', 'value': ''},
  24. {'key': 'should-start', 'value': ''},
  25. {'key': 'should-end', 'value': ''},
  26. {'key': 'max-duration', 'value': ''},
  27. {'key': 'alert-events', 'value': ''},
  28. {'key': 'alert-contact', 'value': ''},
  29. {'key': 'notification-msg', 'value': ''},
  30. {'key': 'upstream-apps', 'value': ''}
  31. ];
  32. function getDefaultSla() {
  33. return jQuery.extend(true, [], DEFAULT_SLA);
  34. }
  35. function normalize_model_fields(node_model) {
  36. $.each(MODEL_FIELDS_JSON, function(index, field) {
  37. if (field in node_model && $.isArray(node_model[field])) {
  38. node_model[field] = JSON.stringify(node_model[field]);
  39. }
  40. });
  41. return node_model;
  42. }
  43. // Parse JSON if it is JSON and appropriately map.
  44. // Apply subscriber to each mapping.
  45. var map_params = function(options, subscribe) {
  46. options.data = ($.type(options.data) == "string") ? $.parseJSON(options.data) : options.data;
  47. if ($.isArray(options.data)) {
  48. var mapping = ko.mapping.fromJS(options.data);
  49. $.each(mapping(), function(index, value) {
  50. subscribe(value);
  51. });
  52. return mapping;
  53. } else {
  54. var mapping = ko.mapping.fromJS(options.data, {});
  55. subscribe(mapping);
  56. return mapping;
  57. }
  58. };
  59. // Maps JSON strings to fields in the view model.
  60. var MAPPING_OPTIONS = {
  61. ignore: ['initialize', 'toString', 'copy', 'sla'], // Do not support cancel edit on SLA
  62. job_properties: {
  63. create: function(options) {
  64. var parent = options.parent;
  65. var subscribe = function(mapping) {
  66. mapping.name.subscribe(function(value) {
  67. parent.job_properties.valueHasMutated();
  68. });
  69. mapping.value.subscribe(function(value) {
  70. parent.job_properties.valueHasMutated();
  71. });
  72. };
  73. return map_params(options, subscribe);
  74. },
  75. update: function(options) {
  76. var parent = options.parent;
  77. var subscribe = function(mapping) {
  78. mapping.name.subscribe(function(value) {
  79. parent.job_properties.valueHasMutated();
  80. });
  81. mapping.value.subscribe(function(value) {
  82. parent.job_properties.valueHasMutated();
  83. });
  84. };
  85. return map_params(options, subscribe);
  86. }
  87. },
  88. files: {
  89. create: function(options) {
  90. return map_params(options, function() {});
  91. },
  92. update: function(options) {
  93. return map_params(options, function() {});
  94. }
  95. },
  96. archives: {
  97. create: function(options) {
  98. var parent = options.parent;
  99. var subscribe = function(mapping) {
  100. mapping.name.subscribe(function(value) {
  101. parent.archives.valueHasMutated();
  102. });
  103. mapping.dummy.subscribe(function(value) {
  104. parent.archives.valueHasMutated();
  105. });
  106. };
  107. return map_params(options, subscribe);
  108. },
  109. update: function(options) {
  110. var parent = options.parent;
  111. var subscribe = function(mapping) {
  112. mapping.name.subscribe(function(value) {
  113. parent.archives.valueHasMutated();
  114. });
  115. mapping.dummy.subscribe(function(value) {
  116. parent.archives.valueHasMutated();
  117. });
  118. };
  119. return map_params(options, subscribe);
  120. }
  121. },
  122. params: {
  123. create: function(options) {
  124. var parent = options.parent;
  125. var subscribe = function(mapping) {
  126. mapping.value.subscribe(function(value) {
  127. parent.params.valueHasMutated();
  128. });
  129. mapping.type.subscribe(function(value) {
  130. parent.params.valueHasMutated();
  131. });
  132. };
  133. return map_params(options, subscribe);
  134. },
  135. update: function(options) {
  136. var parent = options.parent;
  137. var subscribe = function(mapping) {
  138. mapping.value.subscribe(function(value) {
  139. parent.params.valueHasMutated();
  140. });
  141. mapping.type.subscribe(function(value) {
  142. parent.params.valueHasMutated();
  143. });
  144. };
  145. return map_params(options, subscribe);
  146. }
  147. },
  148. prepares: {
  149. create: function(options) {
  150. var parent = options.parent;
  151. var subscribe = function(mapping) {
  152. mapping.value.subscribe(function(value) {
  153. parent.prepares.valueHasMutated();
  154. });
  155. mapping.type.subscribe(function(value) {
  156. parent.prepares.valueHasMutated();
  157. });
  158. };
  159. return map_params(options, subscribe);
  160. },
  161. update: function(options) {
  162. var parent = options.parent;
  163. var subscribe = function(mapping) {
  164. mapping.value.subscribe(function(value) {
  165. parent.prepares.valueHasMutated();
  166. });
  167. mapping.type.subscribe(function(value) {
  168. parent.prepares.valueHasMutated();
  169. });
  170. };
  171. return map_params(options, subscribe);
  172. }
  173. },
  174. deletes: {
  175. create: function(options) {
  176. var parent = options.parent;
  177. var subscribe = function(mapping) {
  178. mapping.name.subscribe(function(value) {
  179. parent.deletes.valueHasMutated();
  180. });
  181. };
  182. return map_params(options, subscribe);
  183. },
  184. update: function(options) {
  185. var parent = options.parent;
  186. var subscribe = function(mapping) {
  187. mapping.name.subscribe(function(value) {
  188. parent.deletes.valueHasMutated();
  189. });
  190. };
  191. return map_params(options, subscribe);
  192. },
  193. },
  194. mkdirs: {
  195. create: function(options) {
  196. var parent = options.parent;
  197. var subscribe = function(mapping) {
  198. mapping.name.subscribe(function(value) {
  199. parent.mkdirs.valueHasMutated();
  200. });
  201. };
  202. return map_params(options, subscribe);
  203. },
  204. update: function(options) {
  205. var parent = options.parent;
  206. var subscribe = function(mapping) {
  207. mapping.name.subscribe(function(value) {
  208. parent.mkdirs.valueHasMutated();
  209. });
  210. };
  211. return map_params(options, subscribe);
  212. },
  213. },
  214. moves: {
  215. create: function(options) {
  216. var parent = options.parent;
  217. var subscribe = function(mapping) {
  218. mapping.source.subscribe(function(value) {
  219. parent.moves.valueHasMutated();
  220. });
  221. mapping.destination.subscribe(function(value) {
  222. parent.moves.valueHasMutated();
  223. });
  224. };
  225. return map_params(options, subscribe);
  226. },
  227. update: function(options) {
  228. var parent = options.parent;
  229. var subscribe = function(mapping) {
  230. mapping.source.subscribe(function(value) {
  231. parent.moves.valueHasMutated();
  232. });
  233. mapping.destination.subscribe(function(value) {
  234. parent.moves.valueHasMutated();
  235. });
  236. };
  237. return map_params(options, subscribe);
  238. }
  239. },
  240. chmods: {
  241. create: function(options) {
  242. var parent = options.parent;
  243. var subscribe = function(mapping) {
  244. mapping.path.subscribe(function(value) {
  245. parent.chmods.valueHasMutated();
  246. });
  247. mapping.permissions.subscribe(function(value) {
  248. parent.chmods.valueHasMutated();
  249. });
  250. mapping.recursive.subscribe(function(value) {
  251. parent.chmods.valueHasMutated();
  252. });
  253. };
  254. return map_params(options, subscribe);
  255. },
  256. update: function(options) {
  257. var parent = options.parent;
  258. var subscribe = function(mapping) {
  259. mapping.path.subscribe(function(value) {
  260. parent.chmods.valueHasMutated();
  261. });
  262. mapping.permissions.subscribe(function(value) {
  263. parent.chmods.valueHasMutated();
  264. });
  265. mapping.recursive.subscribe(function(value) {
  266. parent.chmods.valueHasMutated();
  267. });
  268. };
  269. return map_params(options, subscribe);
  270. },
  271. },
  272. touchzs: {
  273. create: function(options) {
  274. var parent = options.parent;
  275. var subscribe = function(mapping) {
  276. mapping.name.subscribe(function(value) {
  277. parent.touchzs.valueHasMutated();
  278. });
  279. };
  280. return map_params(options, subscribe);
  281. },
  282. update: function(options) {
  283. var parent = options.parent;
  284. var subscribe = function(mapping) {
  285. mapping.name.subscribe(function(value) {
  286. parent.touchzs.valueHasMutated();
  287. });
  288. };
  289. return map_params(options, subscribe);
  290. }
  291. }
  292. };
  293. var ModelModule = function($) {
  294. var module = function(attrs) {
  295. var self = this;
  296. $.extend(self, attrs);
  297. module.prototype.initialize.apply(self, arguments);
  298. return self;
  299. };
  300. $.extend(module.prototype, {
  301. // Normal stuff
  302. initialize: function(){},
  303. toString: function() {
  304. var self = this;
  305. return JSON.stringify(self, null, '\t');
  306. },
  307. copy: function() {
  308. var self = this;
  309. var model = $.extend(true, {}, self);
  310. $.each(MODEL_FIELDS_JSON, function(i, field) {
  311. if (field in model && $.type(model[field]) != "string") {
  312. model[field] = JSON.stringify(model[field]);
  313. }
  314. });
  315. return model;
  316. }
  317. });
  318. return module;
  319. };
  320. var WorkflowModel = ModelModule($);
  321. $.extend(WorkflowModel.prototype, {
  322. id: 0,
  323. name: '',
  324. description: '',
  325. start: 0,
  326. end: 0,
  327. schema_version: 0.4,
  328. deployment_dir: '',
  329. is_shared: true,
  330. parameters: '[]',
  331. job_xml: '',
  332. sla: getDefaultSla()
  333. });
  334. var NodeModel = ModelModule($);
  335. $.extend(NodeModel.prototype, {
  336. id: 0,
  337. name: '',
  338. description: '',
  339. node_type: '',
  340. workflow: 0,
  341. child_links: []
  342. });
  343. var ForkModel = ModelModule($);
  344. $.extend(ForkModel.prototype, {
  345. id: 0,
  346. name: '',
  347. description: '',
  348. node_type: 'fork',
  349. workflow: 0,
  350. child_links: []
  351. });
  352. var DecisionModel = ModelModule($);
  353. $.extend(DecisionModel.prototype, {
  354. id: 0,
  355. name: '',
  356. description: '',
  357. node_type: 'decision',
  358. workflow: 0,
  359. child_links: []
  360. });
  361. var DistCPModel = ModelModule($);
  362. $.extend(DistCPModel.prototype, {
  363. id: 0,
  364. name: '',
  365. description: '',
  366. node_type: 'distcp',
  367. workflow: 0,
  368. job_properties: '[]',
  369. prepares: '[]',
  370. job_xml: '',
  371. params: '[]',
  372. child_links: [],
  373. sla: getDefaultSla()
  374. });
  375. var MapReduceModel = ModelModule($);
  376. $.extend(MapReduceModel.prototype, {
  377. id: 0,
  378. name: '',
  379. description: '',
  380. node_type: 'mapreduce',
  381. workflow: 0,
  382. files: '[]',
  383. archives: '[]',
  384. job_properties: '[]',
  385. jar_path: '',
  386. prepares: '[]',
  387. job_xml: '',
  388. child_links: [],
  389. sla: getDefaultSla()
  390. });
  391. var StreamingModel = ModelModule($);
  392. $.extend(StreamingModel.prototype, {
  393. id: 0,
  394. name: '',
  395. description: '',
  396. node_type: 'streaming',
  397. workflow: 0,
  398. files: '[]',
  399. archives: '[]',
  400. job_properties: '[]',
  401. mapper: '',
  402. reducer: '',
  403. child_links: [],
  404. sla: getDefaultSla()
  405. });
  406. var JavaModel = ModelModule($);
  407. $.extend(JavaModel.prototype, {
  408. id: 0,
  409. name: '',
  410. description: '',
  411. node_type: 'java',
  412. workflow: 0,
  413. files: '[]',
  414. archives: '[]',
  415. job_properties: '[]',
  416. jar_path: '',
  417. prepares: '[]',
  418. job_xml: '',
  419. main_class: '',
  420. args: '',
  421. java_opts: '',
  422. capture_output: false,
  423. child_links: [],
  424. sla: getDefaultSla()
  425. });
  426. var PigModel = ModelModule($);
  427. $.extend(PigModel.prototype, {
  428. id: 0,
  429. name: '',
  430. description: '',
  431. node_type: 'pig',
  432. workflow: 0,
  433. files: '[]',
  434. archives: '[]',
  435. job_properties: '[]',
  436. prepares: '[]',
  437. job_xml: '',
  438. params: '[]',
  439. script_path: '',
  440. child_links: [],
  441. sla: getDefaultSla()
  442. });
  443. var HiveModel = ModelModule($);
  444. $.extend(HiveModel.prototype, {
  445. id: 0,
  446. name: '',
  447. description: '',
  448. node_type: 'hive',
  449. workflow: 0,
  450. files: '[]',
  451. archives: '[]',
  452. job_properties: '[]',
  453. prepares: '[]',
  454. job_xml: '',
  455. params: '[]',
  456. script_path: '',
  457. child_links: [],
  458. sla: getDefaultSla()
  459. });
  460. var SqoopModel = ModelModule($);
  461. $.extend(SqoopModel.prototype, {
  462. id: 0,
  463. name: '',
  464. description: '',
  465. node_type: 'sqoop',
  466. workflow: 0,
  467. files: '[]',
  468. archives: '[]',
  469. job_properties: '[]',
  470. prepares: '[]',
  471. job_xml: '',
  472. params: '[]',
  473. script_path: '',
  474. child_links: [],
  475. sla: getDefaultSla()
  476. });
  477. var ShellModel = ModelModule($);
  478. $.extend(ShellModel.prototype, {
  479. id: 0,
  480. name: '',
  481. description: '',
  482. node_type: 'shell',
  483. workflow: 0,
  484. files: '[]',
  485. archives: '[]',
  486. job_properties: '[]',
  487. prepares: '[]',
  488. job_xml: '',
  489. params: '[]',
  490. command: '',
  491. capture_output: false,
  492. child_links: [],
  493. sla: getDefaultSla()
  494. });
  495. var SshModel = ModelModule($);
  496. $.extend(SshModel.prototype, {
  497. id: 0,
  498. name: '',
  499. description: '',
  500. node_type: 'ssh',
  501. workflow: 0,
  502. user: '',
  503. host: '',
  504. params: '[]',
  505. command: '',
  506. capture_output: false,
  507. child_links: [],
  508. sla: getDefaultSla()
  509. });
  510. var FsModel = ModelModule($);
  511. $.extend(FsModel.prototype, {
  512. id: 0,
  513. name: '',
  514. description: '',
  515. node_type: 'fs',
  516. workflow: 0,
  517. deletes: '[]',
  518. mkdirs: '[]',
  519. moves: '[]',
  520. chmods: '[]',
  521. touchzs: '[]',
  522. child_links: [],
  523. sla: getDefaultSla()
  524. });
  525. var EmailModel = ModelModule($);
  526. $.extend(EmailModel.prototype, {
  527. id: 0,
  528. name: '',
  529. description: '',
  530. node_type: 'email',
  531. workflow: 0,
  532. to: '',
  533. cc: '',
  534. subject: '',
  535. body: '',
  536. child_links: [],
  537. sla: getDefaultSla()
  538. });
  539. var SubWorkflowModel = ModelModule($);
  540. $.extend(SubWorkflowModel.prototype, {
  541. id: 0,
  542. name: '',
  543. description: '',
  544. node_type: 'subworkflow',
  545. workflow: 0,
  546. sub_workflow: 0,
  547. propagate_configuration: true,
  548. job_properties: '[]',
  549. child_links: [],
  550. sla: getDefaultSla()
  551. });
  552. var GenericModel = ModelModule($);
  553. $.extend(GenericModel.prototype, {
  554. id: 0,
  555. name: '',
  556. description: '',
  557. node_type: 'generic',
  558. workflow: 0,
  559. xml: '',
  560. child_links: []
  561. });
  562. function nodeModelChooser(node_type) {
  563. switch(node_type) {
  564. case 'mapreduce':
  565. return MapReduceModel;
  566. case 'streaming':
  567. return StreamingModel;
  568. case 'java':
  569. return JavaModel;
  570. case 'pig':
  571. return PigModel;
  572. case 'hive':
  573. return HiveModel;
  574. case 'sqoop':
  575. return SqoopModel;
  576. case 'shell':
  577. return ShellModel;
  578. case 'ssh':
  579. return SshModel;
  580. case 'distcp':
  581. return DistCPModel;
  582. case 'fs':
  583. return FsModel;
  584. case 'email':
  585. return EmailModel;
  586. case 'subworkflow':
  587. return SubWorkflowModel;
  588. case 'generic':
  589. return GenericModel;
  590. case 'fork':
  591. return ForkModel;
  592. case 'decision':
  593. return DecisionModel;
  594. default:
  595. return NodeModel;
  596. }
  597. }