Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Add API Gateway frontend and client to kick off the lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
JonZeolla committed Aug 19, 2020
1 parent 2315efa commit f18d41d
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 15 deletions.
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
SHELL := /bin/bash

.PHONY: all
all: lambda

Expand All @@ -6,9 +8,6 @@ requirements: requirements-to-freeze.txt
@python3 -c 'print("Updating requirements.txt...")'
@docker run --rm -v $$(pwd):/usr/src/app/ python:3.8 /bin/bash -c "python -m pip install --upgrade pip && pip install -r /usr/src/app/requirements-to-freeze.txt && pip freeze > /usr/src/app/requirements.txt"

.PHONY: clean
clean: clean-python

.PHONY: clean-python
clean-python:
@# Prepending each recipe with - to continue regardless of errors per
Expand All @@ -18,7 +17,13 @@ clean-python:
@-find . -type d -name '.pytest_cache' -exec rm -rf {} +
@-find . -type f -name '*.pyc' -delete

.PHONY: clean
clean: clean-python

.PHONY: lambda
lambda: clean
@docker run --rm -v $$(pwd):/usr/src/app/ python:3.8 /bin/bash -c "cd /usr/src/app/ && apt-get update && apt-get -y --no-install-recommends install zip && python -m pip install --upgrade pip && zip function.zip lambda_function.py && pip install --target ./package -r requirements.txt && cd package && zip -r9 ../function.zip ."
@echo "docker run --rm -it --env-file <(env | grep AWS_) -v $$(pwd):/usr/src/app/ -v ${HOME}/.aws:/root/.aws easy_infra aws lambda update-function-code --function-name release_monitor --zip-file fileb:///usr/src/app/function.zip"

.PHONY: deploy
deploy: lambda
@docker run --rm --env-file <(env | grep AWS_) -v $$(pwd):/usr/src/app/ -v $${HOME}/.aws:/root/.aws seiso/easy_infra:latest aws lambda update-function-code --function-name release_monitor --zip-file fileb:///usr/src/app/function.zip
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
# Release Monitor

This project uses the unauthenticated GitHub APIs to monitor a provided account/repo for a release containing a provided commit. It is meant to be run as an AWS lambda on a cron, and send an email notification when a release with the provided commit is detected.
This project uses the unauthenticated GitHub APIs to identify if the provided commit is in a stable release for the provided account/repo. It is meant to be run periodically, and send an email notification when a release with the provided commit is detected.

