예제 #1
0
 def test_exceptions(self):
     # L needs year, month and daya params
     self.assertRaises(ValueError, WeekdaySetBuilder().build, "1L")
     self.assertRaises(ValueError,
                       WeekdaySetBuilder(year=2016, month=10, day=4).build,
                       "0#6")
     self.assertRaises(ValueError,
                       WeekdaySetBuilder(year=2016, month=10, day=4).build,
                       "0#0")
    def build_schedule_from_maintenance_window(period_str):
        """
        Builds a Instance running schedule based on an RDS preferred maintenance windows string in format ddd:hh:mm-ddd:hh:mm
        :param period_str: rds maintenance windows string
        :return: Instance running schedule with timezone UTC
        """

        # get elements of period
        start_string, stop_string = period_str.split("-")
        start_day_string, start_hhmm_string = start_string.split(":", 1)
        stop_day_string, stop_hhmm_string = stop_string.split(":", 1)

        # weekday set builder
        weekdays_builder = WeekdaySetBuilder()

        start_weekday = weekdays_builder.build(start_day_string)
        start_time = SchedulerConfigBuilder.get_time_from_string(start_hhmm_string)
        end_time = SchedulerConfigBuilder.get_time_from_string(stop_hhmm_string)

        # windows with now day overlap, can do with one period for schedule
        if start_day_string == stop_day_string:
            periods = [
                {
                    "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME,
                                            begintime=start_time,
                                            endtime=end_time,
                                            weekdays=start_weekday)
                }]
        else:
            # window with day overlap, need two periods for schedule
            end_time_day1 = SchedulerConfigBuilder.get_time_from_string("23:59")
            begin_time_day2 = SchedulerConfigBuilder.get_time_from_string("00:00")
            stop_weekday = weekdays_builder.build(stop_day_string)
            periods = [
                {
                    "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME + "-{}".format(start_day_string),
                                            begintime=start_time,
                                            endtime=end_time_day1,
                                            weekdays=start_weekday),
                    "instancetype": None
                },
                {
                    "period": RunningPeriod(name=MAINTENANCE_PERIOD_NAME + "-{}".format(stop_day_string),
                                            begintime=begin_time_day2,
                                            endtime=end_time,
                                            weekdays=stop_weekday),
                    "instancetype": None
                }]

        # create schedule with period(s) and timezone UTC
        schedule = InstanceSchedule(name=MAINTENANCE_SCHEDULE_NAME, periods=periods, timezone="UTC", enforced=True)

        return schedule
    def _build_period(cls, period_configuration, dt):
        def get_periodname(config):
            period_name = config.get(configuration.NAME)
            if not period_name:
                raise ValueError(MSG_NAME_MISSING_IN_PERIOD.format(config))
            return period_name

        # reads a start and end time from config
        def get_begin_and_end(period_name, config):

            begin = SchedulerConfigBuilder.get_time_from_string(
                config.get(configuration.BEGINTIME))
            end = SchedulerConfigBuilder.get_time_from_string(
                config.get(configuration.ENDTIME))
            if (begin and end) and begin > end:
                raise ValueError(
                    MSG_BEGIN_MUST_BEFORE_END.format(begin, end, period_name))
            return begin, end

        def build_period_config_set(period_config, set_builder, config_name):
            config_set = period_config.get(config_name)
            if config_set:
                return set_builder.build(config_set)
            else:
                return None

        name = get_periodname(period_configuration)
        begin_time, end_time = get_begin_and_end(name, period_configuration)

        week_days = build_period_config_set(
            period_configuration,
            WeekdaySetBuilder(year=dt.year, month=dt.month, day=dt.day),
            configuration.WEEKDAYS)
        months = build_period_config_set(period_configuration,
                                         MonthSetBuilder(),
                                         configuration.MONTHS)
        monthdays = build_period_config_set(
            period_configuration,
            MonthdaySetBuilder(year=dt.year, month=dt.month),
            configuration.MONTHDAYS)

        return RunningPeriod(name=name,
                             begintime=begin_time,
                             endtime=end_time,
                             weekdays=week_days,
                             months=months,
                             monthdays=monthdays)
예제 #4
0
    def test_weekday_numbered(self):

        for year in [2016, 2017]:
            for month in range(1, 13):
                weekday, days_in_month = calendar.monthrange(year, month)

                for day in range(1, days_in_month + 1):
                    num = int((day - 1) / 7) + 1
                    builder = WeekdaySetBuilder(year=year,
                                                month=month,
                                                day=day)

                    tested_by_name = builder.build(calendar.day_abbr[weekday] +
                                                   "#" + str(num))
                    self.assertEquals(tested_by_name, {weekday})

                    tested_by_value = builder.build(
                        str(weekday) + "#" + str(num))
                    self.assertEquals(tested_by_value, {weekday})

                    for other_weekday in range(0, 7):
                        if other_weekday != weekday:
                            tested_by_name = builder.build(
                                calendar.day_abbr[other_weekday] + "#" +
                                str(num))
                            self.assertEquals(tested_by_name, set())
                            tested_by_value = builder.build(
                                str(other_weekday) + "#" + str(num))
                            self.assertEquals(tested_by_value, set())

                    for other_num in range(1, 6):
                        if num != other_num:
                            tested_by_name = builder.build(
                                calendar.day_abbr[weekday] + "#" +
                                str(other_num))
                            self.assertEquals(tested_by_name, set())
                            tested_by_value = builder.build(
                                str(weekday) + "#" + str(other_num))
                            self.assertEquals(tested_by_value, set())

                    weekday = (weekday + 1) % 7
