Ejemplo n.º 1
0
def _cleanup_old_versions(name):
    logger.info('cleaning up old versions of {0}. Keeping {1}'.format(
        name, REVISIONS))
    versions = _versions(name)
    for version in versions[0:(len(versions) - REVISIONS)]:
        logger.debug('deleting {} version {}'.format(name, version))
        aws_lambda('delete_function', FunctionName=name, Qualifier=version)
Ejemplo n.º 2
0
def deploy(preflight):
    if preflight:
        logger.info('running preflight checks')
        if not preflight_checks():
            return
    logger.info('deploying')
    run()
Ejemplo n.º 3
0
def _load_config(config_filename):
    try:
        with open(config_filename) as config_file:
            logger.info('Using config {}'.format(config_filename))
            return config_file.name, yaml.load(config_file, Loader=yaml.FullLoader)
    except IOError:
        logger.debug('trying to load {} (not found)'.format(config_filename))
        return config_filename, {}
Ejemplo n.º 4
0
def export(prefix, search):
    logger.info('exporting rules')
    kwargs = {"EventBusName": "default"}
    if prefix is not None:
        kwargs["NamePrefix"] = prefix
    if search is not None:
        query = "Rules[?contains(Name, '{0}')] | {{Rules: @}}".format(search)
        kwargs["query"] = query
    rules = events("list_rules", **kwargs)['Rules']
    print(yaml.dump([_export_rule(rule) for rule in rules]))
Ejemplo n.º 5
0
def preflight_checks():
    logger.info('checking aws credentials and region')
    if region() is None:
        logger.error('Region is not set up. please run aws configure')
        return False
    try:
        check_aws_credentials()
    except AttributeError:
        logger.error('AWS credentials not found. please run aws configure')
        return False
    return True
Ejemplo n.º 6
0
def rollback_lambda(name, alias=LIVE):
    all_versions = _versions(name)
    live_version = _get_version(name, alias)
    try:
        live_index = all_versions.index(live_version)
        if live_index < 1:
            raise RuntimeError('Cannot find previous version')
        prev_version = all_versions[live_index - 1]
        logger.info('rolling back to version {}'.format(prev_version))
        _function_alias(name, prev_version)
    except RuntimeError as error:
        logger.error('Unable to rollback. {}'.format(repr(error)))
Ejemplo n.º 7
0
def role():
    new_role = False
    try:
        logger.info('finding role')
        iam('get_role', RoleName='cronyo')
    except ClientError:
        logger.info('role not found. creating')
        iam('create_role',
            RoleName='cronyo',
            AssumeRolePolicyDocument=ASSUMED_ROLE_POLICY)
        new_role = True

    role_arn = iam('get_role', RoleName='cronyo', query='Role.Arn')
    logger.debug('role_arn={}'.format(role_arn))

    logger.info('updating role policy')

    iam('put_role_policy',
        RoleName='cronyo',
        PolicyName='cronyo',
        PolicyDocument=POLICY)

    if new_role:
        from time import sleep
        logger.info('waiting for role policy propagation')
        sleep(5)

    return role_arn
Ejemplo n.º 8
0
def prepare_zip():
    from pkg_resources import resource_filename as resource
    from yaml import dump
    logger.info('creating/updating cronyo.zip')
    with ZipFile('cronyo.zip', 'w', ZIP_DEFLATED) as zipf:
        info = ZipInfo('config.yml')
        info.external_attr = 0o664 << 16
        zipf.writestr(info, dump(config))
        zipf.write(resource('cronyo', 'config.py'), 'config.py')
        zipf.write(resource('cronyo', 'cronyo.py'), 'cronyo.py')
        zipf.write(resource('cronyo', 'logger.py'), 'logger.py')
        for root, dirs, files in os.walk(resource('cronyo', 'vendor')):
            for file in files:
                real_file = os.path.join(root, file)
                relative_file = os.path.relpath(real_file,
                                                resource('cronyo', ''))
                zipf.write(real_file, relative_file)
Ejemplo n.º 9
0
def _function_alias(name, version, alias=LIVE):
    try:
        logger.info('creating function alias {0} for {1}:{2}'.format(
            alias, name, version))
        arn = aws_lambda('create_alias',
                         FunctionName=name,
                         FunctionVersion=version,
                         Name=alias,
                         query='AliasArn')
    except ClientError:
        logger.info('alias {0} exists. updating {0} -> {1}:{2}'.format(
            alias, name, version))
        arn = aws_lambda('update_alias',
                         FunctionName=name,
                         FunctionVersion=version,
                         Name=alias,
                         query='AliasArn')
    return arn
