# Author : Niloy Chakraborty # AWS Schedule Expression cron expression validator import re from voluptuous import Invalid import datetime minute_regex = r"^([*]|([0]?[0-5]?[0-9]?)|(([0]?[0-5]?[0-9]?)(\/|\-)([0]?[0-5]?[0-9]?))|" \ "(([0]?[0-5]?[0-9]?)((\,)([0]?[0-5]?[0-9]?))*))$" hour_regex = r"^([*]|[01]?[0-9]|2[0-3]|(([01]?[0-9]|2[0-3]?)(\/|\-)([01]?[0-9]|2[0-3]?))|" \ "(([01]?[0-9]|2[0-3]?)((\,)([01]?[0-9]|2[0-3]?))*))$" d_m_regex = r"^([*]|[?]|([0-2]?[0-9]|3[0-1])|(([0-2]?[0-9]|3[0-1])(\/|\-)([0-2]?[0-9]|3[0-1]))|" \ "(([0-2]?[0-9]|3[0-1])((\,)([0-2]?[0-9]|3[0-1]))*))$" month_regex = r"^([*]|([0]?[0-9]|1[0-2])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|" \ "((([0]?[0-9]|1[0-2])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))(\/|\-)(([0]?[0-9]|1[0-2])|" \ "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)))|((([0]?[0-9]|1[0-2])|" \ "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))((\,)(([0]?[0-9]|1[0-2])|" \ "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)))*))$" d_w_regex = r"^([*]|[?]|([0]?[1-7])|(SUN|MON|TUE|WED|THU|FRI|SAT)|((([0]?[1-7])|(SUN|MON|TUE|WED|" \ "THU|FRI|SAT))(\/|\-|\,|\#)(([0]?[1-7])|(SUN|MON|TUE|WED|THU|FRI|SAT)))|((([0]?[1-7])|(SUN|MON|TUE|WED|" \ "THU|FRI|SAT))((\,)(([0]?[1-7])|(SUN|MON|TUE|WED|THU|FRI|SAT)))*))$" year_regex = r"^([*]|([1-2][01][0-9][0-9])|(([1-2][01][0-9][0-9])(\/|\-)([1-2][01][0-9][0-9]))|" \ "(([1-2][01][0-9][0-9])((\,)([1-2][01][0-9][0-9]))*))$" def validate_aws_regex(regex_val): regex_splits = regex_val.split(" ") if len(regex_splits) < 6: raise Invalid( "Schedule parameter should have 6 field minute,hour,day_of_the_month,month,day_of_the_week,year.Please check the value") minute_val = regex_splits[0] hour_val = regex_splits[1] d_m_val = regex_splits[2] month_val = regex_splits[3] d_w_val = regex_splits[4] year_val = regex_splits[5] print( "Values of Min is %s , hour is %s , day_of_month is %s , month is %s ,day of the week is %s and year is %s" % ( minute_val, hour_val, d_m_val, month_val, d_w_val, year_val)) if not ((d_m_val == '?' and d_w_val != '?') or (d_m_val != '?' and d_w_val == '?')): raise Invalid("Either day-of-month or day-of-week values must be a question mark (?)") minute_match = re.fullmatch(minute_regex, minute_val) hour_match = re.fullmatch(hour_regex, hour_val) d_m_match = re.fullmatch(d_m_regex, d_m_val) month_match = re.fullmatch(month_regex, month_val) d_w_match = re.fullmatch(d_w_regex, d_w_val) year_match = re.fullmatch(year_regex, year_val) if not minute_match: raise Invalid("Schedule expression has an invalid minute column value") if not hour_match: raise Invalid("Schedule expression has an invalid hour column value") if not d_m_match: raise Invalid("Schedule expression has an invalid day of the month column value") if not month_match: raise Invalid("Schedule expression has an invalid month column value") if not d_w_match: raise Invalid("Schedule expression has an invalid day of the week column value") if not year_match: raise Invalid("Schedule expression has an invalid year column value") if '#' in d_w_val: nd = int(d_w_val.split('#')[1]) if nd > 5: raise Invalid( "Schedule expression has an invalid day of the week column value. Nth day of week cannot be more than 5") current_year = datetime.datetime.today().year year_split_comma_val = year_val.split(",") year_split_dash_val = year_val.split("-") if "," in year_val: if any(yr_val for yr_val in year_split_comma_val if int(yr_val) < current_year): raise \ Invalid("Schedule expression has an invalid year column value. " \ "Year value[s] should be greater or equal to %s and less than 2199 " % current_year) if "-" in year_val: if int(year_split_dash_val[1]) < current_year: raise \ Invalid("Schedule expression has an invalid year column value. " \ "Year value[s] should be greater or equal to %s and less than 2199 " % current_year) return regex_val # Valid assert validate_aws_regex("0 18 ? * MON-FRI *") == "0 18 ? * MON-FRI *" assert validate_aws_regex("0 10 * * ? *") == "0 10 * * ? *" assert validate_aws_regex("15 12 * * ? *") == "15 12 * * ? *" assert validate_aws_regex("0 8 1 * ? *") == "0 8 1 * ? *" assert validate_aws_regex("0/5 8-17 ? * MON-FRI *") == "0/5 8-17 ? * MON-FRI *" assert validate_aws_regex("0 9 ? * 2#1 *") == "0 9 ? * 2#1 *" assert validate_aws_regex("0 07/12 ? * * *") == "0 07/12 ? * * *" assert validate_aws_regex("10,20,30,40 07/12 ? * * *") == "10,20,30,40 07/12 ? * * *" assert validate_aws_regex("10 10,15,20,23 ? * * *") == "10 10,15,20,23 ? * * *" assert validate_aws_regex("10 10 15,30,31 * ? *") == "10 10 15,30,31 * ? *" assert validate_aws_regex("10 10 15 JAN,JUL,DEC ? *") == "10 10 15 JAN,JUL,DEC ? *" assert validate_aws_regex("10 10 31 04,09,12 ? *") == "10 10 31 04,09,12 ? *" assert validate_aws_regex("0,5 07/12 ? * 01,05,7 *") == "0,5 07/12 ? * 01,05,7 *" assert validate_aws_regex("0,5 07/12 ? * 01,05,7 2020,2021,2028,2199") == "0,5 07/12 ? * 01,05,7 2020,2021,2028,2199" assert validate_aws_regex("0,5 07/12 ? * 01,05,7 2020,2021,2028,2199") # Invalid # validate_aws_regex("0 18 ? * MON-FRI") # validate_aws_regex("0 18 * * * *") # validate_aws_regex("0 65 * * ? *") # validate_aws_regex("89 10 * * ? *") # validate_aws_regex("15/65 10 * * ? *") # validate_aws_regex("15/30 10 * * ? 2400") # validate_aws_regex("0 9 ? * 2#6 *") # validate_aws_regex("0 9 ? * ? *") # validate_aws_regex("10 10 31 04,09,13 ? *") # validate_aws_regex("0,5 07/12 ? * 01,05,8 *") # validate_aws_regex("0,5 07/12 ? * 01,05,7 2020,2021,2028,1111") #validate_aws_regex("0,5 07/12 ? * 01,05,7 2020,2021,2028,2017") #validate_aws_regex("0,5 07/12 ? * 01,05,7 2017-2100")