Browse Source

HUE-983 [oozie] Coordinator could support previous dates

Support dataset formats:
 - 'default' that corresponds to date 0.
 - 'single' that corresponds to a selectable unique date.
 - 'range' that corresponds to a range of date.

All these formats can be set by from an integer or some verbatim Oozie EL functions.

Adding tests. Dynamic UI.

Fix HUE-987 [oozie] Coordinator name and start date conflicts with same dataset attributes
Romain Rigaux 13 years ago
parent
commit
22369d5

+ 8 - 8
apps/oozie/src/oozie/migrations/0014_auto__add_decisionend.py

@@ -5,22 +5,22 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
-        
+
         # Adding model 'DecisionEnd'
         db.create_table('oozie_decisionend', (
             ('node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['oozie.Node'], unique=True, primary_key=True)),
         ))
         db.send_create_signal('oozie', ['DecisionEnd'])
-    
-    
+
+
     def backwards(self, orm):
-        
+
         # Deleting model 'DecisionEnd'
         db.delete_table('oozie_decisionend')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -299,5 +299,5 @@ class Migration(SchemaMigration):
             'start': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'start_workflow'", 'null': 'True', 'to': "orm['oozie.Start']"})
         }
     }
-    
+
     complete_apps = ['oozie']

+ 315 - 0
apps/oozie/src/oozie/migrations/0015_auto__add_field_dataset_advanced_start_instance__add_field_dataset_ins.py

