workflow.models.js 15 KB

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