Beispiel #1
0
def check_cluster_cron(cluster_name):
    """
    Returns False if the cluster is scaled down according to configured variables. Otherwise True.

    :param cluster_name: (str) The name of the cluster to use
    :return: Whether or not we should process the cluster
    """
    # Process as normal if the cluster isn't in the cluster list
    if cluster_name not in SCALE_DOWN_CLUSTERS:
        return True

    # If the cron expressions are invalid process the cluster
    if not croniter.is_valid(SCALE_DOWN_CRON) or not croniter.is_valid(
            SCALE_UP_CRON):
        logger.warning(
            f"Cron expression invalid. Processing {cluster_name} as normal.")
        return True

    # If the cluster scaled down then don't process the cluster
    now = datetime.now()
    last_scale_down = croniter(SCALE_DOWN_CRON, now).get_prev(datetime)
    last_scale_up = croniter(SCALE_UP_CRON, now).get_prev(datetime)
    if last_scale_down > last_scale_up:
        logger.info(f"Cluster {cluster_name} is scaled down. Not processing.")
        return False

    logger.info(f"Cluster {cluster_name} is scaled up. Processing as normal.")
    return True
Beispiel #2
0
def setup_periodic_tasks(sender, **kwargs):
    configurations = ConfigurationLoader().load_by_config_folder()

    for configuration in configurations:
        with Connection(configuration) as connection:
            if connection.has_orm():
                connection.orm.tables.create_tables()

            if connection.has_mongodb():
                connection.mongodb.migrations()

        with open(
                Path.var_folder_path() + '/' + configuration.hash + '.pickle',
                'wb') as handle:
            pickle.dump(configuration,
                        handle,
                        protocol=pickle.HIGHEST_PROTOCOL)

        for configuration_key, aggregationModule in configuration.aggregations.config.items(
        ):
            module = aggregationModule.module
            cron = aggregationModule.cron

            sender.autodiscover_tasks(['modules.aggregation.custom'], module)

            if croniter.is_valid(cron) is True:
                (minute, hour, day_month, month, day_week) = str.split(cron,
                                                                       sep=' ')
                sender.add_periodic_task(
                    crontab(minute, hour, day_week, day_month, month),
                    run, [
                        configuration.hash, configuration_key, module,
                        'modules.aggregation.custom'
                    ],
                    time_limit=aggregationModule.runtime_limit,
                    name='aggregation_' + configuration_key)

        for configuration_key, operationModule in configuration.operations.config.items(
        ):
            module = operationModule.module
            cron = operationModule.cron

            sender.autodiscover_tasks(['modules.operation.custom'], module)

            if croniter.is_valid(cron) is True:
                (minute, hour, day_month, month, day_week) = str.split(cron,
                                                                       sep=' ')
                sender.add_periodic_task(
                    crontab(minute, hour, day_week, day_month, month),
                    run, [
                        configuration.hash, configuration_key, module,
                        'modules.operation.custom'
                    ],
                    time_limit=operationModule.runtime_limit,
                    name='operation_' + configuration_key)
Beispiel #3
0
 def do_crondtc(self, author, channel, serv, message):
     """Cron feature for DTC printing, max 1 minute per loop with no end
     start : lanch cron for DTC, if is not
     stop : cancel cron for DTC, if is start
     next : print time for next cron DTC loop
     update <expression> : change cron DTC frequency, if <expression> is valid"""
     items = message.split()
     if channel in self._cronDTC:
         if message == 'start':
             if self._cronDTC[channel].is_alive():
                 serv.privmsg(channel, 'cronDTC : already start !')
                 self.__prompt('host', '{%alert%}cronDTC : already start !{%default%}')
             else:
                 serv.privmsg(channel, 'cronDTC : start !')
                 self.__prompt('host', '{%alert%}cronDTC : start !{%default%}')
         elif message == 'stop':
             if self._cronDTC[channel].is_alive():
                 serv.privmsg(channel, 'cronDTC : stopped !')
                 self.__prompt('host', '{%alert%}cronDTC : stopped !{%default%}')
             else:
                 serv.privmsg(channel, 'cronDTC : already stopped !')
                 self.__prompt('host', '{%alert%}cronDTC : already stopped !{%default%}')
         elif items[0] == 'update':
             items.pop(0)
             if len(items) > 5:
                 serv.privmsg(channel, 'cronDTC : update refuse ! (possible abuse frequency)')
                 self.__prompt('host', '{%alert%}cronDTC : update refuse ! (possible abuse frequency){%default%}')
             elif croniter.is_valid(' '.join(items[:5])):
                 self._cronDTC[channel].expanded, self._cronDTC[channel].nth_weekday_of_month = croniter.expand(' '.join(items[:5]))
             else:
                 serv.privmsg(channel, 'cronDTC : update refuse !')
                 self.__prompt('host', '{%alert%}cronDTC : update refuse !{%default%}')
         elif message == 'next':
             if self._cronDTC[channel].is_alive():
                 _next = delai(datetime.fromtimestamp(self._cronDTC[channel].get_current()))
                 serv.privmsg(channel, 'cronDTC : next in {next} !'.format(next = _next))
                 self.__prompt('host', '{%alert%}cronDTC : next in {next} !{%default%}', next = _next)
         else:
             return False
     else:
         if not message:
             self._cronDTC[channel] = cron(target = self.do_dtc, expr_format = '0 * * * *', args = (self._name, channel, serv, ''))
         elif croniter.is_valid(' '.join(items[:5])):
             self._cronDTC[channel] = cron(target = self.do_dtc, expr_format = ' '.join(items[:5]), args = (self._name, channel, serv, ''))
         else:
             return False
         self._cronDTC[channel].start()
         serv.privmsg(channel, 'cronDTC : start !')
         self.__prompt('host', '{%alert%}cronDTC : start !{%default%}')
     return True