## Prereqs
1. A lambda named "release_monitor", with a "lambda_function.lambda_handler" Handler, and Python 3.8 runtime.
1. An API Gateway attached to the lambda with AWS_IAM authorization required, named "release_monitor", and "Invoke with caller credentials" enabled.
1. Successful authentication to AWS with credentials that have access to lambda and API Gateway. For simplicity, we recommend using [environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html). If your environment uses roles, you may want to consider an approach such as [this](https://github.com/JonZeolla/Configs/blob/a524d572a5426b8cfffad3e5e70d300bfd9b8c90/apple/productivity/.zshrc#L159-L186).

## Quickstart
1. Create a lambda in your AWS account.
1. Auth to AWS via environment variables.
1. Run the following:
1. Make a reusable alias
```bash
alias awsdocker="docker run --rm -it --env-file <(env | grep AWS_) -v \$(pwd):/usr/src/app/ -v \${HOME}/.aws:/root/.aws seiso/easy_infra:latest"
```
1. Build and deploy the lambda.
```bash
make deploy
```
1. Get your REST api ID
```bash
awsdocker "aws apigateway get-rest-apis | jq -r '.[][][\"id\"]'
```
1. Query the lambda via API Gateway.
```bash
make
docker run --rm -it --env-file <(env | grep AWS_) -v $(pwd):/usr/src/app/ -v ${HOME}/.aws:/root/.aws seiso/easy_infra aws lambda update-function-code --function-name release_monitor --zip-file fileb:///usr/src/app/function.zip
ACCOUNT=jonzeolla
REPOSITORY=release_monitor
COMMIT=2315efa04cd4a415916c654f26570a17b9195279
API_ID=example
./client.py --account $ACCOUNT --repository $REPOSITORY --commit $COMMIT --rest-api-id $API_ID
```
80 changes: 80 additions & 0 deletions client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
"""
Client for interacting with the release monitor's API gateway trigger
"""
# pylint: disable=line-too-long

import os
from typing import Dict
from argparse import ArgumentParser
from urllib.parse import urlencode
import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth


def main():
"""Do the thing"""
config = get_args_config()

account = config["account"]
commit = config["commit"]
repository = config["repository"]
method = config["method"]
rest_api_id = config["rest_api_id"]

uri = "/default/release_monitor"
querystring = {
"account": account, # pylint: disable=undefined-variable
"commit": commit, # pylint: disable=undefined-variable
"repository": repository, # pylint: disable=undefined-variable
}
querystring_encoded = urlencode(sorted(querystring.items()))

region = "us-east-1"
host = rest_api_id + ".execute-api." + region + ".amazonaws.com"
url = "https://" + host + uri + "?" + querystring_encoded
service = "execute-api"

# Uses boto logic for auth
auth = BotoAWSRequestsAuth(
aws_host=rest_api_id + ".execute-api." + region + ".amazonaws.com",
aws_region=region,
aws_service=service,
)

response = getattr(requests, method.lower())(url, auth=auth)
print("Request sent. Hope it worked :shrug:")


def get_args_config() -> Dict:
"""
Get the configs passed as arguments
"""
parser = create_arg_parser()
config = vars(parser.parse_args())
return config


def create_arg_parser() -> ArgumentParser:
"""Parse the arguments"""
parser = ArgumentParser()
parser.add_argument(
"--account", type=str, required=True, help="github account",
)
parser.add_argument(
"--repository", type=str, required=True, help="github repository",
)
parser.add_argument(
"--commit", type=str, required=True, help="commitish to monitor for",
)
parser.add_argument(
"--rest-api-id", type=str, required=True, help="The AWS API Gateway REST API ID"
)
parser.add_argument(
"--method", type=str.upper, default="GET", help="HTTP method to use",
)
return parser


if __name__ == "__main__":
main()
38 changes: 33 additions & 5 deletions lambda_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@
from argparse import ArgumentParser
import requests


def lambda_handler(event, context):
"""
AWS Lambda handler
"""
check_for_commit(account=event["account"], repository=event["repository"], commitish=event["commit"])
print(event)
check_for_commit(
account=event["queryStringParameters"]["account"],
repository=event["queryStringParameters"]["repository"],
commitish=event["queryStringParameters"]["commit"],
)


def main():
Expand All @@ -21,25 +27,46 @@ def main():
"""
config = get_args_config()

check_for_commit(account=config["account"], repository=config["repository"], commitish=config["commit"])
check_for_commit(
account=config["account"],
repository=config["repository"],
commitish=config["commit"],
)


def check_for_commit(*, account: str, repository: str, commitish: str) -> bool:
"""
Check a provided account/repo for a commitish
"""
url = "https://api.github.com/repos/" + account + "/" + repository + "/releases/latest"
url = (
"https://api.github.com/repos/"
+ account
+ "/"
+ repository
+ "/releases/latest"
)
headers = {"Accept": "application/vnd.github.v3+json"}

response = requests.get(url, headers=headers)
latest_release_json = response.json()
try:
latest_release_sha = latest_release_json["target_commitish"]
except KeyError:
print("Unable to identify the latest release commitish, are you being rate limited?")
print(
"Unable to identify the latest release commitish, are you being rate limited?"
)
sys.exit(1)

url = "https://api.github.com/repos/" + account + "/" + repository + "/compare/" + commitish + "..." + latest_release_sha
url = (
"https://api.github.com/repos/"
+ account
+ "/"
+ repository
+ "/compare/"
+ commitish
+ "..."
+ latest_release_sha
)

response = requests.get(url, headers=headers)
github_status_json = response.json()
Expand Down Expand Up @@ -79,5 +106,6 @@ def create_arg_parser() -> ArgumentParser:
)
return parser


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions requirements-to-freeze.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
requests
aws-requests-auth
botocore
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
aws-requests-auth==0.4.3
botocore==1.17.46
certifi==2020.6.20
chardet==3.0.4
docutils==0.15.2
idna==2.10
jmespath==0.10.0
python-dateutil==2.8.1
requests==2.24.0
six==1.15.0
urllib3==1.25.10

0 comments on commit f18d41d

Please sign in to comment.