workflow.models.js 14 KB

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