Beispiel #4
0
    def validate(self, attrs):
        if 'schedule_type' in attrs:
            schedule_type = attrs['schedule_type']
        else:
            schedule_type = self.instance['schedule_type']

        value = attrs.get('schedule')
        if not value:
            return attrs

        if schedule_type == ScheduleType.INTERVAL:
            # type: [int count, str unit name]
            if not isinstance(value, list):
                raise ValidationError('Invalid value for schedule_type')
            if not isinstance(value[0], int):
                raise ValidationError(
                    'Invalid value for schedule unit count (index 0)')
            if value[1] not in INTERVAL_NAMES:
                raise ValidationError(
                    'Invalid value for schedule unit name (index 1)')
        elif schedule_type == ScheduleType.CRONTAB:
            # type: str schedule
            if not isinstance(value, six.string_types):
                raise ValidationError('Invalid value for schedule_type')
            value = value.strip()
            if value.startswith('@'):
                try:
                    value = NONSTANDARD_CRONTAB_SCHEDULES[value]
                except KeyError:
                    raise ValidationError('Schedule was not parseable')
            if not croniter.is_valid(value):
                raise ValidationError('Schedule was not parseable')
            attrs['schedule'] = value
        return attrs
Beispiel #5
0
    def __init__(self,
                 id,
                 update,
                 interval,
                 name,
                 user_id,
                 tz,
                 command,
                 context=[],
                 last_run=None,
                 next_run=None,
                 total_run_count=0,
                 *args,
                 **kwargs):

        self._id = id
        self._update = update
        self._name = name
        self._user_id = user_id
        self._tz = tz
        # validate cron interval
        if not croniter.is_valid(interval):
            raise ValueError("The 'interval' value is not valid")
        self._interval = interval
        self._command = command
        self._context = context
        self._last_run = last_run
        self._next_run = next_run
        self._total_run_count = total_run_count
    def crontab_config_filter(self, trigger_time, crontab_config):
        '''
        Crontab执行时机过滤函数

        算法描述如下:

        trigger_time - 1m             trigger_time
        |                             |    实际Starter执行时间(比trigger_time晚1秒,此时计算出trigger_time)
        |                             | 1s |
        |                             |    |
        +-----------------------------+====+------------> Future
        ^                             ^
        |                             |
        |                             start_time(需要执行的Crontab任务)
        |
        start_time(不需要执行的Crontab任务)

        即:只有启动点大于等于当前触发点的才需要执行
        '''
        crontab_expr = crontab_config['crontab']

        if not crontab_expr:
            return False

        if not croniter.is_valid(crontab_expr):
            return False

        now = arrow.get(trigger_time + 1).to('Asia/Shanghai').datetime
        crontab_iter = croniter(crontab_expr, now)

        start_time = int(crontab_iter.get_prev())
        return start_time >= trigger_time
