-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: contract based deployments (#379)
* feat: contract based deployments adds support in the cli for running deployments using contracts instead of bash scripts This allows for the engine to control how the deployment is run and also lets the python executor look after making it happen Current implementation handles cloudformation deployments using either Change Sets or standard stack updates. Using standard stack updates should reduce some of the processing time when running deployments that don't need change sets. Also supports presigned url hosting of cloudformation templates so that we can use larger template sizes To make the bites to chomp off smaller there is a utility function which calls the bash executor to return the cf_dir so that we don't have to fully replicate the context lookup to get this going * feat: extend file management and cfn stacks * chore: formatting updates * fix: test mocks * fix: test mocks * chore: flake fixup * fix: disable the cli pager in commands
- Loading branch information
1 parent
392a648
commit d88000a
Showing
28 changed files
with
696 additions
and
251 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -1 +1 @@ | ||
3.11.1 | ||
3.11.7 |
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,46 @@ | ||
from hamlet.backend.common.exceptions import BackendException | ||
|
||
|
||
class CloudFormationStackException(BackendException): | ||
|
||
def __init__(self, stack_name, cfn_client, client_request_token): | ||
self.stack_name = stack_name | ||
|
||
stack_events = [ | ||
"* " | ||
+ " - ".join( | ||
[ | ||
stack_event["LogicalResourceId"], | ||
stack_event["ResourceType"], | ||
stack_event["ResourceStatus"], | ||
stack_event.get("ResourceStatusReason", ""), | ||
] | ||
) | ||
for sublist in [ | ||
x["StackEvents"] | ||
for x in cfn_client.get_paginator("describe_stack_events").paginate( | ||
StackName=self.stack_name | ||
) | ||
] | ||
for stack_event in sublist | ||
if ( | ||
stack_event.get("ClientRequestToken") | ||
and stack_event["ClientRequestToken"] == client_request_token | ||
and stack_event["ResourceStatus"] | ||
in [ | ||
"CREATE_FAILED", | ||
"DELETE_FAILED", | ||
"UPDATE_FAILED", | ||
"UPDATE_ROLLBACK_FAILED", | ||
"UPDATE_ROLLBACK_COMPLETE", | ||
"ROLLBACK_FAILED", | ||
"ROLLBACK_COMPLETE", | ||
] | ||
) | ||
] | ||
|
||
super().__init__( | ||
msg="Cloudformation failed to update the stack\n\n" | ||
+ "\n".join(stack_events) | ||
+ "\n" | ||
) |
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
104 changes: 104 additions & 0 deletions
104
hamlet/backend/contract/tasks/aws_cfn_create_change_set/__init__.py
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,104 @@ | ||
import datetime | ||
from typing import Optional | ||
|
||
import boto3 | ||
import botocore | ||
|
||
|
||
def run( | ||
TemplateS3Uri=None, | ||
TemplateBody=None, | ||
StackName=None, | ||
ChangeSetName=None, | ||
Parameters=None, | ||
Capabilities: Optional[str] = None, | ||
Region: Optional[str] = None, | ||
AWSAccessKeyId: Optional[str] = None, | ||
AWSSecretAccessKey: Optional[str] = None, | ||
AWSSessionToken: Optional[str] = None, | ||
env={}, | ||
): | ||
""" | ||
Create a CloudFormation ChangeSet | ||
""" | ||
|
||
session = boto3.Session( | ||
aws_access_key_id=AWSAccessKeyId, | ||
aws_secret_access_key=AWSSecretAccessKey, | ||
aws_session_token=AWSSessionToken, | ||
region_name=Region, | ||
) | ||
|
||
cfn = session.client("cloudformation") | ||
|
||
client_token = str(int(datetime.datetime.now().timestamp())) | ||
|
||
existing_stacks = [ | ||
stack | ||
for sublist in [ | ||
x["StackSummaries"] for x in cfn.get_paginator("list_stacks").paginate() | ||
] | ||
for stack in sublist | ||
if stack["StackName"] == StackName | ||
] | ||
|
||
for stack in [ | ||
stack for stack in existing_stacks if stack["StackStatus"] == "CREATE_FAIlED" | ||
]: | ||
cfn.delete_stack(StackName=stack["StackName"]) | ||
cfn.get_waiter("stack_delete_complete").wait(StackName=stack["StackName"]) | ||
|
||
change_set_params = { | ||
"StackName": StackName, | ||
"ChangeSetName": ChangeSetName, | ||
"ChangeSetType": "CREATE", | ||
"ClientToken": client_token, | ||
} | ||
|
||
if TemplateS3Uri: | ||
change_set_params["TemplateURL"] = TemplateS3Uri | ||
elif TemplateBody: | ||
change_set_params["TemplateBody"] = TemplateBody | ||
|
||
if ( | ||
len( | ||
[ | ||
stack | ||
for stack in existing_stacks | ||
if stack["StackStatus"] not in ["DELETE_COMPLETE", "CREATE_FAILED"] | ||
] | ||
) | ||
> 0 | ||
): | ||
change_set_params["ChangeSetType"] = "UPDATE" | ||
|
||
if Parameters: | ||
change_set_params["Parameters"] = [ | ||
{"ParameterKey": k, "ParameterValue": v} for k, v in Parameters.items() | ||
] | ||
|
||
if Capabilities: | ||
change_set_params["Capabilities"] = Capabilities.split(",") | ||
|
||
cfn.create_change_set(**change_set_params) | ||
changes_required = True | ||
|
||
try: | ||
cfn.get_waiter("change_set_create_complete").wait( | ||
ChangeSetName=ChangeSetName, | ||
StackName=StackName, | ||
) | ||
except botocore.exceptions.WaiterError as error: | ||
change_set_state = cfn.describe_change_set( | ||
ChangeSetName=ChangeSetName, StackName=StackName | ||
) | ||
if ( | ||
change_set_state["Status"] == "FAILED" | ||
and change_set_state["StatusReason"] | ||
== "The submitted information didn't contain changes. Submit different information to create a change set." | ||
): | ||
changes_required = False | ||
else: | ||
raise error | ||
|
||
return {"Properties": {"changes_required": str(changes_required)}} |
79 changes: 0 additions & 79 deletions
79
hamlet/backend/contract/tasks/aws_cfn_create_changeset/__init__.py
This file was deleted.
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
Oops, something went wrong.