@@ -0,0 +1,315 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+
+        # Adding field 'Dataset.advanced_start_instance'
+        db.add_column('oozie_dataset', 'advanced_start_instance', self.gf('django.db.models.fields.CharField')(default='0', max_length=128), keep_default=False)
+
+        # Adding field 'Dataset.instance_choice'
+        db.add_column('oozie_dataset', 'instance_choice', self.gf('django.db.models.fields.CharField')(default='default', max_length=10), keep_default=False)
+
+        # Adding field 'Dataset.advanced_end_instance'
+        db.add_column('oozie_dataset', 'advanced_end_instance', self.gf('django.db.models.fields.CharField')(default='0', max_length=128, blank=True), keep_default=False)
+
+
+    def backwards(self, orm):
+
+        # Deleting field 'Dataset.advanced_start_instance'
+        db.delete_column('oozie_dataset', 'advanced_start_instance')
+
+        # Deleting field 'Dataset.instance_choice'
+        db.delete_column('oozie_dataset', 'instance_choice')
+
+        # Deleting field 'Dataset.advanced_end_instance'
+        db.delete_column('oozie_dataset', 'advanced_end_instance')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'oozie.coordinator': {
+            'Meta': {'object_name': 'Coordinator', '_ormbases': ['oozie.Job']},
+            'concurrency': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'end': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 1, 6, 19, 26, 33, 676504)'}),
+            'execution': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'frequency_number': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+            'frequency_unit': ('django.db.models.fields.CharField', [], {'default': "'days'", 'max_length': '20'}),
+            'job_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Job']", 'unique': 'True', 'primary_key': 'True'}),
+            'start': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 1, 3, 19, 26, 33, 676468)'}),
+            'throttle': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'timeout': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'timezone': ('django.db.models.fields.CharField', [], {'default': "'America/Los_Angeles'", 'max_length': '24'}),
+            'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Workflow']", 'null': 'True'})
+        },
+        'oozie.datainput': {
+            'Meta': {'object_name': 'DataInput'},
+            'coordinator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Coordinator']"}),
+            'dataset': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Dataset']", 'unique': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'})
+        },
+        'oozie.dataoutput': {
+            'Meta': {'object_name': 'DataOutput'},
+            'coordinator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Coordinator']"}),
+            'dataset': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Dataset']", 'unique': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'})
+        },
+        'oozie.dataset': {
+            'Meta': {'object_name': 'Dataset'},
+            'advanced_end_instance': ('django.db.models.fields.CharField', [], {'default': "'0'", 'max_length': '128', 'blank': 'True'}),
+            'advanced_start_instance': ('django.db.models.fields.CharField', [], {'default': "'0'", 'max_length': '128'}),
+            'coordinator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Coordinator']"}),
+            'description': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
+            'done_flag': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64', 'blank': 'True'}),
+            'frequency_number': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+            'frequency_unit': ('django.db.models.fields.CharField', [], {'default': "'days'", 'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'instance_choice': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '10'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'start': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 1, 3, 19, 26, 33, 677121)'}),
+            'timezone': ('django.db.models.fields.CharField', [], {'default': "'America/Los_Angeles'", 'max_length': '24'}),
+            'uri': ('django.db.models.fields.CharField', [], {'default': "'/data/${YEAR}${MONTH}${DAY}'", 'max_length': '1024'})
+        },
+        'oozie.decision': {
+            'Meta': {'object_name': 'Decision'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.decisionend': {
+            'Meta': {'object_name': 'DecisionEnd'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.distcp': {
+            'Meta': {'object_name': 'DistCp'},
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"})
+        },
+        'oozie.email': {
+            'Meta': {'object_name': 'Email'},
+            'body': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'cc': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'subject': ('django.db.models.fields.TextField', [], {'default': "''"}),
+            'to': ('django.db.models.fields.TextField', [], {'default': "''"})
+        },
+        'oozie.end': {
+            'Meta': {'object_name': 'End'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.fork': {
+            'Meta': {'object_name': 'Fork'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.fs': {
+            'Meta': {'object_name': 'Fs'},
+            'chmods': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}),
+            'deletes': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}),
+            'mkdirs': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}),
+            'moves': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'touchzs': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'})
+        },
+        'oozie.generic': {
+            'Meta': {'object_name': 'Generic'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'xml': ('django.db.models.fields.TextField', [], {'default': "''"})
+        },
+        'oozie.history': {
+            'Meta': {'object_name': 'History'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'job': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Job']"}),
+            'oozie_job_id': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'properties': ('django.db.models.fields.TextField', [], {}),
+            'submission_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'submitter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+        },
+        'oozie.hive': {
+            'Meta': {'object_name': 'Hive'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': '\'[{"name":"oozie.hive.defaults","value":"hive-site.xml"}]\''}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'script_path': ('django.db.models.fields.CharField', [], {'max_length': '256'})
+        },
+        'oozie.java': {
+            'Meta': {'object_name': 'Java'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'args': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'blank': 'True'}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'jar_path': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'java_opts': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'main_class': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"})
+        },
+        'oozie.job': {
+            'Meta': {'object_name': 'Job'},
+            'deployment_dir': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_shared': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
+            'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'parameters': ('django.db.models.fields.TextField', [], {'default': '\'[{"name":"oozie.use.system.libpath","value":"true"}]\''}),
+            'schema_version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
+        },
+        'oozie.join': {
+            'Meta': {'object_name': 'Join'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.kill': {
+            'Meta': {'object_name': 'Kill'},
+            'message': ('django.db.models.fields.CharField', [], {'default': "'Action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]'", 'max_length': '256'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'})
+        },
+        'oozie.link': {
+            'Meta': {'object_name': 'Link'},
+            'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parent_node'", 'to': "orm['oozie.Node']"}),
+            'comment': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'child_node'", 'to': "orm['oozie.Node']"})
+        },
+        'oozie.mapreduce': {
+            'Meta': {'object_name': 'Mapreduce'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'jar_path': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True'}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"})
+        },
+        'oozie.node': {
+            'Meta': {'object_name': 'Node'},
+            'children': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'parents'", 'symmetrical': 'False', 'through': "orm['oozie.Link']", 'to': "orm['oozie.Node']"}),
+            'description': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'node_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Workflow']"})
+        },
+        'oozie.pig': {
+            'Meta': {'object_name': 'Pig'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'script_path': ('django.db.models.fields.CharField', [], {'max_length': '256'})
+        },
+        'oozie.shell': {
+            'Meta': {'object_name': 'Shell'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'capture_output': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'command': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"})
+        },
+        'oozie.sqoop': {
+            'Meta': {'object_name': 'Sqoop'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'prepares': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'script_path': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'})
+        },
+        'oozie.ssh': {
+            'Meta': {'object_name': 'Ssh'},
+            'capture_output': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'command': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+            'host': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'params': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'user': ('django.db.models.fields.CharField', [], {'max_length': '64'})
+        },
+        'oozie.start': {
+            'Meta': {'object_name': 'Start'},
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True'})
+        },
+        'oozie.streaming': {
+            'Meta': {'object_name': 'Streaming'},
+            'archives': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'files': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'mapper': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'reducer': ('django.db.models.fields.CharField', [], {'max_length': '512'})
+        },
+        'oozie.subworkflow': {
+            'Meta': {'object_name': 'SubWorkflow'},
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Node']", 'unique': 'True', 'primary_key': 'True'}),
+            'propagate_configuration': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'sub_workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['oozie.Workflow']"})
+        },
+        'oozie.workflow': {
+            'Meta': {'object_name': 'Workflow', '_ormbases': ['oozie.Job']},
+            'end': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'end_workflow'", 'null': 'True', 'to': "orm['oozie.End']"}),
+            'is_single': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'job_properties': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+            'job_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['oozie.Job']", 'unique': 'True', 'primary_key': 'True'}),
+            'job_xml': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
+            'start': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'start_workflow'", 'null': 'True', 'to': "orm['oozie.Start']"})
+        }
+    }
+
+    complete_apps = ['oozie']

+ 39 - 1
apps/oozie/src/oozie/models.py

@@ -1118,7 +1118,7 @@ DATASET_FREQUENCY = ['MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR']
 
 class Coordinator(Job):
   """
-  http://incubator.apache.org/oozie/docs/3.2.0-incubating/docs/CoordinatorFunctionalSpec.html
+  http://oozie.apache.org/docs/3.3.0/CoordinatorFunctionalSpec.html
   """
   frequency_number = models.SmallIntegerField(default=1, choices=FREQUENCY_NUMBERS, verbose_name=_t('Frequency number'),
                                               help_text=_t('The number of units of the rate at which '
@@ -1267,6 +1267,9 @@ class DatasetManager(models.Manager):
 
 
 class Dataset(models.Model):
+  """
+  http://oozie.apache.org/docs/3.3.0/CoordinatorFunctionalSpec.html#a6.3._Synchronous_Coordinator_Application_Definition
+  """
   name = models.CharField(max_length=40, validators=[name_validator], verbose_name=_t('Name'),
                           help_text=_t('The name of the dataset.'))
   description = models.CharField(max_length=1024, blank=True, default='', verbose_name=_t('Description'),
@@ -1291,6 +1294,12 @@ class Dataset(models.Model):
                                             'flag is set to empty, then Coordinator looks for the existence of the directory itself.'))
   coordinator = models.ForeignKey(Coordinator, verbose_name=_t('Coordinator'),
                                   help_text=_t('The coordinator associated with this data.'))
+  instance_choice = models.CharField(max_length=10, default='default', verbose_name=_t('Instance type'),
+                               help_text=_t('Customize the date instance(s), e.g. define a range of dates, use EL functions...'))
+  advanced_start_instance  = models.CharField(max_length=128, default='0', verbose_name=_t('Start instance'),
+                               help_text=_t('Shift the frequency for gettting past/future start date or enter verbatim the Oozie start instance, e.g. ${coord:current(0)}'))
+  advanced_end_instance  = models.CharField(max_length=128, blank=True, default='0', verbose_name=_t('End instance'),
+                               help_text=_t('Optional: shift the frequency for gettting past/future end dates or enter verbatim the Oozie end instance'))
 
   objects = DatasetManager()
   unique_together = ('coordinator', 'name')
@@ -1310,6 +1319,35 @@ class Dataset(models.Model):
   def text_frequency(self):
     return '%(number)d %(unit)s' % {'unit': self.frequency_unit, 'number': self.frequency_number}
 
+  @property
+  def start_instance(self):
+    if not self.is_advanced_start_instance:
+      return int(self.advanced_start_instance)
+    else:
+      return 0
+
+  @property
+  def is_advanced_start_instance(self):
+    return not self.is_int(self.advanced_start_instance)
+
+  def is_int(self, text):
+    try:
+      int(text)
+      return True
+    except ValueError:
+      return False
+
+  @property
+  def end_instance(self):
+    if not self.is_advanced_end_instance:
+      return int(self.advanced_end_instance)
+    else:
+      return 0
+
+  @property
+  def is_advanced_end_instance(self):
+    return not self.is_int(self.advanced_end_instance)
+
 
 class DataInput(models.Model):
   name = models.CharField(max_length=40, validators=[name_validator], verbose_name=_t('Name of an input variable in the workflow.'),

+ 0 - 1
apps/oozie/src/oozie/templates/editor/coordinator_properties.mako

@@ -63,7 +63,6 @@
 </%def>
 
 <%def name="init_viewmodel(element, initial_value)">
-
   <script type="text/javascript">
     $(document).ready(function(){
       var ViewModel = function(${ element }) {

+ 1 - 1
apps/oozie/src/oozie/templates/editor/create_coordinator.mako

@@ -79,7 +79,7 @@ ${ layout.menubar(section='coordinators') }
               ${ coordinator_form['parameters'] }
               <div class="hide">
                 ${ utils.render_field(coordinator_form['timeout']) }
-                     ${ coordinator_form['schema_version'] }
+                ${ coordinator_form['schema_version'] }
               </div>
             </div>
           </div>

+ 4 - 1
apps/oozie/src/oozie/templates/editor/create_coordinator_dataset.mako

@@ -27,6 +27,7 @@
   ${ utils.render_field_no_popover(dataset_form['name']) }
   ${ utils.render_field_no_popover(dataset_form['description']) }
   ${ utils.render_field_no_popover(dataset_form['start']) }
+
   <div class="row-fluid">
     <div class="span6">
       ${ utils.render_field_no_popover(dataset_form['frequency_number']) }
@@ -48,6 +49,8 @@
   </div>
   ${ utils.render_field_no_popover(dataset_form['uri']) }
 
+  <%include file="dataset_utils.mako" args="base_id='#id_create-'"/>
+
   ${ utils.render_field_no_popover(dataset_form['timezone']) }
   ${ utils.render_field_no_popover(dataset_form['done_flag']) }
-</fieldset>
+</fieldset>

+ 115 - 0
apps/oozie/src/oozie/templates/editor/dataset_utils.mako

@@ -0,0 +1,115 @@
+## Licensed to Cloudera, Inc. under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  Cloudera, Inc. licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+
+## How to use:
+## <%include file="dataset_utils.mako"/>
+## <%include file="dataset_utils.mako" args="base_id='#id_create-'"/>
+
+<%page args="base_id='#id_edit-'"/>
+
+
+<div class="control-group">
+  <label class="control-label">Instance</label>
+  <div class="controls">
+      <div class="btn-group" data-toggle="buttons-radio">
+          <button id="default-btn" type="button" class="btn" data-bind="click: setDefault, css: { active: instance_choice() == 'default' }">Default</button>
+          <button id="single-btn" type="button" class="btn" data-bind="click: setSingle, css: { active: instance_choice() == 'single' }">Single</button>
+          <button id="range-btn" type="button" class="btn" data-bind="click: setRange, css: { active: instance_choice() == 'range' }">Range</button>
+      </div>
+      <span class="help-block">${ dataset_form['instance_choice'].help_text }</span>
+
+      <div data-bind="visible: $.inArray(instance_choice(), ['single', 'range']) != -1">
+          <span class="span1">Start</span>
+          <input name="instance_start" type="number" data-bind="value: start_instance, enable: ! is_advanced_start_instance()"/>
+          <label style="display: inline">
+              &nbsp;
+              <input type="checkbox" data-bind="checked: is_advanced_start_instance">
+              (advanced)
+          </label>
+          <input type="text" data-bind="value: advanced_start_instance, visible: is_advanced_start_instance()" class="span4"/>
+          <span class="help-block">${ dataset_form['advanced_start_instance'].help_text }</span>
+      </div>
+      <div data-bind="visible: instance_choice() == 'range'">
+          <span class="span1">End</span>
+          <input name="instance_end" type="number" data-bind="value: end_instance, enable: ! is_advanced_end_instance()" />
+          <label style="display: inline">
+              &nbsp;
+              <input type="checkbox" data-bind="checked: is_advanced_end_instance">
+              (advanced)
+          </label>
+          <input type="text" data-bind="value: advanced_end_instance, visible: is_advanced_end_instance()" class="span4"/>
+          <span class="help-block">${ dataset_form['advanced_end_instance'].help_text }</span>
+      </div>
+  </div>
+</div>
+
+<div class="hide">
+    ${ dataset_form['instance_choice'] }
+    ${ dataset_form['advanced_start_instance'] }
+    ${ dataset_form['advanced_end_instance'] }
+</div>
+
+<script type="text/javascript">
+  $(document).ready(function(){
+    window.viewModel.updateInstance = function() {
+      $("${ base_id }instance_choice").val(window.viewModel.instance_choice());
+
+      if (window.viewModel.is_advanced_start_instance()) {
+        $("${ base_id }advanced_start_instance").val(window.viewModel.advanced_start_instance());
+      } else {
+        $("${ base_id }advanced_start_instance").val(window.viewModel.start_instance());
+      }
+
+      if (window.viewModel.is_advanced_end_instance()) {
+        $("${ base_id }advanced_end_instance").val(window.viewModel.advanced_end_instance());
+      } else {
+        $("${ base_id }advanced_end_instance").val(window.viewModel.end_instance());
+      }
+    }
+
+    window.viewModel.instance_choice = ko.observable('${ dataset.instance_choice }');
+
+    window.viewModel.start_instance = ko.observable(${ dataset.start_instance });
+    window.viewModel.advanced_start_instance = ko.observable('${ (dataset.is_advanced_start_instance and dataset.advanced_start_instance) or "${coord:current(%s)}" % dataset.start_instance }');
+    window.viewModel.is_advanced_start_instance = ko.observable(${ dataset.is_advanced_start_instance and 'true' or 'false' });
+
+    window.viewModel.end_instance = ko.observable(${ dataset.end_instance });
+    window.viewModel.advanced_end_instance = ko.observable('${ (dataset.is_advanced_end_instance and dataset.advanced_end_instance) or "${coord:current(%s)}" % dataset.end_instance }');
+    window.viewModel.is_advanced_end_instance = ko.observable(${ dataset.is_advanced_end_instance and 'true' or 'false' });
+
+
+    window.viewModel.setDefault = function() {
+      window.viewModel.instance_choice('default');
+    };
+    window.viewModel.setSingle = function() {
+      window.viewModel.instance_choice('single');
+    };
+    window.viewModel.setRange = function() {
+      window.viewModel.instance_choice('range');
+    };
+
+    window.viewModel.reset = function() {
+      window.viewModel.instance_choice('default');
+      window.viewModel.start_instance('0');
+      window.viewModel.advanced_start_instance('${"${"}coord:current(0)}');
+      window.viewModel.is_advanced_start_instance(false);
+      window.viewModel.end_instance('0');
+      window.viewModel.advanced_end_instance('${"${"}coord:current(0)}');
+      window.viewModel.is_advanced_end_instance(false);
+    }
+  });
+</script>

+ 6 - 4
apps/oozie/src/oozie/templates/editor/edit_coordinator.mako

@@ -408,10 +408,8 @@ ${ layout.menubar(section='coordinators') }
 
 
 % if coordinator.id:
-
   <div class="modal hide" id="edit-dataset-modal" style="z-index:1500;width:850px"></div>
 
-
   <style type="text/css">
     .delete-row input {
       display: none;
@@ -478,6 +476,7 @@ ${ layout.menubar(section='coordinators') }
 
       $('#add-dataset-btn').click(function () {
         $("#add-dataset-form").empty();
+        window.viewModel.updateInstance();
         $("#add-dataset-body").find("input, select").each(function () {
           $(this).clone().appendTo($("#add-dataset-form"));
         });
@@ -488,6 +487,7 @@ ${ layout.menubar(section='coordinators') }
                     $("#add-dataset-form").empty();
                     $('#add-dataset-body').html(response['data']);
                     decorateDateTime();
+                    ko.applyBindings(window.viewModel);
                   } else {
                     window.location.replace(response['data']);
                     window.location.reload();
@@ -508,6 +508,7 @@ ${ layout.menubar(section='coordinators') }
           success:function (response) {
             $("#edit-dataset-body").html(response['data']);
             decorateDateTime();
+            ko.applyBindings(window.viewModel);
             routie("editDataset");
           }
         });
@@ -515,6 +516,7 @@ ${ layout.menubar(section='coordinators') }
 
       $('#update-dataset-btn').click(function () {
         $("#edit-dataset-form").empty();
+        window.viewModel.updateInstance();
         $("#edit-dataset-body").find("input, select").each(function () {
           $(this).clone().appendTo($("#edit-dataset-form"));
         });
@@ -599,6 +601,7 @@ ${ layout.menubar(section='coordinators') }
           showSection("steps");
         },
         "createDataset":function () {
+          window.viewModel.reset();
           showSection("createDataset");
         },
         "editDataset":function () {
@@ -689,10 +692,9 @@ ${ layout.menubar(section='coordinators') }
       });
     });
   </script>
-
 % endif
 
 
 ${ utils.decorate_datetime_fields() }
 
-${ commonfooter(messages) }
+${ commonfooter(messages) }

+ 32 - 28
apps/oozie/src/oozie/templates/editor/edit_coordinator_dataset.mako

@@ -21,31 +21,35 @@
 
 
 <%namespace name="utils" file="../utils.inc.mako" />
-    <fieldset>
-      ${ utils.render_field(dataset_form['name']) }
-      ${ utils.render_field(dataset_form['description']) }
-      ${ utils.render_field(dataset_form['start']) }
-      <div class="row-fluid">
-        <div class="span6">
-          ${ utils.render_field(dataset_form['frequency_number']) }
-        </div>
-        <div class="span6">
-          ${ utils.render_field(dataset_form['frequency_unit']) }
-        </div>
-      </div>
-
-      <div class="alert alert-info">
-        ${ _('You can parameterize the values using') }
-        % for frequency in DATASET_FREQUENCY:
-          <code>${"${"}${ frequency }}</code>
-          % if not loop.last:
-            ,
-          % endif
-        % endfor
-        .
-      </div>
-      ${ utils.render_field(dataset_form['uri']) }
-
-      ${ utils.render_field(dataset_form['timezone']) }
-      ${ utils.render_field(dataset_form['done_flag']) }
-    </fieldset>
+
+
+<fieldset>
+  ${ utils.render_field(dataset_form['name']) }
+  ${ utils.render_field(dataset_form['description']) }
+  ${ utils.render_field(dataset_form['start']) }
+  <div class="row-fluid">
+    <div class="span6">
+      ${ utils.render_field(dataset_form['frequency_number']) }
+    </div>
+    <div class="span6">
+      ${ utils.render_field(dataset_form['frequency_unit']) }
+    </div>
+  </div>
+
+  <div class="alert alert-info">
+    ${ _('You can parameterize the values using') }
+    % for frequency in DATASET_FREQUENCY:
+      <code>${"${"}${ frequency }}</code>
+      % if not loop.last:
+        ,
+      % endif
+    % endfor
+    .
+  </div>
+  ${ utils.render_field(dataset_form['uri']) }
+
+  <%include file="dataset_utils.mako"/>
+
+  ${ utils.render_field(dataset_form['timezone']) }
+  ${ utils.render_field(dataset_form['done_flag']) }
+</fieldset>

+ 28 - 2
apps/oozie/src/oozie/templates/editor/gen/coordinator.xml.mako

@@ -15,6 +15,32 @@
 ## limitations under the License.
 
 
+<%def name="render_dataset_instance(dataset)">
+  % if dataset.instance_choice in ('default', 'single'):
+    % if not dataset.is_advanced_start_instance:
+      <instance>${ '${'}coord:current(${ dataset.start_instance })}</instance>
+    % else:
+      <instance>${ dataset.advanced_start_instance }</instance>
+    % endif
+  % else:
+    <start-instance>
+      % if not dataset.is_advanced_start_instance:
+        ${ '${'}coord:current(${ dataset.start_instance })}
+      % else:
+        ${ dataset.advanced_start_instance }
+      % endif
+    </start-instance>
+    <end-instance>
+      % if not dataset.is_advanced_end_instance:
+        ${ '${'}coord:current(${ dataset.end_instance })}
+      % else:
+        ${ dataset.advanced_end_instance }
+      % endif
+    </end-instance>
+  % endif
+</%def>
+
+
 <coordinator-app name="${ coord.name }"
   frequency="${ coord.frequency }"
   start="${ coord.start_utc }" end="${ coord.end_utc }" timezone="${ coord.timezone }"
@@ -52,7 +78,7 @@
   <input-events>
     % for input in coord.datainput_set.all():
     <data-in name="${ input.name }" dataset="${ input.dataset }">
-      <instance>${'${'}coord:current(0)}</instance>
+      ${ render_dataset_instance(input.dataset) }
     </data-in>
     % endfor
   </input-events>
@@ -62,7 +88,7 @@
   <output-events>
     % for output in coord.dataoutput_set.all():
     <data-out name="${ output.name }" dataset="${ output.dataset }">
-      <instance>${'${'}coord:current(0)}</instance>
+      ${ render_dataset_instance(output.dataset) }
     </data-out>
     % endfor
   </output-events>

+ 88 - 33
apps/oozie/src/oozie/tests.py

@@ -944,39 +944,74 @@ class TestEditor(OozieMockBase):
     create_dataset(coord, self.c)
     create_coordinator_data(coord, self.c)
 
-    assert_equal(
-        ['<coordinator-app', 'name="MyCoord"', 'frequency="${coord:days(1)}"', 'start="2012-07-01T00:00Z"', 'end="2012-07-04T00:00Z"',
-         'timezone="America/Los_Angeles"',
-         'xmlns="uri:oozie:coordinator:0.1">',
-         '<controls>',
-         '<timeout>100</timeout>',
-         '<concurrency>3</concurrency>',
-         '<execution>FIFO</execution>',
-         '<throttle>10</throttle>',
-         '</controls>',
-         '<datasets>',
-         '<dataset', 'name="MyDataset"', 'frequency="${coord:days(1)}"', 'initial-instance="2012-07-01T00:00Z"', 'timezone="America/Los_Angeles">',
-         '<uri-template>/data/${YEAR}${MONTH}${DAY}</uri-template>',
-         '<done-flag></done-flag>',
-         '</dataset>',
-         '</datasets>',
-         '<input-events>',
-         '<data-in', 'name="input_dir"', 'dataset="MyDataset">',
-         '<instance>${coord:current(0)}</instance>',
-         '</data-in>',
-         '</input-events>',
-         '<action>',
-         '<workflow>',
-         '<app-path>${wf_application_path}</app-path>',
-         '<configuration>',
-         '<property>',
-         '<name>input_dir</name>',
-         "<value>${coord:dataIn('input_dir')}</value>",
-         '</property>',
-         '</configuration>',
-         '</workflow>',
-         '</action>',
-         '</coordinator-app>'], coord.to_xml().split())
+    self.c.post(reverse('oozie:create_coordinator_dataset', args=[coord.id]), {
+                          u'create-name': [u'MyDataset2'], u'create-frequency_number': [u'1'], u'create-frequency_unit': [u'days'],
+                          u'create-uri': [u'/data/out/${YEAR}${MONTH}${DAY}'],
+                          u'create-instance_choice': [u'single'],
+                          u'instance_start': [u'-1'],
+                          u'create-advanced_start_instance': [u'0'],
+                          u'create-advanced_end_instance': [u'0'],
+                          u'create-start_0': [u'07/01/2012'], u'create-start_1': [u'12:00 AM'],
+                          u'create-timezone': [u'America/Los_Angeles'], u'create-done_flag': [u''],
+                        u'create-description': [u'']})
+
+    self.c.post(reverse('oozie:create_coordinator_data', args=[coord.id, 'output']),
+                         {u'output-name': [u'output_dir'], u'output-dataset': [u'2']})
+
+    assert_true(
+"""<coordinator-app name="MyCoord"
+  frequency="${coord:days(1)}"
+  start="2012-07-01T00:00Z" end="2012-07-04T00:00Z" timezone="America/Los_Angeles"
+  xmlns="uri:oozie:coordinator:0.1">
+  <controls>
+    <timeout>100</timeout>
+    <concurrency>3</concurrency>
+    <execution>FIFO</execution>
+    <throttle>10</throttle>
+  </controls>
+  <datasets>
+    <dataset name="MyDataset" frequency="${coord:days(1)}"
+             initial-instance="2012-07-01T00:00Z" timezone="America/Los_Angeles">
+      <uri-template>/data/${YEAR}${MONTH}${DAY}</uri-template>
+      <done-flag></done-flag>
+    </dataset>
+    <dataset name="MyDataset2" frequency="${coord:days(1)}"
+             initial-instance="2012-07-01T00:00Z" timezone="America/Los_Angeles">
+      <uri-template>/data/out/${YEAR}${MONTH}${DAY}</uri-template>
+      <done-flag></done-flag>
+    </dataset>
+  </datasets>
+  <input-events>
+    <data-in name="input_dir" dataset="MyDataset">
+    <start-instance>
+        ${coord:current(-1)}
+    </start-instance>
+    <end-instance>
+        ${coord:current(1)}
+    </end-instance>
+    </data-in>
+  </input-events>
+  <output-events>
+    <data-out name="output_dir" dataset="MyDataset2">
+      <instance>${coord:current(0)}</instance>
+    </data-out>
+  </output-events>
+  <action>
+    <workflow>
+      <app-path>${wf_application_path}</app-path>
+      <configuration>
+          <property>
+            <name>input_dir</name>
+            <value>${coord:dataIn('input_dir')}</value>
+          </property>
+        <property>
+          <name>output_dir</name>
+          <value>${coord:dataOut('output_dir')}</value>
+        </property>
+      </configuration>
+   </workflow>
+  </action>
+</coordinator-app>""" in coord.to_xml(), coord.to_xml())
 
 
   def test_create_coordinator_dataset(self):
@@ -984,6 +1019,23 @@ class TestEditor(OozieMockBase):
     create_dataset(coord, self.c)
 
 
+  def test_edit_coordinator_dataset(self):
+    coord = create_coordinator(self.wf, self.c)
+    create_dataset(coord, self.c)
+
+    response = self.c.post(reverse('oozie:edit_coordinator_dataset', args=[1]), {
+                        u'edit-name': [u'MyDataset'], u'edit-frequency_number': [u'1'], u'edit-frequency_unit': [u'days'],
+                        u'edit-uri': [u'/data/${YEAR}${MONTH}${DAY}'],
+                        u'edit-start_0': [u'07/01/2012'], u'edit-start_1': [u'12:00 AM'],
+                        u'edit-instance_choice': [u'range'],
+                        u'edit-advanced_start_instance': [u'-1'],
+                        u'edit-advanced_end_instance': [u'${coord:current(1)}'],
+                        u'edit-start_0': [u'07/01/2012'], u'edit-start_1': [u'12:00 AM'],
+                        u'edit-timezone': [u'America/Los_Angeles'], u'edit-done_flag': [u''],
+                        u'edit-description': [u'']}, follow=True)
+    data = json.loads(response.content)
+    assert_equal(0, data['status'], data['status'])
+
   def test_create_coordinator_input_data(self):
     coord = create_coordinator(self.wf, self.c)
     create_dataset(coord, self.c)
@@ -1868,6 +1920,9 @@ def create_dataset(coord, client):
   response = client.post(reverse('oozie:create_coordinator_dataset', args=[coord.id]), {
                         u'create-name': [u'MyDataset'], u'create-frequency_number': [u'1'], u'create-frequency_unit': [u'days'],
                         u'create-uri': [u'/data/${YEAR}${MONTH}${DAY}'],
+                        u'create-instance_choice': [u'range'],
+                        u'create-advanced_start_instance': [u'-1'],
+                        u'create-advanced_end_instance': [u'${coord:current(1)}'],
                         u'create-start_0': [u'07/01/2012'], u'create-start_1': [u'12:00 AM'],
                         u'create-timezone': [u'America/Los_Angeles'], u'create-done_flag': [u''],
                         u'create-description': [u'']})

+ 6 - 6
apps/oozie/src/oozie/views/editor.py

@@ -331,6 +331,7 @@ def edit_coordinator(request, coordinator):
     'dataset_formset': dataset_formset,
     'data_input_formset': data_input_formset,
     'data_output_formset': data_output_formset,
+    'dataset': dataset,
     'dataset_form': dataset_form,
     'new_data_input_formset': new_data_input_formset,
     'new_data_output_formset': new_data_output_formset,
@@ -355,8 +356,6 @@ def create_coordinator_dataset(request, coordinator):
       response['status'] = 0
       response['data'] = reverse('oozie:edit_coordinator', kwargs={'coordinator': coordinator.id}) + "#listDataset"
       request.info(_('Dataset created'))
-    else:
-      dataset_form = DatasetForm(request.POST, instance=dataset, prefix='create')
   else:
     ## Bad
     response['data'] = _('A POST request is required.')
@@ -365,6 +364,7 @@ def create_coordinator_dataset(request, coordinator):
     response['data'] = render('editor/create_coordinator_dataset.mako', request, {
                             'coordinator': coordinator,
                             'dataset_form': dataset_form,
+                            'dataset': dataset,
                           }, force_template=True).content
 
   return HttpResponse(json.dumps(response), mimetype="application/json")
@@ -378,7 +378,7 @@ def edit_coordinator_dataset(request, dataset):
   response = {'status': -1, 'data': 'None'}
 
   if request.method == 'POST':
-    dataset_form = DatasetForm(request.POST, instance=dataset)
+    dataset_form = DatasetForm(request.POST, instance=dataset, prefix='edit')
 
     if dataset_form.is_valid():
       dataset_form.save()
@@ -386,14 +386,15 @@ def edit_coordinator_dataset(request, dataset):
       response['data'] = reverse('oozie:edit_coordinator', kwargs={'coordinator': dataset.coordinator.id}) + "#listDataset"
       request.info(_('Dataset modified'))
     else:
-      dataset_form = DatasetForm(request.POST, instance=dataset)
+      response['data'] = dataset_form.errors
   else:
-    dataset_form = DatasetForm(instance=dataset)
+    dataset_form = DatasetForm(instance=dataset, prefix='edit')
 
   if response['status'] != 0:
     response['data'] = render('editor/edit_coordinator_dataset.mako', request, {
                           'coordinator': dataset.coordinator,
                           'dataset_form': dataset_form,
+                          'dataset': dataset,
                           'path': request.path,
                         }, force_template=True).content
 
@@ -423,7 +424,6 @@ def create_coordinator_data(request, coordinator, data_type):
       response['data'] = reverse('oozie:edit_coordinator', kwargs={'coordinator': coordinator.id})
       request.info(_('Coordinator data created'));
     else:
-      data_form = DataForm(request.POST, instance=data_instance, coordinator=coordinator)
       response['data'] = data_form.errors
   else:
     response['data'] = _('A POST request is required.')