Beispiel #7
0
def create_cron_job(cron_job):
    # check cron_job does't exists first
    cron_job_exists = mongo_connection.mongo_check_cron_job_exists(cron_job)
    if cron_job_exists is True:
        return jsonify({"cron_job_exists": True}), 403
    else:
        # check the request is passed with all needed parameters
        try:
            cron_job_json = request.json
            schedule = cron_job_json["schedule"]
            env_vars = return_sane_default_if_not_declared(
                "env_vars", cron_job_json, {})
            docker_image = cron_job_json["docker_image"]
            running = return_sane_default_if_not_declared(
                "running", cron_job_json, True)
            networks = return_sane_default_if_not_declared(
                "networks", cron_job_json, [])
            volumes = return_sane_default_if_not_declared(
                "volumes", cron_job_json, [])
            devices = return_sane_default_if_not_declared(
                "devices", cron_job_json, [])
            privileged = return_sane_default_if_not_declared(
                "privileged", cron_job_json, False)
        except:
            return json.dumps(
                find_missing_params(cron_job_json,
                                    ["docker_image", "schedule"])), 400
        # check edge case where schedule is not valid
        if croniter.is_valid(schedule) is False:
            return jsonify({"schedule_valid": False}), 400
        # update the db
        cron_job_json = mongo_connection.mongo_add_cron_job(
            cron_job, schedule, env_vars, docker_image, running, networks,
            volumes, devices, privileged)
        return dumps(cron_job_json), 200
Beispiel #8
0
    def post(self, project_id):
        '''
        Create new cronjob
        '''
        b = request.get_json()

        if not CronJobs.name_pattern.match(b['name']):
            abort(400, 'CronJob name must be not empty alphanumeric string.')

        if not croniter.is_valid('%s %s %s %s %s' % (b['minute'], b['hour'], b['day_month'], b['month'], b['day_week'])):
            abort(400, 'Invalid input expression')

        result = g.db.execute_one_dict("""
            SELECT COUNT(*) as cnt FROM cronjob WHERE project_id = %s
        """, [project_id])

        if result['cnt'] > 50:
            abort(400, 'Too many cronjobs.')

        r = g.db.execute_one("""
                    SELECT count(*) FROM cronjob
                    WHERE project_id = %s AND name = %s
                """, [project_id, b['name']])

        if r[0] > 0:
            abort(400, 'CronJob with this name already exist')

        g.db.execute('''
            INSERT INTO cronjob (project_id, name, minute, hour, day_month, month, day_week, sha, infrabox_file) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s)
        ''', [project_id, b['name'], b['minute'], b['hour'], b['day_month'], b['month'], b['day_week'], b['sha'], b['infrabox_file']])

        g.db.commit()

        return OK('Successfully added CronJob.')
Beispiel #9
0
    def validate(self, attrs):
        if "schedule_type" in attrs:
            schedule_type = attrs["schedule_type"]
        else:
            schedule_type = self.instance["schedule_type"]

        value = attrs.get("schedule")
        if not value:
            return attrs

        if schedule_type == ScheduleType.INTERVAL:
            if not isinstance(value, list):
                raise ValidationError("Invalid value for schedule_type")
            if not isinstance(value[0], int):
                raise ValidationError(
                    "Invalid value for schedule unit count (index 0)")
            if value[1] not in INTERVAL_NAMES:
                raise ValidationError(
                    "Invalid value for schedule unit name (index 1)")
        elif schedule_type == ScheduleType.CRONTAB:
            if not isinstance(value, six.string_types):
                raise ValidationError("Invalid value for schedule_type")
            value = value.strip()
            if value.startswith("@"):
                try:
                    value = NONSTANDARD_CRONTAB_SCHEDULES[value]
                except KeyError:
                    raise ValidationError("Schedule was not parseable")
            if not croniter.is_valid(value):
                raise ValidationError("Schedule was not parseable")
            attrs["schedule"] = value
        return attrs
Beispiel #10
0
def validate_cronjob_format(schedule):
    """
    validates if the cronjob schedule provided is valid
    :param schedule: input schedule
    :return: True/False
    """
    return croniter.is_valid(schedule)
Beispiel #11
0
    def validate_schedule(self, attrs, source):
        if 'schedule_type' in attrs:
            schedule_type = attrs['schedule_type']
        else:
            schedule_type = self.object['schedule_type']

        value = attrs[source]
        if not value:
            return attrs

        if schedule_type == ScheduleType.INTERVAL:
            if not isinstance(value, list):
                raise ValidationError('Invalid value for schedule_type')
            if not isinstance(value[0], int):
                raise ValidationError('Invalid value for schedule frequency')
            if value[1] not in INTERVAL_NAMES:
                raise ValidationError('Invalid value for schedlue interval')
        elif schedule_type == ScheduleType.CRONTAB:
            if not isinstance(value, six.string_types):
                raise ValidationError('Invalid value for schedule_type')
            value = value.strip()
            if value.startswith('@'):
                try:
                    value = NONSTANDARD_CRONTAB_SCHEDULES[value]
                except KeyError:
                    raise ValidationError('Schedule was not parseable')
            if not croniter.is_valid(value):
                raise ValidationError('Schedule was not parseable')
            attrs[source] = value
        return attrs
