def _construct_tag_list(self): """ Transforms the SAM defined Tags into the form CloudFormation is expecting. :returns: List of Tag Dictionaries :rtype: list """ sam_tag = {self._SAM_KEY: self._SAM_VALUE} return get_tag_list(sam_tag) + get_tag_list(self.tags)
def _construct_http_api(self): """Constructs and returns the ApiGatewayV2 HttpApi. :returns: the HttpApi to which this SAM Api corresponds :rtype: model.apigatewayv2.ApiGatewayHttpApi """ http_api = ApiGatewayV2HttpApi(self.logical_id, depends_on=self.depends_on, attributes=self.resource_attributes) if self.definition_uri and self.definition_body: raise InvalidResourceException( self.logical_id, "Specify either 'DefinitionUri' or 'DefinitionBody' property and not both" ) self._add_auth() if self.definition_uri: http_api.BodyS3Location = self._construct_body_s3_dict() elif self.definition_body: http_api.Body = self.definition_body else: raise InvalidResourceException( self.logical_id, "'DefinitionUri' or 'DefinitionBody' are required properties of an " "'AWS::Serverless::HttpApi'. Add a value for one of these properties or " "add a 'HttpApi' event to an 'AWS::Serverless::Function'", ) if self.tags is not None: http_api.Tags = get_tag_list(self.tags) return http_api
def _depend_on_lambda_permissions_using_tag(self, bucket, permission): """ Since conditional DependsOn is not supported this undocumented way of implicitely making dependency through tags is used. See https://stackoverflow.com/questions/34607476/cloudformation-apply-condition-on-dependson It is done by using Ref wrapped in a conditional Fn::If. Using Ref implies a dependency, so CloudFormation will automatically wait once it reaches that function, the same as if you were using a DependsOn. """ properties = bucket.get('Properties', None) if properties is None: properties = {} bucket['Properties'] = properties tags = properties.get('Tags', None) if tags is None: tags = [] properties['Tags'] = tags dep_tag = { 'sam:ConditionalDependsOn:' + permission.logical_id: { 'Fn::If': [ permission.resource_attributes[CONDITION], ref(permission.logical_id), 'no dependency' ] } } properties['Tags'] = tags + get_tag_list(dep_tag) return bucket
def _construct_stage(self, deployment, swagger): """Constructs and returns the ApiGateway Stage. :param model.apigateway.ApiGatewayDeployment deployment: the Deployment for this Stage :returns: the Stage to which this SAM Api corresponds :rtype: model.apigateway.ApiGatewayStage """ # If StageName is some intrinsic function, then don't prefix the Stage's logical ID # This will NOT create duplicates because we allow only ONE stage per API resource stage_name_prefix = self.stage_name if isinstance( self.stage_name, string_types) else "" stage = ApiGatewayStage( self.logical_id + stage_name_prefix + 'Stage', attributes=self.passthrough_resource_attributes) stage.RestApiId = ref(self.logical_id) stage.update_deployment_ref(deployment.logical_id) stage.StageName = self.stage_name stage.CacheClusterEnabled = self.cache_cluster_enabled stage.CacheClusterSize = self.cache_cluster_size stage.Variables = self.variables stage.MethodSettings = self.method_settings stage.AccessLogSetting = self.access_log_setting stage.CanarySetting = self.canary_setting stage.TracingEnabled = self.tracing_enabled if swagger is not None: deployment.make_auto_deployable(stage, self.remove_extra_stage, swagger) if self.tags is not None: stage.Tags = get_tag_list(self.tags) return stage
def _construct_stage(self): """Constructs and returns the ApiGatewayV2 Stage. :returns: the Stage to which this SAM Api corresponds :rtype: model.apigatewayv2.ApiGatewayV2Stage """ # If there are no special configurations, don't create a stage and use the default if not self.stage_name and not self.stage_variables and not self.access_log_settings: return # If StageName is some intrinsic function, then don't prefix the Stage's logical ID # This will NOT create duplicates because we allow only ONE stage per API resource stage_name_prefix = self.stage_name if isinstance(self.stage_name, string_types) else "" if stage_name_prefix.isalnum(): stage_logical_id = self.logical_id + stage_name_prefix + "Stage" elif stage_name_prefix == DefaultStageName: stage_logical_id = self.logical_id + "ApiGatewayDefaultStage" else: generator = logical_id_generator.LogicalIdGenerator(self.logical_id + "Stage", stage_name_prefix) stage_logical_id = generator.gen() stage = ApiGatewayV2Stage(stage_logical_id, attributes=self.passthrough_resource_attributes) stage.ApiId = ref(self.logical_id) stage.StageName = self.stage_name stage.StageVariables = self.stage_variables stage.AccessLogSettings = self.access_log_settings stage.AutoDeploy = True if self.tags is not None: stage.Tags = get_tag_list(self.tags) return stage
def _depend_on_lambda_permissions_using_tag(self, bucket, permission): """ Since conditional DependsOn is not supported this undocumented way of implicitely making dependency through tags is used. See https://stackoverflow.com/questions/34607476/cloudformation-apply-condition-on-dependson It is done by using Ref wrapped in a conditional Fn::If. Using Ref implies a dependency, so CloudFormation will automatically wait once it reaches that function, the same as if you were using a DependsOn. """ properties = bucket.get('Properties', None) if properties is None: properties = {} bucket['Properties'] = properties tags = properties.get('Tags', None) if tags is None: tags = [] properties['Tags'] = tags dep_tag = { 'sam:ConditionalDependsOn:' + permission.logical_id: { 'Fn::If': [ permission.resource_attributes[CONDITION], ref(permission.logical_id), 'no dependency' ] } } properties['Tags'] = tags + get_tag_list(dep_tag) return bucket
def _construct_tag_list(self, tags, additional_tags=None): if not bool(tags): tags = {} if additional_tags is None: additional_tags = {} for tag in self._RESERVED_TAGS: self._check_tag(tag, tags) sam_tag = {self._SAM_KEY: self._SAM_VALUE} # To maintain backwards compatibility with previous implementation, we *must* append SAM tag to the start of the # tags list. Changing this ordering will trigger a update on Lambda Function resource. Even though this # does not change the actual content of the tags, we don't want to trigger update of a resource without # customer's knowledge. return get_tag_list(sam_tag) + get_tag_list(additional_tags) + get_tag_list(tags)
def _construct_tag_list(self, tags, additional_tags=None): if not bool(tags): tags = {} if additional_tags == None: additional_tags = {} for tag in self._RESERVED_TAGS: self._check_tag(tag, tags) sam_tag = {self._SAM_KEY: self._SAM_VALUE} # To maintain backwards compatibility with previous implementation, we *must* append SAM tag to the start of the # tags list. Changing this ordering will trigger a update on Lambda Function resource. Even though this # does not change the actual content of the tags, we don't want to trigger update of a resource without # customer's knowledge. return get_tag_list(sam_tag) + get_tag_list(additional_tags) + get_tag_list(tags)
def test_get_tag_list_with_tag_dictionary(self): tag_list = get_tag_list({"AnotherKey": "This time with a value"}) expected_tag_list = [{ "Key": "AnotherKey", "Value": "This time with a value" }] self.assertEqual(tag_list, expected_tag_list)
def test_get_tag_list_returns_default_tag_list_values(self): tag_list = get_tag_list(None) expected_tag_list = [] self.assertEqual(tag_list, expected_tag_list)
def test_get_tag_list_with_tag_dictionary_with_key_only(self): tag_list = get_tag_list({"key": None}) expected_tag_list = [{"Key": "key", "Value": ""}] self.assertEqual(tag_list, expected_tag_list)
def test_get_tag_list_returns_default_tag_list_values(self): tag_list = get_tag_list(None) expected_tag_list = [] self.assertEquals(tag_list, expected_tag_list)
def test_get_tag_list_with_tag_dictionary(self): tag_list = get_tag_list({"AnotherKey": "This time with a value"}) expected_tag_list = [{"Key": "AnotherKey", "Value": "This time with a value"}] self.assertEquals(tag_list, expected_tag_list)
def test_get_tag_list_with_tag_dictionary_with_key_only(self): tag_list = get_tag_list({"key": None}) expected_tag_list = [{"Key": "key", "Value": ""}] self.assertEquals(tag_list, expected_tag_list)