def main(): uid = os.getuid() if len(sys.argv) < 3: jobs_old = api.get_jobs_for_user(uid) with tempfile.NamedTemporaryFile('w', delete=False) as temp: for job in jobs_old: temp.write("%s %s\n" % (job.interval, job.command)) tb_file = temp.name editor = os.getenv('EDITOR') if editor is not None: os.system("%s %s" % (editor, tb_file)) else: subprocess.call("vim %s" % tb_file, shell=True) elif sys.argv[1] == '-u': tb_file = sys.argv[2] jobs_new = [] with open(tb_file, 'r') as tab: for job in tab: tmp = job.strip().split(' ') interval = string.joinfields(tmp[:5], ' ') cmd = string.joinfields(tmp[5:], ' ') jobs_new.append(api.Job(interval, cmd, uid, datetime.now())) if len(sys.argv) < 3: os.unlink(tb_file) api.set_jobs(jobs_new, uid)
def test_get_schedules_many_workers_many_schedules(self): num_of_jobs = MANY num_of_schedules = num_of_jobs num_of_workers = num_of_schedules num_of_workers = MANY test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create many workers and add them to a list for bookkeeping for worker in range(num_of_workers): test_workers.append(api.create_worker()) # Create a schedule belonging to each worker representing the only job test_schedules = [] for worker in test_workers: for job in jobs_list: test_schedules.append(api.Schedule(datetime.now(), job, worker)) api.add_schedules(test_schedules) # Aggregate each worker's schedules into a single list for comparison # with test schedules schedules_for_workers = [] for worker in test_workers: schedules_list = api.get_schedules(worker) schedules_for_workers.extend(schedules_list) # Verify that the information we get matches what was set check_schedule_fields(self, schedules_for_workers, test_schedules)
def test_remove_schedule_many_schedules(self): # Number of jobs and floor(requests) + ceiling(requests) are equal num_of_jobs = MANY num_of_schedules = num_of_jobs # Automatic flooring care of Python num_of_requests = num_of_jobs / 2 # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for many jobs test_schedules = [] for schedule in range(num_of_schedules): test_schedules.append(api.Schedule(datetime.now(), test_jobs[schedule], test_workers[0])) api.add_schedules(test_schedules) # Kill the floor of half of the workers in the list for request in range(num_of_requests): api.remove_schedule(test_schedules.pop()) schedules_list = api.get_schedules(test_workers[0]) # Verify that the correct remaining schedules are still in the list check_schedule_fields(self, schedules_list, test_schedules) # Remove all remaining test schedules while test_schedules: api.remove_schedule(test_schedules.pop()) # Try to get schedules from an empty pool schedules_list = api.get_schedules(test_workers[0]) # Verify that the next worker does not exist self.assertFalse(len(schedules_list))
def test_remove_schedule_many_schedules(self): # Number of jobs and floor(requests) + ceiling(requests) are equal num_of_jobs = MANY num_of_schedules = num_of_jobs # Automatic flooring care of Python num_of_requests = num_of_jobs / 2 # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for many jobs test_schedules = [] for schedule in range(num_of_schedules): test_schedules.append( api.Schedule(datetime.now(), test_jobs[schedule], test_workers[0])) api.add_schedules(test_schedules) # Kill the floor of half of the workers in the list for request in range(num_of_requests): api.remove_schedule(test_schedules.pop()) schedules_list = api.get_schedules(test_workers[0]) # Verify that the correct remaining schedules are still in the list check_schedule_fields(self, schedules_list, test_schedules) # Remove all remaining test schedules while test_schedules: api.remove_schedule(test_schedules.pop()) # Try to get schedules from an empty pool schedules_list = api.get_schedules(test_workers[0]) # Verify that the next worker does not exist self.assertFalse(len(schedules_list))
def test_remove_schedules_many_schedules_random_schedules(self): # Number of jobs and floor(requests) + ceiling(requests) are equal num_of_jobs = MANY num_of_schedules = num_of_jobs # Leave one schedule remaining for comparison at the end num_of_requests = num_of_jobs - 1 # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) test_schedules = [] for schedule in range(num_of_schedules): test_schedules.append(api.Schedule(datetime.now(), test_jobs[schedule], test_workers[0])) api.add_schedules(test_schedules) # Kill number of requests random schedules in the list for request in range(num_of_requests): random_schedule = random.randrange(len(test_schedules)) api.remove_schedule(test_schedules.pop(random_schedule)) schedules_list = [] schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list contains exactly one schedule self.assertEqual(len(schedules_list), 1) # Verify that the correct remaining schedule is still in the list check_schedule_fields(self, schedules_list, test_schedules)
def test_remove_schedules_many_schedules_random_schedules(self): # Number of jobs and floor(requests) + ceiling(requests) are equal num_of_jobs = MANY num_of_schedules = num_of_jobs # Leave one schedule remaining for comparison at the end num_of_requests = num_of_jobs - 1 # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) test_schedules = [] for schedule in range(num_of_schedules): test_schedules.append( api.Schedule(datetime.now(), test_jobs[schedule], test_workers[0])) api.add_schedules(test_schedules) # Kill number of requests random schedules in the list for request in range(num_of_requests): random_schedule = random.randrange(len(test_schedules)) api.remove_schedule(test_schedules.pop(random_schedule)) schedules_list = [] schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list contains exactly one schedule self.assertEqual(len(schedules_list), 1) # Verify that the correct remaining schedule is still in the list check_schedule_fields(self, schedules_list, test_schedules)
def test_get_jobs_for_user_empty_jobs(self): num_of_jobs = ZERO # Create a crontab with zero jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list_user1 = api.get_jobs_for_user(user1) # Verify that the jobs list for user1 is empty self.assertFalse(len(jobs_list_user1))
def test_get_crontab_empty_jobs(self): num_of_jobs = ZERO # Create a crontab with zero jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) crontab = api.get_crontab(user1) # Verify that the crontab is empty self.assertEqual(crontab, False)
def test_get_jobs_many_jobs(self): num_of_jobs = MANY # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() self.assertEqual(len(jobs_list), num_of_jobs) # Verify that the information we get matches what was set check_job_fields(self, jobs_list, test_jobs, user1)
def test_get_jobs_for_user_many_jobs(self): num_of_jobs = MANY # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list_user1 = api.get_jobs_for_user(user1) # Verify that the jobs list for user1 # contains the correct number of jobs self.assertEqual(len(jobs_list_user1), num_of_jobs)
def test_get_jobs_empty_jobs(self): num_of_jobs = ZERO # Create a crontab with zero jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() # Verify that the jobs list is empty self.assertEqual(len(jobs_list), num_of_jobs) # Verify that the information we get matches what was set check_job_fields(self, jobs_list, test_jobs, user1)
def test_get_crontab_many_jobs(self): num_of_jobs = MANY # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) with open(TAB_FILE, 'r') as tabfile: crontab = tabfile.read() api.set_crontab(crontab, user1) test_crontab = api.get_crontab(user1) self.assertEqual(crontab, test_crontab)
def test_get_jobs_one_job(self): num_of_jobs = ONE # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() # Verify that the jobs list contains exactly one job self.assertEqual(len(jobs_list), num_of_jobs) # Verify that the information we get matches what was set check_job_fields(self, jobs_list, test_jobs, user1)
def test_get_jobs_for_user_some_users_empty_jobs(self): jobs_list_user4 = api.get_jobs_for_user(user4) # Verify that the jobs_list for user4 is empty self.assertFalse(len(jobs_list_user4)) num_of_jobs_user1 = ONE # Add one job to the tabfile user1 test_jobs_user1 = create_test_tab(num_of_jobs_user1, user1) api.set_jobs(test_jobs_user1, user1) jobs_list_user4 = api.get_jobs_for_user(user4) # Verify that the jobs_list for user4 is empty self.assertFalse(len(jobs_list_user4))
def test_set_crontab_one_job(self): num_of_jobs = ONE # Create a crontab with one jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) with open(TAB_FILE, 'r') as tabfile: crontab = tabfile.read() test_crontab = api.get_crontab(user1) self.assertEquals(test_crontab, False) api.set_crontab(crontab, user1) test_crontab = api.get_crontab(user1) self.assertEqual(crontab, test_crontab)
def test_set_job_time_random_job_from_many(self): checkpoint1 = datetime.now() num_of_jobs = MANY # Create a crontab with many jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) # Pop a random job in list to modify its time job = test_jobs.pop(random.randrange(len(test_jobs))) api.set_job_time(job) checkpoint2 = datetime.now() # Verify that the job's last time run was updated correctly self.assertTrue(job.last_time_run > checkpoint1 and job.last_time_run < checkpoint2)
def test_set_job_time_one_job(self): checkpoint1 = datetime.now() num_of_jobs = ONE # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) # Pop the only job in the list to modify its time job = test_jobs.pop() api.set_job_time(job) checkpoint2 = datetime.now() # Verify that the job's last time run was updated correctly self.assertTrue(job.last_time_run > checkpoint1 and job.last_time_run < checkpoint2)
def process_edits(uid, tb_file, using_local_file, old_tab): crontab = [] jobs = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, "r") as tab: for line in tab: line = line.strip() crontab.append(line) # Ignore newlines and full line comments if line and (line[0] != "#"): split = line.split() interval = " ".join(split[:5]) cmd = " ".join(split[5:]) try: # Ensure the crontab line is valid croniter(interval) if not cmd: raise ValueError except (KeyError, ValueError): # Otherwise prompt user to edit crontab e_str = "The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) " while True: cnt = _input(e_str) if (cnt == "n") or (cnt == "N"): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == "y") or (cnt == "Y"): return False e_str = "Please enter y or n: " # Check if job was already there job = None if line in old_tab: for old_job in old_jobs: if old_job.interval == interval and old_job.command == cmd: job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, datetime.now()) jobs.append(job) if using_local_file is False: os.unlink(tb_file) api.set_crontab("\n".join(crontab), uid) api.set_jobs(jobs, uid) return True
def test_set_jobs_empty_jobs(self): checkpoint1 = datetime.now() num_of_jobs = ZERO # Create a crontab with zero jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) # Query metadata for the database file creation time db_creation_time = datetime.fromtimestamp( os.stat(api.FILE_NAME).st_mtime) # We are comparing different orders of time, so offset by one second new_time = db_creation_time.replace(second=db_creation_time.second + 1) checkpoint2 = datetime.now() checkpoint2 = checkpoint2.replace(second=checkpoint2.second + 1) # Verify that the jobs have been set just now self.assertTrue(new_time > checkpoint1 and new_time < checkpoint2)
def test_get_schedules_one_worker_many_schedules(self): num_of_jobs = MANY num_of_schedules = num_of_jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] for job in range(num_of_jobs): test_schedules.append(api.Schedule(datetime.now(), test_jobs[job], test_workers[0])) api.add_schedules(test_schedules) schedules_list = api.get_schedules(test_workers[0]) # Verify that the information we get matches what was set check_schedule_fields(self, schedules_list, test_schedules)
def test_add_schedules_one_job_one_schedule(self): num_of_jobs = ONE num_of_schedules = num_of_jobs # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] test_schedules.append(api.Schedule(datetime.now(), test_jobs[0], test_workers[0])) api.add_schedules(test_schedules) schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list contains exactly one schedule self.assertEqual(len(schedules_list), num_of_schedules)
def test_add_schedules_one_job_one_schedule(self): num_of_jobs = ONE num_of_schedules = num_of_jobs # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] test_schedules.append( api.Schedule(datetime.now(), test_jobs[0], test_workers[0])) api.add_schedules(test_schedules) schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list contains exactly one schedule self.assertEqual(len(schedules_list), num_of_schedules)
def test_get_crontab_different_users_many_jobs(self): num_of_jobs = MANY # Create a crontab with many jobs for another user from crontab owner test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) with open(TAB_FILE, 'r') as tabfile: crontab = tabfile.read() api.set_crontab(crontab, user2) test_crontab = api.get_crontab(user2) self.assertEqual(crontab, test_crontab) # Append crontab for another user test_jobs = create_test_tab(num_of_jobs, user3) api.set_jobs(test_jobs, user3) with open(TAB_FILE, 'r') as tabfile: crontab = tabfile.read() api.set_crontab(crontab, user3) test_crontab = api.get_crontab(user3) self.assertEqual(crontab, test_crontab)
def test_get_schedules_one_worker_many_schedules(self): num_of_jobs = MANY num_of_schedules = num_of_jobs test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] for job in range(num_of_jobs): test_schedules.append( api.Schedule(datetime.now(), test_jobs[job], test_workers[0])) api.add_schedules(test_schedules) schedules_list = api.get_schedules(test_workers[0]) # Verify that the information we get matches what was set check_schedule_fields(self, schedules_list, test_schedules)
def test_remove_schedule_one_schedule(self): num_of_jobs = ONE num_of_schedules = num_of_jobs # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] test_schedules.append( api.Schedule(datetime.now(), test_jobs[0], test_workers[0])) api.add_schedules(test_schedules) # Kill the only schedule in the list api.remove_schedule(test_schedules[0]) schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list is empty self.assertFalse(len(schedules_list))
def test_remove_schedule_one_schedule(self): num_of_jobs = ONE num_of_schedules = num_of_jobs # Create a crontab with one job test_jobs = create_test_tab(num_of_jobs, user1) api.set_jobs(test_jobs, user1) jobs_list = api.get_jobs() test_workers = [] # Create one worker and add them to a list for bookkeeping test_workers.append(api.create_worker()) # Create a schedule for the only job test_schedules = [] test_schedules.append(api.Schedule(datetime.now(), test_jobs[0], test_workers[0])) api.add_schedules(test_schedules) # Kill the only schedule in the list api.remove_schedule(test_schedules[0]) schedules_list = api.get_schedules(test_workers[0]) # Verify that the schedules list is empty self.assertFalse(len(schedules_list))
def test_get_jobs_for_user_different_users_some_jobs(self): num_of_jobs_user1 = ONE # Add one job to the tabfile for user1 test_jobs_user1 = create_test_tab(num_of_jobs_user1, user1) api.set_jobs(test_jobs_user1, user1) jobs_list_user1 = api.get_jobs_for_user(user1) num_of_jobs_user2 = ZERO # Add zero jobs to the tabfile for user2 test_jobs_user2 = create_test_tab(num_of_jobs_user2, user2) api.set_jobs(test_jobs_user2, user2) jobs_list_user2 = api.get_jobs_for_user(user2) num_of_jobs_user3 = SOME # Add some jobs to the tabfile for user3 test_jobs_user3 = create_test_tab(num_of_jobs_user3, user3) api.set_jobs(test_jobs_user3, user3) jobs_list_user3 = api.get_jobs_for_user(user3) # Verify that the jobs list for user1 contains # the correct number of jobs self.assertEqual(len(jobs_list_user1), num_of_jobs_user1) # Verify that the jobs list for user2 contains # the correct number of jobs self.assertEqual(len(jobs_list_user2), num_of_jobs_user2) # Verify that the jobs list for user3 contains # the correct number of jobs self.assertEqual(len(jobs_list_user3), num_of_jobs_user3) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user1, test_jobs_user1, user1) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user2, test_jobs_user2, user2) # Verify that the information we get matches what was set check_job_fields(self, jobs_list_user3, test_jobs_user3, user3)
def main(): tb_file = None valid_crontab = None usr_euid = os.geteuid() opts = parse_args() # Convert given username into (uid, username) if opts.usr: try: opts.usr = (pwd.getpwnam(opts.usr).pw_uid, opts.usr) except KeyError: sys.exit("User '%s' does not exist." % opts.usr) # Verify permissions for selected crontab if (usr_euid != 0) and (opts.usr[0] != usr_euid): sys.exit("Access denied. You do not have permission to edit %s's " "crontab." % opts.usr[1]) # If no user is specified, set to current user (euid or uid?) else: opts.usr = (usr_euid, pwd.getpwuid(usr_euid).pw_name) # Perform rm operation if opts.rm: if opts.rm_prompt: rm = None e_str = "You are about to delete %s's crontab, continue? " "(y/n) " % opts.usr[1] while (rm != "Y") and (rm != "y"): rm = _input(e_str) if (rm == "N") or (rm == "n"): sys.exit(0) e_str = "Please enter y or n: " api.set_jobs([], opts.usr[0]) api.set_crontab(False, opts.usr[0]) sys.exit(0) while not valid_crontab: tb_file, old_tab = get_crontab(opts, valid_crontab, tb_file) valid_crontab = process_edits(opts.usr[0], tb_file, opts.file, old_tab)
def main(): tb_file = None valid_crontab = None usr_euid = os.geteuid() opts = parse_args() # Convert given username into (uid, username) if opts.usr: try: opts.usr = (pwd.getpwnam(opts.usr).pw_uid, opts.usr) except KeyError: sys.exit("User `%s' does not exist." % opts.usr) # If no user is specified, set to current user (euid or uid?) else: opts.usr = (usr_euid, pwd.getpwuid(usr_euid).pw_name) check_permissions(opts.usr, usr_euid) # Perform rm operation if opts.rm: if opts.rm_prompt: rm = None e_str = ("You are about to delete %s's crontab, continue? " "(y/n) " % opts.usr[1]) while (rm != 'Y') and (rm != 'y'): rm = _input(e_str) if (rm == 'N') or (rm == 'n'): sys.exit(0) e_str = "Please enter y or n: " api.set_jobs([], opts.usr[0]) api.set_crontab(False, opts.usr[0]) sys.exit(0) while not valid_crontab: tb_file, old_tab = get_crontab(opts, valid_crontab, tb_file) valid_crontab = process_edits(opts.usr[0], tb_file, opts.file, old_tab)
def process_edits(uid, tb_file, using_local_file, old_tab): e_str = "" jobs = [] crontab = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, 'r') as tab: for i, line in enumerate(tab): line = line.strip() crontab.append(line) # Ignore newlines and comments if line and (line[0] != '#'): split = line.split() # Check for special interval syntax if split[0][0] == '@': try: interval = _special_intervals[split[0]] except KeyError: e_str += ("Error in line %i: Bad special interval " "syntax, %s\n" % (i + 1, split[0])) continue cmd = ' '.join(split[1:]) # Check if setting variable elif '=' in ''.join(split[:5]): name, _, value = line.partition('=') # Check if var name is zero or multiple words name = name.strip() num_names = len(name.split()) if num_names != 1: if num_names: e_str += ("Error in line %i: Bad variable " "assignment syntax; multiple variable " "names given\n" % (i + 1)) else: e_str += ("Error in line %i: Bad variable " "assignment syntax; no variable name " "given\n" % (i + 1)) else: value = value.strip() if (((value[0] == "'") or (value[0] == '"')) and (value[-1] == value[0])): # If properly wrapped in quotes, check if escaped for i, char in enumerate(reversed(value[:-1])): if char != '\\': i += 1 break if i % 2 != 0: value = value[1:-1] os.environ[name] = value continue else: # Check if five or six time/date fields if (len(split) > 5 and not any(c.isalpha() for c in split[5]) and ('*' in split[5] or any(c.isdigit() for c in split[5])) and split[5][0] != '/'): # Could print warning that using 6 time fields interval = ' '.join(split[:6]) cmd = ' '.join(split[6:]) else: interval = ' '.join(split[:5]) cmd = ' '.join(split[5:]) # Check for un-escaped %s in command job_input = None index = cmd.find('%') while (index != -1) and (cmd[index - 1] == '\\'): index = cmd.find('%', index + 1) if index != -1: job_input = _escaped_pct.sub( '%', _unescaped_pct.sub(r"\1\n", cmd[index + 1:])) cmd = cmd[:index] cmd = _escaped_pct.sub('%', cmd) # Ensure the crontab line is valid try: croniter(interval) if not cmd: raise ValueError("Missing command") except (KeyError, ValueError) as e: if isinstance(e, KeyError): e = "Bad time interval syntax, %s " % e # Replace croniter's typo-riddled error msg elif str(e) == ("Exactly 5 or 6 columns has to be " "specified for iteratorexpression."): e = ("Less than 5 fields separated by whitespace in " "the time interval (requires 5 or 6)") e_str += "Error in line %i: %s\n" % (i + 1, e) else: if not e_str: job = None # Check if job was in the old crontab if line in old_tab: for old_job in old_jobs: if (old_job.interval == interval and old_job.command == cmd and old_job.job_input == job_input and old_job.environment == os.environ): job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, os.environ.copy(), job_input, datetime.now()) jobs.append(job) # Prompt user to edit crontab on error if e_str: e_str += ("The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) ") while True: cnt = _input(e_str) if (cnt == 'n') or (cnt == 'N'): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == 'y') or (cnt == 'Y'): return False e_str = "Please enter y or n: " if using_local_file is False: os.unlink(tb_file) api.set_crontab('\n'.join(crontab), uid) api.set_jobs(jobs, uid) return True
def test_set_jobs(): api.set_jobs(test_jobs, uid)
def process_edits(uid, tb_file, using_local_file, old_tab): e_str = "" jobs = [] crontab = [] old_jobs = api.get_jobs_for_user(uid) with open(tb_file, 'r') as tab: for i, line in enumerate(tab): line = line.strip() crontab.append(line) # Ignore newlines and comments if line and (line[0] != '#'): split = line.split() # Check for special interval syntax if split[0][0] == '@': try: interval = _special_intervals[split[0]] except KeyError: e_str += ("Error in line %i: Bad special interval " "syntax, %s\n" % (i + 1, split[0])) continue cmd = ' '.join(split[1:]) # Check if setting variable elif '=' in ''.join(split[:5]): name, _, value = line.partition('=') # Check if var name is zero or multiple words name = name.strip() num_names = len(name.split()) if num_names != 1: if num_names: e_str += ("Error in line %i: Bad variable " "assignment syntax; multiple variable " "names given\n" % (i + 1)) else: e_str += ("Error in line %i: Bad variable " "assignment syntax; no variable name " "given\n" % (i + 1)) else: value = value.strip() if (((value[0] == "'") or (value[0] == '"')) and (value[-1] == value[0])): # If properly wrapped in quotes, check if escaped for i, char in enumerate(reversed(value[:-1])): if char != '\\': i += 1 break if i % 2 != 0: value = value[1:-1] os.environ[name] = value continue else: # Check if five or six time/date fields if (len(split) > 5 and not any(c.isalpha() for c in split[5]) and ('*' in split[5] or any(c.isdigit() for c in split[5])) and split[5][0] != '/'): # Could print warning that using 6 time fields interval = ' '.join(split[:6]) cmd = ' '.join(split[6:]) else: interval = ' '.join(split[:5]) cmd = ' '.join(split[5:]) # Check for un-escaped %s in command job_input = None index = cmd.find('%') while (index != -1) and (cmd[index-1] == '\\'): index = cmd.find('%', index + 1) if index != -1: job_input = _escaped_pct.sub('%', _unescaped_pct.sub( r"\1\n", cmd[index+1:])) cmd = cmd[:index] cmd = _escaped_pct.sub('%', cmd) # Ensure the crontab line is valid try: croniter(interval) if not cmd: raise ValueError("Missing command") except (KeyError, ValueError) as e: if isinstance(e, KeyError): e = "Bad time interval syntax, %s " % e # Replace croniter's typo-riddled error msg elif str(e) == ("Exactly 5 or 6 columns has to be " "specified for iteratorexpression."): e = ("Less than 5 fields separated by whitespace in " "the time interval (requires 5 or 6)") e_str += "Error in line %i: %s\n" % (i + 1, e) else: if not e_str: job = None # Check if job was in the old crontab if line in old_tab: for old_job in old_jobs: if (old_job.interval == interval and old_job.command == cmd and old_job.job_input == job_input and old_job.environment == os.environ): job = old_job old_jobs.remove(old_job) break if not job: old_tab.discard(line) job = api.Job(interval, cmd, uid, os.environ.copy(), job_input, datetime.now()) jobs.append(job) # Prompt user to edit crontab on error if e_str: e_str += ("The crontab you entered has invalid entries, " "would you like to edit it again? (y/n) ") while True: cnt = _input(e_str) if (cnt == 'n') or (cnt == 'N'): if using_local_file is False: os.unlink(tb_file) sys.exit(1) elif (cnt == 'y') or (cnt == 'Y'): return False e_str = "Please enter y or n: " if using_local_file is False: os.unlink(tb_file) api.set_crontab('\n'.join(crontab), uid) api.set_jobs(jobs, uid) return True