Beispiel #12
0
def update_cron_job_all_fields(cron_job):
    # check cron_job exists first
    cron_job_exists = mongo_connection.mongo_check_cron_job_exists(cron_job)
    if cron_job_exists is False:
        return jsonify({"cron_job_exists": False}), 403
    # check cron_job got update parameters
    try:
        cron_job_json = request.json
        if len(cron_job_json) == 0:
            return jsonify({"missing_parameters": True}), 400
        if cron_job_json["docker_image"] is None or cron_job_json["schedule"] is None:
            return json.dumps(find_missing_params(cron_job_json, ["docker_image", "schedule"])), 400
    except:
        return jsonify({"missing_parameters": True}), 400
    # set default for undeclared params
    try:
        cron_job_json["env_vars"] = return_sane_default_if_not_declared("env_vars", cron_job_json, {})
        cron_job_json["running"] = return_sane_default_if_not_declared("running", cron_job_json, True)
        cron_job_json["volumes"] = return_sane_default_if_not_declared("volumes", cron_job_json, [])
        cron_job_json["devices"] = return_sane_default_if_not_declared("devices", cron_job_json, [])
        cron_job_json["privileged"] = return_sane_default_if_not_declared("privileged", cron_job_json, False)
        cron_job_json["networks"] = return_sane_default_if_not_declared("networks", cron_job_json, ["nebula", "bridge"])
    except:
        return json.dumps(find_missing_params(cron_job_json, ["docker_image", "schedule"])), 400
    # check edge case of port being outside of possible port ranges in case trying to update port listing
    try:
        schedule = request.json["schedule"]
        # check edge case where schedule is not valid
        if croniter.is_valid(schedule) is False:
            return jsonify({"schedule_valid": False}), 400
    except:
        pass
    # update db
    cron_job_json = mongo_connection.mongo_update_cron_job_fields(cron_job, request.json)
    return dumps(cron_job_json), 202
Beispiel #13
0
    def __init__(self, config):
        self._startup_run_done = False

        if config.schedule is None:
            self.mode = ScheduleMode.once
            self.run_at_startup = True
        else:
            try:
                self.interval = int(config.schedule)
                self.cron = None
                self.mode = ScheduleMode.interval
                self.run_at_startup = config.run_at_startup if config.run_at_startup is not None else True
            except ValueError:
                self.interval = None
                self.cron = config.schedule
                self.mode = ScheduleMode.cron
                self.run_at_startup = config.run_at_startup if config.run_at_startup is not None else False

        if self.mode == ScheduleMode.interval:
            if self.interval <= 0:
                raise ValueError("Interval must be at least one second!")

        if self.mode == ScheduleMode.cron:
            self.schedule_hash_id = str.encode(
                config.schedule_hash_id if config.schedule_hash_id is not None else socket.getfqdn())

            if not croniter.is_valid(self.cron, hash_id=self.schedule_hash_id):
                raise ValueError("Invalid cron expression!")
Beispiel #14
0
    def __init__(self, task=None, schedule=None, args=(), kwargs={}):
        # Task needs to be callable
        if not callable(task):
            raise TypeError("{} is not callable".format(task))

        # Validate cron schedule
        if not croniter.is_valid(schedule):
            raise ValueError(
                "'{}' is not a valid cron string.".format(schedule))

        # Validate args
        if args is not None and not isinstance(args, tuple) and not isinstance(
                args, list):
            raise InvalidSignatureException(
                "Args must be a tuple or list, got {}".format(args))

        # Marshall args to tuple
        if isinstance(args, list):
            args = tuple(args)

        # Validate kwargs
        if kwargs is not None and not isinstance(kwargs, dict):
            raise InvalidSignatureException(
                "Kwargs must be a dict, got {}".format(kwargs))

        self.task = task
        self.schedule = schedule
        self.next_run = datetime.fromtimestamp(
            croniter(schedule, datetime.now()).get_next())
        self.args = args
        self.kwargs = kwargs
Beispiel #15
0
    async def check_schedule(self, ctx):
        table = []
        for k, v in self.userdata.items():
            if ctx.guild.id != v["server_id"]:
                continue
            # get next running
            run_at = self._strftime(
                croniter(v["schedule"],
                         self._now()).get_next(dt)) if croniter.is_valid(
                             v["schedule"]) else None
            # get target channel
            run_on = self.bot.get_channel(
                v["channel_id"]
            ) if "channel_id" in v.keys() and v["channel_id"] else None
            # get author
            author = await ctx.guild.fetch_member(v["author"])
            author_name = author.nick if author else "Unknown"
            table.append([run_at, run_on, k, author_name])

        if len(table):
            formatted_table = tabulate(
                table, ["次回実行日時", "実行先チャンネル", "スケジュール名", "登録した人"],
                tablefmt="simple")
            await ctx.send(
                f":bulb: 直近の実行タイミングは次の通りです。\n```{formatted_table}```")
        else:
            await ctx.send(":bulb: 登録されているスケジュールはありません。")
