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)
def deploy(preflight): if preflight: logger.info('running preflight checks') if not preflight_checks(): return logger.info('deploying') run()
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, {}
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]))
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
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)))
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
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)
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
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
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
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))))
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)
def _enable(rules): for rule in rules: logger.info("enabling rule {}".format(rule["Name"])) events("enable_rule", Name=rule["Name"])
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"]))
def preflight(): logger.info('running preflight checks') preflight_checks()
def configure(): if not config: logger.info('generating new config {}'.format(config_filename)) generate_config(config_filename) click.edit(filename=config_filename)