Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions samtranslator/model/api/api_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def _construct_deployment(self, rest_api):

return deployment

def _construct_stage(self, deployment, swagger):
def _construct_stage(self, deployment, swagger, redeploy_restapi_parameters):
"""Constructs and returns the ApiGateway Stage.

:param model.apigateway.ApiGatewayDeployment deployment: the Deployment for this Stage
Expand Down Expand Up @@ -245,7 +245,9 @@ def _construct_stage(self, deployment, swagger):
stage.TracingEnabled = self.tracing_enabled

if swagger is not None:
deployment.make_auto_deployable(stage, self.remove_extra_stage, swagger, self.domain)
deployment.make_auto_deployable(
stage, self.remove_extra_stage, swagger, self.domain, redeploy_restapi_parameters
)

if self.tags is not None:
stage.Tags = get_tag_list(self.tags)
Expand Down Expand Up @@ -372,7 +374,7 @@ def _construct_alias_target(self, domain):
alias_target["DNSName"] = route53.get("DistributionDomainName")
return alias_target

def to_cloudformation(self):
def to_cloudformation(self, redeploy_restapi_parameters):
"""Generates CloudFormation resources from a SAM API resource

:returns: a tuple containing the RestApi, Deployment, and Stage for an empty Api.
Expand All @@ -388,7 +390,7 @@ def to_cloudformation(self):
elif rest_api.BodyS3Location is not None:
swagger = rest_api.BodyS3Location

stage = self._construct_stage(deployment, swagger)
stage = self._construct_stage(deployment, swagger, redeploy_restapi_parameters)
permissions = self._construct_authorizer_lambda_permission()

return rest_api, deployment, stage, permissions, domain, basepath_mapping, route53
Expand Down
14 changes: 12 additions & 2 deletions samtranslator/model/apigateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@ class ApiGatewayDeployment(Resource):

runtime_attrs = {"deployment_id": lambda self: ref(self.logical_id)}