Beispiel #16
0
    def __call__(self, value) -> typing.Any:
        message = f'The schedule_interval expression `{value}` must be a valid CRON expression: ' \
                  'validate it here https://crontab.guru/'
        if not croniter.is_valid(value):
            raise validate.ValidationError(message)

        return value
Beispiel #17
0
 def __init__(self, cron: str = None):
     # validates if cron is a valid string
     if cron and not croniter.is_valid(cron):
         raise ValueError(f'''
           Invalid cron string: `{cron}`. For help, consult `crontab.guru.com`
           ''')
     self.cron = cron
Beispiel #18
0
 def validate_schedule(value):
     '''
     校验 schedule 是否合法
     '''
     if croniter.is_valid(value):
         return value
     raise ValidationError
Beispiel #19
0
    def validate_schedule(self, attrs, source):
        if 'schedule_type' in attrs:
            schedule_type = attrs['schedule_type']
        else:
            schedule_type = self.object['schedule_type']

        value = attrs[source]
        if not value:
            return attrs

        if schedule_type == ScheduleType.INTERVAL:
            # type: [int count, str unit name]
            if not isinstance(value, list):
                raise ValidationError('Invalid value for schedule_type')
            if not isinstance(value[0], int):
                raise ValidationError('Invalid value for schedule unit count (index 0)')
            if value[1] not in INTERVAL_NAMES:
                raise ValidationError('Invalid value for schedlue unit name (index 1)')
        elif schedule_type == ScheduleType.CRONTAB:
            # type: str schedule
            if not isinstance(value, six.string_types):
                raise ValidationError('Invalid value for schedule_type')
            value = value.strip()
            if value.startswith('@'):
                try:
                    value = NONSTANDARD_CRONTAB_SCHEDULES[value]
                except KeyError:
                    raise ValidationError('Schedule was not parseable')
            if not croniter.is_valid(value):
                raise ValidationError('Schedule was not parseable')
            attrs[source] = value
        return attrs
Beispiel #20
0
 def _check_schedule(self):
     if self.interval and self.schedule:
         raise InvalidQuerySchedule(
             self.name, "both interval and schedule specified"
         )
     if self.schedule and not croniter.is_valid(self.schedule):
         raise InvalidQuerySchedule(self.name, "invalid schedule format")
Beispiel #21
0
 def wrapper(*args, **kwargs):
     cron = kwargs.get('cron', None)
     if not isinstance(cron, str):
         raise TypeError("invalid cron")
     if not croniter.is_valid(cron):
         raise ValueError("Invalid cron specified {}".format(cron))
     return func(*args, **kwargs)
Beispiel #22
0
 async def add_schedule(self, ctx, name, m, h, dom, mon, dow, *cmd):
     crontab = " ".join([m, h, dom, mon, dow])
     escaped_cmds = None
     if not croniter.is_valid(crontab):
         await ctx.send(f":x: スケジュール `{crontab}` が不正です。")
         return
     else:
         if not self._dig(list(cmd)):
             await ctx.send(
                 ":x: 他Botのコマンドまたは正しくないコマンドは定時実行ができないので登録しませんでした。")
             logger.debug("Specified command could not scheduled.")
             return
         escaped_cmds = " ".join((f'"{i}"' if " " in i else i for i in cmd))
         self.userdata[name] = {
             "command": escaped_cmds,
             "server_id": ctx.guild.id,
             "channel_id": ctx.channel.id,
             "author": ctx.message.author.id,
             "schedule": crontab,
         }
         await self._save_userdata()
         logger.debug("Specified command scheduled successfully.")
     next_run = self._strftime(croniter(crontab, self._now()).get_next(dt))
     await ctx.send(f":white_check_mark: スケジュール `{name}` を追加しました。\n"
                    f"次回実行予定は {next_run} です。\n"
                    f"実行されるコマンドは `{escaped_cmds}` です。")
Beispiel #23
0
def check_invalid(window, values):
    invalid = False

    if re.search(
            "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+",
            window["link"].get(),
    ):
        window["invalid_link"].update(visible=False)
    else:
        invalid = True
        window["invalid_link"].update(visible=True)

    if re.search("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+",
                 window["recipient"].get()):
        window["invalid_recipient"].update(visible=False)
    else:
        window["invalid_recipient"].update(visible=True)
        invalid = True

    if values["content_type"] in ["text/plain", "text/html"]:
        window["invalid_type"].update(visible=False)
    else:
        window["invalid_type"].update(visible=True)
        invalid = True

    if croniter.is_valid(values["frequency"]):
        window["invalid_cron"].update(visible=False)
    else:
        window["invalid_cron"].update(visible=True)
        invalid = True

    return invalid
