Skip to content

Commit

Permalink
Merge pull request #15 from aws-solutions/develop
Browse files Browse the repository at this point in the history
Update to version v1.4.1
  • Loading branch information
aassadza authored Dec 20, 2021
2 parents c2315ee + a9acf84 commit 843a7b4
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 100 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.1] - 2021-12-20

### Added

- Developer section in the Implementation Guide (IG) to explain how customers can integrate
their own custom blueprints with the solution.
- Configurable server-side error propagation to allow/disallow detailed error messages
in the solution's APIs responses.

### Updated

- The format of the solution's APIs responses.
- AWS Cloud Development Kit (AWS CDK) and AWS Solutions Constructs to version 1.126.0.

## [1.4.0] - 2021-09-28

### Added
Expand Down
2 changes: 1 addition & 1 deletion deployment/build-s3-dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
set -e

# Important: CDK global version number
cdk_version=1.117.0
cdk_version=1.126.0

# Check to see if the required parameters have been provided:
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
Expand Down
23 changes: 15 additions & 8 deletions source/lambdas/pipeline_orchestration/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def provision_pipeline(
# if the pipeline to provision is byom_image_builder
if pipeline_type == "byom_image_builder":
image_builder_params = get_image_builder_params(validated_event)
# format the params (the format is the same for multi-accouunt parameters)
# format the params (the format is the same for multi-account parameters)
formatted_image_builder_params = format_template_parameters(image_builder_params, "True")
# create the codepipeline
stack_response = create_codepipeline_stack(
Expand Down Expand Up @@ -140,7 +140,7 @@ def provision_pipeline(
"isBase64Encoded": False,
"body": json.dumps(
{
"message": "success: stack creation started",
"message": stack_response["message"],
"pipeline_id": stack_response["StackId"],
}
),
Expand All @@ -154,6 +154,7 @@ def update_stack(
pipeline_template_url: str,
template_parameters: List[Dict[str, str]],
client: BaseClient,
stack_id: str,
) -> Dict[str, str]:
try:
update_response = client.update_stack(
Expand All @@ -169,13 +170,14 @@ def update_stack(

logger.info(update_response)

return {"StackId": f"Pipeline {codepipeline_stack_name} is being updated."}
return {"StackId": stack_id, "message": f"Pipeline {codepipeline_stack_name} is being updated."}

except Exception as e:
logger.info(f"Error during stack update {codepipeline_stack_name}: {str(e)}")
if "No updates are to be performed" in str(e):
return {
"StackId": f"Pipeline {codepipeline_stack_name} is already provisioned. No updates are to be performed."
"StackId": stack_id,
"message": f"Pipeline {codepipeline_stack_name} is already provisioned. No updates are to be performed.",
}
else:
raise e
Expand All @@ -201,18 +203,23 @@ def create_codepipeline_stack(
)

logger.info(stack_response)
return stack_response
return {"StackId": stack_response["StackId"], "message": "success: stack creation started"}

except Exception as e:
logger.error(f"Error in create_update_cf_stackset lambda functions: {str(e)}")
logger.error(f"Error in create_codepipeline_stack: {str(e)}")
if "already exists" in str(e):
logger.info(f"AWS Codepipeline {codepipeline_stack_name} already exists. Skipping codepipeline create")
# get the stack id using stack-name
stack_id = client.describe_stacks(StackName=codepipeline_stack_name)["Stacks"][0]["StackId"]
# if the pipeline to update is BYOMPipelineImageBuilder
if codepipeline_stack_name.endswith("byompipelineimagebuilder"):
return update_stack(codepipeline_stack_name, pipeline_template_url, template_parameters, client)
return update_stack(
codepipeline_stack_name, pipeline_template_url, template_parameters, client, stack_id
)

return {
"StackId": f"Pipeline {codepipeline_stack_name} is already provisioned. Updating template parameters."
"StackId": stack_id,
"message": f"Pipeline {codepipeline_stack_name} is already provisioned. Updating template parameters.",
}
else:
raise e
Expand Down
52 changes: 31 additions & 21 deletions source/lambdas/pipeline_orchestration/shared/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,52 @@
# #####################################################################################################################
import json
import sys
import os
import traceback
from functools import wraps
import boto3
import botocore
from shared.logger import get_logger
from shared.helper import get_client

logger = get_logger(__name__)
endable_detailed_error_message = os.getenv("ALLOW_DETAILED_ERROR_MESSAGE", "Yes")


class BadRequest(Exception):
pass


def handle_exception(error_description, error_object, status_code):
# log the error
logger.error(f"{error_description}. Error: {str(error_object)}")
exc_type, exc_value, exc_tb = sys.exc_info()
logger.error(traceback.format_exception(exc_type, exc_value, exc_tb))
# update the response body
body = {"message": error_description}
if endable_detailed_error_message == "Yes":
body.update({"detailedMessage": str(error_object)})

return {
"statusCode": status_code,
"isBase64Encoded": False,
"body": json.dumps(body),
"headers": {"Content-Type": "plain/text"},
}


def api_exception_handler(f):
@wraps(f)
def wrapper(event, context):
try:
return f(event, context)
except BadRequest as e:
logger.error(f"A BadRequest exception occurred, exception message: {str(e)}")
exc_type, exc_value, exc_tb = sys.exc_info()
logger.error(traceback.format_exception(exc_type, exc_value, exc_tb))
return {
"statusCode": 400,
"isBase64Encoded": False,
"body": json.dumps({"message": str(e)}),
"headers": {"Content-Type": "plain/text"},
}
except:
exc_type, exc_value, exc_tb = sys.exc_info()
logger.error(traceback.format_exception(exc_type, exc_value, exc_tb))
return {
"statusCode": 500,
"isBase64Encoded": False,
"body": json.dumps({"message": "Internal server error. See logs for more information."}),
"headers": {"Content-Type": "plain/text"},
}

except BadRequest as bad_request_error:
return handle_exception("A BadRequest exception occurred", bad_request_error, 400)

except botocore.exceptions.ClientError as client_error:
status_code = client_error.response["ResponseMetadata"]["HTTPStatusCode"]
return handle_exception("A boto3 ClientError occurred", client_error, status_code)

except Exception as e:
return handle_exception("An Unexpected Server side exception occurred", e, 500)

return wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ def stack_name():
return "teststack-testmodel-byompipelineimagebuilder"


@pytest.fixture
def stack_id():
return "fake-stack-id"


@pytest.fixture
def expected_multi_account_params_format():
return [
Expand Down Expand Up @@ -690,5 +695,8 @@ def cf_client_params(api_byom_event, template_parameters_realtime_builtin):


@pytest.fixture
def expected_update_response(stack_name):
return {"StackId": f"Pipeline {stack_name} is already provisioned. No updates are to be performed."}
def expected_update_response(stack_name, stack_id):
return {
"StackId": stack_id,
"message": f"Pipeline {stack_name} is already provisioned. No updates are to be performed.",
}
Loading

0 comments on commit 843a7b4

Please sign in to comment.