def make_auto_deployable(self, stage, openapi_version=None, swagger=None, domain=None):
def make_auto_deployable(
self, stage, openapi_version=None, swagger=None, domain=None, redeploy_restapi_parameters=None
):
"""
Sets up the resource such that it will trigger a re-deployment when Swagger changes
or the openapi version changes or a domain resource changes.

:param swagger: Dictionary containing the Swagger definition of the API
:param openapi_version: string containing value of OpenApiVersion flag in the template
:param domain: Dictionary containing the custom domain configuration for the API
:param redeploy_restapi_parameters: Dictionary containing the properties for which rest api will be redeployed
"""
if not swagger:
return
Expand All @@ -91,7 +94,14 @@ def make_auto_deployable(self, stage, openapi_version=None, swagger=None, domain
hash_input.append(str(openapi_version))
if domain:
hash_input.append(json.dumps(domain))

if redeploy_restapi_parameters:
function_names = redeploy_restapi_parameters.get("function_names")
else:
function_names = None
# The deployment logical id is <api logicalId> + "Deployment"
# The keyword "Deployment" is removed and all the function names associated with api is obtained
if function_names and function_names.get(self.logical_id[:-10], None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remind me again why self.logical_id[:-10] is needed here? Maybe add a comment about what you're trying to do?

Copy link
Author

@ShreyaGangishetty ShreyaGangishetty Dec 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I will add a comment. self.logical_id has the api_name and the word "deployment". I am removing the word "deployment" and just getting the api_name to search for corresponding string of function_name/names

hash_input.append(function_names.get(self.logical_id[:-10], ""))
data = self._X_HASH_DELIMITER.join(hash_input)
generator = logical_id_generator.LogicalIdGenerator(self.logical_id, data)
self.logical_id = generator.gen()
Expand Down
5 changes: 4 additions & 1 deletion samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ def to_cloudformation(self, **kwargs):
intrinsics_resolver = kwargs["intrinsics_resolver"]
self.BinaryMediaTypes = intrinsics_resolver.resolve_parameter_refs(self.BinaryMediaTypes)
self.Domain = intrinsics_resolver.resolve_parameter_refs(self.Domain)
redeploy_restapi_parameters = kwargs.get("redeploy_restapi_parameters")

api_generator = ApiGenerator(
self.logical_id,
Expand Down Expand Up @@ -789,7 +790,9 @@ def to_cloudformation(self, **kwargs):
domain=self.Domain,
)

rest_api, deployment, stage, permissions, domain, basepath_mapping, route53 = api_generator.to_cloudformation()
rest_api, deployment, stage, permissions, domain, basepath_mapping, route53 = api_generator.to_cloudformation(
redeploy_restapi_parameters
)

resources.extend([rest_api, deployment, stage])
resources.extend(permissions)
Expand Down
38 changes: 36 additions & 2 deletions samtranslator/translator/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,35 @@ def __init__(self, managed_policy_map, sam_parser, plugins=None):
self.plugins = plugins
self.sam_parser = sam_parser

def _get_function_names(self, resource_dict, intrinsics_resolver):
"""
:param resource_dict: AWS::Serverless::Function resource is provided as input
:param intrinsics_resolver: to resolve intrinsics for function_name
:return: a dictionary containing api_logical_id as the key and concatenated String of all function_names
associated with this api as the value
"""
if resource_dict.get("Type") and resource_dict.get("Type").strip() == "AWS::Serverless::Function":
if resource_dict.get("Properties") and resource_dict.get("Properties").get("Events"):
events = list(resource_dict.get("Properties").get("Events").values())
for item in events:
# If the function event type is `Api` then gets the function name and
# adds to the function_names dict with key as the api_name and value as the function_name
if item.get("Type") == "Api" and item.get("Properties") and item.get("Properties").get("RestApiId"):
rest_api = item.get("Properties").get("RestApiId")
if type(rest_api) == dict:
api_name = item.get("Properties").get("RestApiId").get("Ref")
else:
api_name = item.get("Properties").get("RestApiId")
if api_name:
function_name = intrinsics_resolver.resolve_parameter_refs(
resource_dict.get("Properties").get("FunctionName")
)
if function_name:
self.function_names[api_name] = self.function_names.get(api_name, "") + str(
function_name
)
return self.function_names

def translate(self, sam_template, parameter_values):
"""Loads the SAM resources from the given SAM manifest, replaces them with their corresponding
CloudFormation resources, and returns the resulting CloudFormation template.
Expand All @@ -51,6 +80,8 @@ def translate(self, sam_template, parameter_values):
:returns: a copy of the template with SAM resources replaced with the corresponding CloudFormation, which may \
be dumped into a valid CloudFormation JSON or YAML template
"""
self.function_names = dict()
self.redeploy_restapi_parameters = dict()
sam_parameter_values = SamParameterValues(parameter_values)
sam_parameter_values.add_default_parameter_values(sam_template)
sam_parameter_values.add_pseudo_parameter_values()
Expand All @@ -70,7 +101,6 @@ def translate(self, sam_template, parameter_values):
supported_resource_refs = SupportedResourceReferences()
document_errors = []
changed_logical_ids = {}

for logical_id, resource_dict in self._get_resources_to_iterate(sam_template, macro_resolver):
try:
macro = macro_resolver.resolve_resource_type(resource_dict).from_dict(
Expand All @@ -83,7 +113,11 @@ def translate(self, sam_template, parameter_values):
kwargs["mappings_resolver"] = mappings_resolver
kwargs["deployment_preference_collection"] = deployment_preference_collection
kwargs["conditions"] = template.get("Conditions")

# add the value of FunctionName property if the function is referenced with the api resource
self.redeploy_restapi_parameters["function_names"] = self._get_function_names(
resource_dict, intrinsics_resolver
)
kwargs["redeploy_restapi_parameters"] = self.redeploy_restapi_parameters
translated = macro.to_cloudformation(**kwargs)

supported_resource_refs = macro.get_resource_references(translated, supported_resource_refs)
Expand Down
2 changes: 1 addition & 1 deletion tests/translator/input/intrinsic_functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Resources:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName:
Ref: FunctionName
Fn::Sub: ${FunctionName}
CodeUri:
Bucket:
Ref: CodeBucket
Expand Down
Loading