Beispiel #24
0
    def _update_current_crontab_schedule(self):
        # select not execute record from journal
        query = sql.SQL('SELECT {} FROM {} WHERE {}').format(
            sql.SQL(', ').join(map(sql.Identifier, ('id', 'type', 'plan'))),
            sql.Identifier(self._table_name),
            sql.SQL('{} = {} AND {} > {} AND {} is Null').format(
                sql.Identifier('status'), sql.Literal(self.JobStatus.TODO),
                sql.Identifier('plan'), sql.Literal(datetime.now()),
                sql.Identifier('params')
            )
        )

        cursor = self._db_conn.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
        cursor.execute(query)
        rows = cursor.fetchall()
        rows = rows if rows else list()  # change None to empty list

        # id, type, start and valid state (used later)
        schedule = [[row.id, row.type, row.plan, False] for row in rows]

        # check current crontab schedule from script
        for activity_type, params in self._registry.items():
            cron_tab = params['crontab'] or ''
            if not croniter.is_valid(cron_tab):
                continue
            next_plan = croniter(params['crontab'], datetime.now()).get_next(datetime)
            need_to_plan = True
            for rec in schedule:
                if rec[1] == activity_type:
                    if next_plan == rec[2]:
                        rec[3] = True
                        need_to_plan = False
                        break
            if need_to_plan:
                insert_params = {
                    'type': activity_type,
                    'status': 'todo',
                    'plan': next_plan,
                }
                insert_new_schedule_query =\
                    sql.SQL('insert into {}({}) values({})').format(
                        sql.Identifier(self._table_name),
                        sql.SQL(', ').join(sql.Identifier(field) for field in insert_params.keys()),
                        sql.SQL(', ').join(sql.Literal(value) for value in insert_params.values())
                    )
                cursor.execute(insert_new_schedule_query)
                self._db_conn.commit()

        # prepare journal record list for removing
        rec_for_delete = [rec[0] for rec in schedule if not rec[3]]
        # and removing them
        if len(rec_for_delete):
            delete_not_valid_record_query = sql.SQL('DELETE FROM {} WHERE {} IN ({})').format(
                sql.Identifier(self._table_name),
                sql.Identifier('id'),
                sql.SQL(', ').join(sql.Literal(_id) for _id in rec_for_delete)
            )
            cursor.execute(delete_not_valid_record_query)
            self._db_conn.commit()
Beispiel #25
0
def job_load(entry, job):
    jid = None
    if 'run_interval' in job or 'run_cron' in job:
        if 'id' in job:
            jid = job['id']
            del job['id']
        if not jid or jid in entry.data['jobs']:
            #jid = ((job['group'] + '.') if 'group' in job and job['group'] else ((job['entry_id'] + '.') if 'entry_id' in job and job['entry_id'] else '')) + hashlib.sha1((str(i) + ':' + str(job)).encode('UTF-8')).hexdigest()[:16]
            i = 0
            while True:
                jid = ((job['group'] +
                        '.') if 'group' in job and job['group'] else
                       ((job['entry_id'] + '.') if 'entry_id' in job
                        and job['entry_id'] else '')) + hashlib.sha1(
                            (str(job)).encode('UTF-8')).hexdigest()[:16] + (
                                ('_' + str(i)) if i else '')
                if not (jid in entry.data['jobs']):
                    break
                i = i + 1
        if jid in entry.scheduler_oldjobs:
            job = {**entry.scheduler_oldjobs[jid], **job}

        if 'do' in job and isinstance(job['do'], str):
            job['do'] = [job['do']]
        if 'enabled' not in job:
            job['enabled'] = True
        if 'max_delay' not in job:
            job['max_delay'] = 60 if 'run_cron' in job else 0
        job['max_delay'] = utils.read_duration(job['max_delay'])
        if 'timer_to' not in job:
            job['timer_to'] = 0
        if 'last_run' not in job:
            job['last_run'] = 0
        if 'run_interval' in job:
            job['run_interval'] = utils.read_duration(job['run_interval'])
            if job['run_interval'] <= 0:
                job = False
        if job and 'run_cron' in job and not croniter.is_valid(
                job['run_cron']):
            logging.error(
                '#{id}> invalid cron rule: {cron} in job: {job}'.format(
                    id=entry.id, cron=job['run_cron'], job=job))
            job = False
        if job:
            if 'next_run' not in job or (
                    job['max_delay'] > 0
                    and system.time() >= job['next_run'] + job['max_delay']):
                job_set_next_run(job)
            entry.data['jobs'][jid] = job

            if 'group' in job and job[
                    'group'] and not job['group'] in entry.data['groups']:
                entry.data['groups'][job['group']] = {
                    'enabled': True,
                    'timer_to': 0
                } if job[
                    'group'] not in entry.scheduler_oldgroups else entry.scheduler_oldgroups[
                        job['group']]
    return jid