Ejemplo n.º 10
0
def http_post(event, _context):
    logger.info(event)
    url = event["url"]
    headers = event.get("headers", {"User-Agent": "Cronyo"})
    cookies = event.get("cookies", {})
    params = event.get("params", {})
    data = event.get("data", {})
    # secret_key is defined in our config
    secret_key = config["secret_key"]
    # our signature protects the whole url
    t, signature = sign(url, secret_key)
    signature_header = {
        "X-Signature": "t={},signature={}".format(t, signature)
    }
    logger.info("t={},signature={}".format(t, signature))
    headers.update(signature_header)
    data.update({"signature": signature, "t": t}),
    # POSTing a request to the url, and passing the signature and the nonce as header as well as params
    r = requests.post(url,
                      data=data,
                      headers=headers,
                      params=params,
                      cookies=cookies)
    logger.info("response status: {} body: {} headers: {}".format(
        r.status_code, r.text, r.headers))
    return r.status_code
Ejemplo n.º 11
0
def create_update_lambda(role_arn, wiring):
    name, handler, memory, timeout = (wiring[k]
                                      for k in ('FunctionName', 'Handler',
                                                'MemorySize', 'Timeout'))
    try:
        logger.info('finding lambda function')
        function_arn = aws_lambda('get_function',
                                  FunctionName=name,
                                  query='Configuration.FunctionArn')
    except ClientError:
        function_arn = None
    if not function_arn:
        logger.info('creating new lambda function {}'.format(name))
        with open('cronyo.zip', 'rb') as zf:
            function_arn, version = aws_lambda('create_function',
                                               FunctionName=name,
                                               Runtime='python3.8',
                                               Role=role_arn,
                                               Handler=handler,
                                               MemorySize=memory,
                                               Timeout=timeout,
                                               Publish=True,
                                               Code={'ZipFile': zf.read()},
                                               query='[FunctionArn, Version]')
    else:
        logger.info('updating lambda function {}'.format(name))
        aws_lambda('update_function_configuration',
                   FunctionName=name,
                   Runtime='python3.8',
                   Role=role_arn,
                   Handler=handler,
                   MemorySize=memory,
                   Timeout=timeout)
        with open('cronyo.zip', 'rb') as zf:
            function_arn, version = aws_lambda('update_function_code',
                                               FunctionName=name,
                                               Publish=True,
                                               ZipFile=zf.read(),
                                               query='[FunctionArn, Version]')
    function_arn = _function_alias(name, version)
    _cleanup_old_versions(name)
    logger.debug('function_arn={} ; version={}'.format(function_arn, version))
    return function_arn
Ejemplo n.º 12
0
def put(name,
        cron_expression,
        function_name,
        target_input={},
        description=None):

    logger.info("finding lambda function {}".format(function_name))
    target_arn = \
        _get_target_arn(function_name) or \
        _get_target_arn(_namespaced(function_name))
    if not target_arn:
        logger.error("unable to find lambda function for {}".format(function_name))
        return

    logger.debug(
        "create / update cron rule {0}: {1} for target {2}".format(
            name,
            cron_expression,
            target_arn
        )
    )
    if description:
        rule = events("put_rule",
                      Name=name,
                      ScheduleExpression=cron_expression,
                      Description=description)
    else:
        rule = events("put_rule",
                      Name=name,
                      ScheduleExpression=cron_expression)
    events(
        "put_targets",
        Rule=name,
        Targets=[
            {
                "Id": "1",
                "Arn": target_arn,
                "Input": json.dumps(target_input)
            }
        ]
    )
    try:
        logger.debug("setting lambda permission")
        source_arn = rule["RuleArn"]
        if source_arn.find(NAMESPACE) > 0:
            rule_prefix = rule["RuleArn"].split("/{}".format(NAMESPACE))[0]
            source_arn = "{}/{}*".format(rule_prefix, NAMESPACE)
        logger.debug("lambda permission SourceArn:{}".format(source_arn))
        aws_lambda(
            "add_permission",
            FunctionName=target_arn,
            Action="lambda:InvokeFunction",
            Principal="events.amazonaws.com",
            SourceArn=source_arn,
            StatementId=hashlib.sha1(source_arn.encode("utf-8")).hexdigest()
        )
    except ClientError as error:
        logger.debug("permission already set. {}".format(error))

    for rule in _find([name]):
        logger.info("rule created/updated:\n{}".format(yaml.dump(_export_rule(rule))))
Ejemplo n.º 13
0
def delete(name):
    rules = _find([name, _namespaced(name)])
    for rule in rules:
        logger.info("deleting rule:\n{}".format(yaml.dump(_export_rule(rule))))
    _delete(rules)
Ejemplo n.º 14
0
def _enable(rules):
    for rule in rules:
        logger.info("enabling rule {}".format(rule["Name"]))
        events("enable_rule", Name=rule["Name"])
Ejemplo n.º 15
0
def _delete(rules):
    for rule in rules:
        events("remove_targets", Rule=rule["Name"], Ids=["1"])
        events("delete_rule", Name=rule["Name"])
        logger.info("rule {} deleted".format(rule["Name"]))
Ejemplo n.º 16
0
def preflight():
    logger.info('running preflight checks')
    preflight_checks()
Ejemplo n.º 17
0
def configure():
    if not config:
        logger.info('generating new config {}'.format(config_filename))
        generate_config(config_filename)
    click.edit(filename=config_filename)