예제 #5
0
    def test_L_wildcard(self):

        for year in [2016, 2017]:
            for month in range(1, 13):
                weekday, days_in_month = calendar.monthrange(year, month)
                for tested_on_day in range(1, days_in_month + 1):
                    builder = WeekdaySetBuilder(year=year,
                                                month=month,
                                                day=tested_on_day)

                    # test by name of weekday
                    day_num_l = calendar.day_abbr[weekday] + "L"
                    tested_by_name = builder.build(day_num_l)
                    # test by number of weekday
                    day_value_l = str(weekday) + "L"
                    tested_by_value = builder.build(day_value_l)

                    # everything before last week should be empty set
                    if tested_on_day <= (days_in_month - 7):
                        self.assertEquals(tested_by_name, set())
                        self.assertEquals(tested_by_value, set())
                    else:
                        # in last week the set should contain the day
                        self.assertEquals(tested_by_name, {weekday})
                        self.assertEquals(tested_by_value, {weekday})

                        # test if ofther weekdays on that day return empty set
                        for d in range(0, 6):
                            if d != weekday:
                                day_num_l = calendar.day_abbr[d] + "L"
                                day_value_l = str(d) + "L"
                                self.assertEquals(builder.build(day_num_l),
                                                  set())
                                self.assertEqual(builder.build(day_value_l),
                                                 set())

                    weekday = (weekday + 1) % 7
    def _validate_period(self, **period):

        result = {}

        def is_valid_time(s):
            return re.match(ConfigAdmin.TIME_REGEX, s) is not None

        # allowed and validated parameters
        valid_parameters = [
            configuration.BEGINTIME, configuration.ENDTIME,
            configuration.WEEKDAYS, configuration.MONTHDAYS,
            configuration.MONTHS, configuration.NAME, configuration.DESCRIPTION
        ]

        for attr in period:
            # indicates type for config entry
            if attr == ConfigAdmin.TYPE_ATTR:
                continue

            # parameter is allowed?
            if attr not in valid_parameters:
                raise ValueError(
                    ERR_PERIOD_UNKNOWN_PARAMETER.format(
                        attr, str(valid_parameters)))

            # remove None values
            if period[attr] is None or len(str(period[attr])) == 0:
                continue

            # period name
            if attr == configuration.NAME:
                result[attr] = period[attr]
                continue

            # description
            if attr == configuration.DESCRIPTION:
                result[attr] = period[attr]
                continue

            # validate start and end types times
            if attr in [configuration.BEGINTIME, configuration.ENDTIME]:
                time_str = period[attr]
                if not is_valid_time(time_str):
                    raise ValueError(
                        ERR_PERIOD_INVALID_TIME.format(attr, time_str))
                result[attr] = str(
                    datetime.strptime(time_str,
                                      configuration.TIME_FORMAT_STRING).time()
                )[0:len(configuration.TIME_FORMAT_STRING)]
                if configuration.BEGINTIME in result and configuration.ENDTIME in result:
                    begintime = datetime.strptime(
                        result[configuration.BEGINTIME],
                        configuration.TIME_FORMAT_STRING).time()
                    endtime = datetime.strptime(
                        result[configuration.ENDTIME],
                        configuration.TIME_FORMAT_STRING).time()
                    if begintime > endtime:
                        raise ValueError(
                            ERR_PERIOD_BEGIN_LATER_THAN_END.format(
                                result[configuration.BEGINTIME],
                                result[configuration.ENDTIME]))

                continue

            # check weekdays, monthdays and month sets
            if attr in [
                    configuration.WEEKDAYS, configuration.MONTHDAYS,
                    configuration.MONTHS
            ]:
                temp = self._ensure_set(period[attr])

                if len(temp) == 0:
                    continue

                # validate month
                if attr == configuration.MONTHS:
                    # noinspection PyPep8
                    try:
                        MonthSetBuilder().build(temp)
                        result[attr] = temp
                        continue
                    except:
                        raise ValueError(
                            ERR_PERIOD_INVALID_MONTHS.format(str(
                                period[attr])))

                # validate weekdays
                if attr == configuration.WEEKDAYS:
                    try:
                        wdb = WeekdaySetBuilder(year=2016, month=12, day=31)
                        wdb.build(temp)
                        result[attr] = temp
                        continue
                    except Exception as ex:
                        raise ValueError(
                            ERR_PERIOD_INVALID_WEEKDAYS.format(
                                str(period[attr]), ex))

                # validate monthdays
                if attr == configuration.MONTHDAYS:
                    # noinspection PyPep8
                    try:
                        MonthdaySetBuilder(year=2016, month=12).build(temp)
                        result[attr] = temp
                        continue
                    except:
                        raise ValueError(
                            ERR_PERIOD_INVALID_MONTHDAYS.format(
                                str(period[attr])))

        if configuration.NAME not in result:
            raise ValueError(ERR_NAME_PARAM_MISSING)

        for condition in [
                configuration.BEGINTIME, configuration.ENDTIME,
                configuration.WEEKDAYS, configuration.MONTHS,
                configuration.MONTHDAYS
        ]:
            if condition in result:
                break
        else:
            raise ValueError(ERR_NO_PERIODS)

        result[ConfigAdmin.TYPE_ATTR] = configuration.PERIOD

        return result
예제 #7
0
    def test_name(self):
        for i, day_name in enumerate(calendar.day_abbr):
            self.assertEqual(WeekdaySetBuilder().build(day_name), {i})

        for i, day_name in enumerate(calendar.day_name):
            self.assertEqual(WeekdaySetBuilder().build(day_name), {i})
예제 #8
0
 def test_value(self):
     for i in range(0, len(calendar.day_abbr) - 1):
         self.assertEqual(WeekdaySetBuilder().build(str(i)), {i})