Beispiel #26
0
 def __init__(
     self, cron: str, start_date: datetime = None, end_date: datetime = None
 ):
     # build cron object to check the cron string - will raise an error if it's invalid
     if not croniter.is_valid(cron):
         raise ValueError("Invalid cron string: {}".format(cron))
     self.cron = cron
     super().__init__(start_date=start_date, end_date=end_date)
Beispiel #27
0
    def interval(self, value):
        if value is None:
            raise ValueError("The 'interval' can not be None")

        if not croniter.is_valid(value):
            raise ValueError("The 'interval' value is not valid")

        self._interval = value
    def pre_add(self, item: "AlertModelView") -> None:
        item.recipients = get_email_address_str(item.recipients)

        if not croniter.is_valid(item.crontab):
            raise SupersetException("Invalid crontab format")

        item.validator_type = item.validator_type.lower()
        check_validator(item.validator_type, item.validator_config)
Beispiel #29
0
 def __init__(self, name, cron, kids=False):
     if not croniter.is_valid(cron):
         raise ValueError(
             "cron was not valid cron sytax. Should be in min hour day" +
             " month day_of_week, instead was {}".format(cron))
     self.name = name
     self.cron = cron
     self.kids = kids
Beispiel #30
0
def is_cron(key, val):
    """
    Check crontab syntax or ``None``.
    """
    if val is None:
        return
    assert croniter.is_valid(val), "[{}] expected cron syntax or None".format(
        key)
Beispiel #31
0
def main():
    parser = argparse.ArgumentParser(
        description='Tool for running and initializing backup container')
    parser.add_argument('-i',
                        '--initialize',
                        action='store_true',
                        help='configure cron and install dependencies')
    parser.add_argument('-r',
                        '--run',
                        action='store_true',
                        help='runs scrips following the lifecycle')
    parser.add_argument('-csp',
                        '--container-scripts-path',
                        default='/scripts',
                        help='path to scripts folder, default /scripts')
    parser.add_argument(
        '-c',
        '--cron-path',
        default='/etc/crontabs/root',
        help='path to scripts folder, default /etc/crontabs/root')

    arguments = parser.parse_args()

    if CRON_BACKUP_SCHEDULE not in os.environ:
        print_logger("Could not find '%s' in the environment variables" %
                     CRON_BACKUP_SCHEDULE)
        exit(1)

    if not croniter.is_valid(os.environ[CRON_BACKUP_SCHEDULE]):
        print_logger("Provided cron schedule '%s' is not valid" %
                     os.environ[CRON_BACKUP_SCHEDULE])
        exit(1)

    # check if provided directory exists
    if not os.path.isdir(arguments.container_scripts_path):
        print_logger("The following path '%s' is not a valid directory" %
                     arguments.container_scripts_path)
        exit(1)

    if not arguments.initialize and not arguments.run:
        print_logger(
            "Nothing to do.\nPlease run: 'fridge --help' to see possible options"
        )
        exit(1)

    scripts_detector = ScriptsDetector(arguments.container_scripts_path)
    scripts_detector.list_detected_scripts()

    if arguments.initialize:
        print_logger("Initializing...")
        start_initialize(scripts_detector, arguments.cron_path)
        print_logger("Initialization complete.")

    if arguments.run:
        print_logger("Running...")
        start_run(scripts_detector)
        print_logger("Finished running.")
Beispiel #32
0
    def pre_add(self, obj):
        try:
            recipients = get_email_address_list(obj.recipients)
            obj.recipients = ', '.join(recipients)
        except Exception:
            raise SupersetException('Invalid email list')

        obj.user = obj.user or g.user
        if not croniter.is_valid(obj.crontab):
            raise SupersetException('Invalid crontab format')
Beispiel #33
0
    def pre_add(self, obj):
        try:
            recipients = get_email_address_list(obj.recipients)
            obj.recipients = ", ".join(recipients)
        except Exception:
            raise SupersetException("Invalid email list")

        obj.user = obj.user or g.user
        if not croniter.is_valid(obj.crontab):
            raise SupersetException("Invalid crontab format")
Beispiel #34
0
 def __init__(self, target, args, expr_format):
     if croniter.is_valid(expr_format):
         Thread.__init__(self)
         self.__target = target
         self.__args = args
         croniter.__init__(self, expr_format)
         self.get_next()
         self.__forceStop = False
         self.__initialized = True
     else:
         self = None
