-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DO NOT APPROVE] New deploys #670
Open
iakinsey
wants to merge
18
commits into
temporal
Choose a base branch
from
new_deploys
base: temporal
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
b84eeb1
Some random stuff
freeqaz 011021e
Script for remapping Git block IDs
freeqaz cde925c
Remove extra migration
freeqaz 27ebd8d
Remove version_token
freeqaz 0df64ee
Merge branch 'master' into git-block-remapper-script
freeqaz 16cfea3
Small changes per comments
freeqaz 7097b47
Fix terraform plan output
freeqaz 788a3ac
Merge pull request #663 from refinery-labs/git-block-remapper-script
freeqaz 494541a
Potential fix for session breaking deployments for Mensatech
freeqaz cdd8159
Move grabbing the org_id to above the fold of deployment
freeqaz 76372b1
Merge pull request #664 from refinery-labs/fix-session-weirdness-for-…
freeqaz 6481a4d
Add additional error category for wrapped Lambda functions
freeqaz 2136f90
Merge pull request #665 from refinery-labs/add-extra-error-class-to-l…
freeqaz 6ff2ffd
Resource boilerplate
eb14aea
Add some stuff to aws lambda
4b4ac75
Merge branch 'temporal' into new_deploys
58c9a83
aws lambda resource boilerplate
829ea39
Some stuff
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from functools import cached_property | ||
from hashlib import sha256 | ||
from json import dumps | ||
|
||
|
||
class LambdaConfig: | ||
def __init__(self, name, runtime, code, libraries, env, shared_files, role, memory, handler, is_inline_execution, max_execution_time, tags, layers): | ||
self.name = name | ||
self.runtime = runtime | ||
self.code = code | ||
self.libraries = libraries | ||
self.env = env | ||
self.shared_files = shared_files | ||
self.role = role | ||
self.handler = handler | ||
self.is_inline_execution = is_inline_execution | ||
self.max_execution_time = int(max_execution_time) | ||
self.memory = int(memory) | ||
self.tags = tags | ||
self.layers = layers | ||
self.description = "A Lambda deployed by refinery" | ||
|
||
@cached_property | ||
def uid(self): | ||
attrs = [ | ||
self.name, | ||
self.runtime, | ||
self.code, | ||
dumps(self.libraries, sort_keys=True), | ||
dumps(self.env, sort_keys=True), | ||
dumps(self.shared_files, sort_keys=True), | ||
self.role, | ||
self.handler, | ||
self.is_inline_execution, | ||
self.max_execution_time, | ||
self.memory, | ||
self.tags, | ||
self.layers, | ||
self.description | ||
] | ||
template = '{}' * len(attrs) | ||
return sha256(template.formate(attrs).encode("UTF-8")).hexdigest() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from data_types.aws_api_gateway_config import AwsApiGatewayConfig | ||
from resources.base import Resource | ||
from tasks.api_gateway import create_resource | ||
|
||
|
||
class AWSAPIEndpoint(Resource): | ||
def __init__(self, credentials, config: AwsApiGatewayConfig): | ||
self.credentials = credentials | ||
self.config = config | ||
|
||
def deploy(self): | ||
return create_resource( | ||
self.credentials, | ||
self.config.gateway_id, | ||
self.config.parent_id, | ||
self.config.path_part | ||
) | ||
|
||
def teardown(self): | ||
pass | ||
|
||
def uid(self): | ||
return self.config.uid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
from assistants.decorators import aws_exponential_backoff | ||
from botocore.exceptions import ClientError | ||
from data_types.lambda_config import LambdaConfig | ||
from functools import cached_property | ||
from hashlib import sha256 | ||
from json import dumps | ||
from resources.base import Resource | ||
from tasks.build.temporal.python import Python36Builder | ||
from tasks.build.temporal.nodejs import NodeJs12Builder | ||
from tasks.s3 import s3_object_exists | ||
from utils.shared_files import ( | ||
add_shared_files_symlink_to_zip, add_shared_files_to_zip | ||
) | ||
from utils.wrapped_aws_functions import lambda_delete_function | ||
|
||
|
||
BUILDERS = [ | ||
Python36Builder, | ||
NodeJs12Builder | ||
] | ||
RUNTIME_TO_BUILDER = {b.RUNTIME_PRETTY_NAME: b for b in BUILDERS} | ||
|
||
|
||
class AWSLambda(Resource): | ||
def __init__(self, app_config, aws_client_factory, credentials, lambda_config: LambdaConfig): | ||
self.app_config = app_config | ||
self.aws_client_factory = aws_client_factory | ||
self.credentials = credentials | ||
self.lambda_config = lambda_config | ||
|
||
@property | ||
def builder(self): | ||
return RUNTIME_TO_BUILDER[self.lambda_config.runtime] | ||
|
||
@cached_property | ||
def s3_path(self): | ||
uid_input = bytes("{}{}{}{}".format( | ||
self.lambda_config.runtime, | ||
self.lambda_config.code, | ||
dumps(self.lambda_config.shared_files, sort_keys=True), | ||
sorted(self.lambda_config.libraries), | ||
), encoding='UTF-8') | ||
|
||
return sha256(uid_input).hexdigest() + ".zip" | ||
|
||
@property | ||
def exists_in_s3(self): | ||
return s3_object_exists( | ||
self.aws_client_factory, | ||
self.credentials, | ||
self.credentials["lambda_packages_bucket"], | ||
self.s3_path | ||
) | ||
|
||
@cached_property | ||
def s3_client(self): | ||
return self.aws_client_factory.get_aws_client( | ||
"s3", | ||
self.credentials | ||
) | ||
|
||
@cached_property | ||
def lambda_client(self): | ||
return self.aws_client_factory.get_aws_client( | ||
"lambda", | ||
self.credentials | ||
) | ||
|
||
@property | ||
def uid(self): | ||
return self.lambda_config.uid | ||
|
||
def deploy(self): | ||
zip_data = self.get_zip_data() | ||
self.upload_to_s3(zip_data) | ||
|
||
return self.deploy_lambda() | ||
|
||
def get_zip_data(self): | ||
builder = self.builder( | ||
self.app_config, | ||
self.aws_client_factory, | ||
self.credentials, | ||
self.code, | ||
self.libraries | ||
) | ||
zip_data = builder.build() | ||
|
||
return self.apply_shared_files(zip_data) | ||
|
||
def upload_to_s3(self, zip_data): | ||
if self.exists_in_s3: | ||
return | ||
|
||
# Write it the cache | ||
self.s3_client.put_object( | ||
Key=self.path, | ||
Bucket=self.credentials["lambda_packages_bucket"], | ||
Body=zip_data, | ||
) | ||
|
||
def apply_shared_files(self, zip_data): | ||
if self.lambda_config.is_inline_execution: | ||
return add_shared_files_symlink_to_zip(zip_data) | ||
else: | ||
# If it's an inline execution we don't add the shared files | ||
# folder because we'll be live injecting them into /tmp/ | ||
# Add shared files to Lambda package as well. | ||
return add_shared_files_to_zip(zip_data, self.lambda_config.shared_files) | ||
|
||
@aws_exponential_backoff(allowed_errors=["ResourceConflictException"]) | ||
def deploy_lambda(self): | ||
try: | ||
return self.create_lambda_function() | ||
except ClientError as e: | ||
if e.response["Error"]["Code"] == "ResourceConflictException": | ||
# Delete the existing lambda | ||
lambda_delete_function(self.lambda_client, self.lambda_config.name) | ||
|
||
raise | ||
|
||
def create_lambda_function(self): | ||
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.create_function | ||
response = self.lambda_client.create_function( | ||
FunctionName=self.lambda_config.name, | ||
Runtime=self.lambda_config.runtime, | ||
Role=self.lambda_config.role, | ||
Handler=self.lambda_config.handler, | ||
Code={ | ||
"S3Bucket": self.credentials["lambda_packages_bucket"], | ||
"S3Key": self.s3_path, | ||
}, | ||
Description=self.lambda_config.description, | ||
Timeout=self.lambda_config.max_execution_time, | ||
MemorySize=self.lambda_config.memory, | ||
Publish=True, | ||
VpcConfig={}, | ||
Environment={ | ||
"Variables": self.lambda_config.env.copy() | ||
}, | ||
Tags=self.lambda_config.tags, | ||
Layers=self.lambda_config.layers | ||
) | ||
|
||
return response['FunctionArn'] | ||
|
||
def teardown(self): | ||
lambda_delete_function(self.lambda_client, self.lambda_config.name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from resources.base import Resource | ||
|
||
|
||
class AWSQueue(Resource): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from resources.base import Resource | ||
|
||
|
||
class AWSTimer(Resource): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Resource(ABC): | ||
@abstractmethod | ||
def deploy(self): | ||
pass | ||
|
||
@abstractmethod | ||
def teardown(self): | ||
pass | ||
|
||
@property | ||
@abstractmethod | ||
def uid(self): | ||
pass |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from subprocess import Popen, PIPE | ||
|
||
|
||
def popen_communicate(cmd, cwd=None): | ||
process_handler = Popen( | ||
cmd, | ||
stdout=PIPE, | ||
stderr=PIPE, | ||
shell=False, | ||
universal_newlines=True, | ||
cwd=cwd, | ||
) | ||
|
||
# Returns tuple (stdout, stderr) | ||
return process_handler.communicate() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that all modifications of
self
are done in the properties here, and only really as a performance optimization. That's nice.