Beispiel #35
0
 def _validate(self, name, start, schedule_type, arguments, repeat, duration, end):
     if name is None or not isinstance(name, basestring) or name.strip() == '':
         raise RuntimeError('A schedule must have a name')
     # Check whether the requested type is valid
     accepted_types = ['GROUP_ACTION', 'BASIC_ACTION', 'LOCAL_API']
     if schedule_type not in accepted_types:
         raise RuntimeError('Unknown schedule type. Allowed: {0}'.format(', '.join(accepted_types)))
     # Check duration/repeat/end combinations
     if repeat is None:
         if end is not None:
             raise RuntimeError('No `end` is allowed when it is a non-repeated schedule')
     else:
         if not croniter.is_valid(repeat):
             raise RuntimeError('Invalid `repeat`. Should be a cron-style string. See croniter documentation')
     if duration is not None and duration <= 60:
         raise RuntimeError('If a duration is specified, it should be at least more than 60s')
     # Type specifc checks
     if schedule_type == 'BASIC_ACTION':
         if duration is not None:
             raise RuntimeError('A schedule of type BASIC_ACTION does not have a duration. It is a one-time trigger')
         if not isinstance(arguments, dict) or 'action_type' not in arguments or not isinstance(arguments['action_type'], int) or \
                 'action_number' not in arguments or not isinstance(arguments['action_number'], int) or len(arguments) != 2:
             raise RuntimeError('The arguments of a BASIC_ACTION schedule must be of type dict with arguments `action_type` and `action_number`')
     elif schedule_type == 'GROUP_ACTION':
         if duration is not None:
             raise RuntimeError('A schedule of type GROUP_ACTION does not have a duration. It is a one-time trigger')
         if not isinstance(arguments, int) or arguments < 0 or arguments > 254:
             raise RuntimeError('The arguments of a GROUP_ACTION schedule must be an integer, representing the Group Action to be executed')
     elif schedule_type == 'LOCAL_API':
         if duration is not None:
             raise RuntimeError('A schedule of type LOCAL_API does not have a duration. It is a one-time trigger')
         if not isinstance(arguments, dict) or 'name' not in arguments or 'parameters' not in arguments or not isinstance(arguments['parameters'], dict):
             raise RuntimeError('The arguments of a LOCAL_API schedule must be of type dict with arguments `name` and `parameters`')
         func = getattr(self._web_interface, arguments['name']) if hasattr(self._web_interface, arguments['name']) else None
         if func is None or not callable(func) or not hasattr(func, 'plugin_exposed') or getattr(func, 'plugin_exposed') is False:
             raise RuntimeError('The arguments of a LOCAL_API schedule must specify a valid and (plugin_)exposed call')
         check = getattr(func, 'check')
         if check is not None:
             params_parser(arguments['parameters'], check)
Beispiel #36
0
def trigger(site, event, last=None, queued_jobs=(), now=False):
    """Trigger method in hooks.scheduler_events."""

    queue = 'long' if event.endswith('_long') else 'short'
    timeout = queue_timeout[queue]
    if not queued_jobs and not now:
        queued_jobs = get_jobs(site=site, queue=queue)

    if frappe.flags.in_test:
        frappe.flags.ran_schedulers.append(event)

    events_from_hooks = get_scheduler_events(event)
    if not events_from_hooks:
        return

    events = events_from_hooks
    if not now:
        events = []
        if event == "cron":
            for e in events_from_hooks:
                e = cron_map.get(e, e)
                if croniter.is_valid(e):
                    if croniter(e, last).get_next(datetime) <= frappe.utils.now_datetime():
                        events.extend(events_from_hooks[e])
                else:
                    frappe.log_error("Cron string " + e + " is not valid", "Error triggering cron job")
                    frappe.logger(__name__).error('Exception in Trigger Events for Site {0}, Cron String {1}'.format(site, e))

        else:
            if croniter(cron_map[event], last).get_next(datetime) <= frappe.utils.now_datetime():
                events.extend(events_from_hooks)

    for handler in events:
        if not now:
            if handler not in queued_jobs:
                enqueue(handler, queue, timeout, event)
        else:
            scheduler_task(site=site, event=event, handler=handler, now=True)
Beispiel #37
0
 def test_invalid_zerorepeat(self):
     self.assertFalse(croniter.is_valid('*/0 * * * *'))
Beispiel #38
0
 def test_is_valid(self):
     self.assertTrue(croniter.is_valid('0 * * * *'))
     self.assertFalse(croniter.is_valid('0 * *'))
     self.assertFalse(croniter.is_valid('* * * janu-jun *'))