def test_transform_method_must_inject_plugins_when_creating_resources( self, prepare_plugins_mock, sam_plugins_class_mock, resource_from_dict_mock): manifest = { "Resources": { "MyTable": { "Type": "AWS::Serverless::SimpleTable", "Properties": {} } } } sam_plugins_object_mock = Mock() sam_plugins_class_mock.return_value = sam_plugins_object_mock prepare_plugins_mock.return_value = sam_plugins_object_mock resource_from_dict_mock.return_value = SamSimpleTable("MyFunction") initial_plugins = [1, 2, 3] sam_parser = Parser() translator = Translator({}, sam_parser, plugins=initial_plugins) translator.translate(manifest, {}) resource_from_dict_mock.assert_called_with( "MyTable", manifest["Resources"]["MyTable"], sam_plugins=sam_plugins_object_mock) prepare_plugins_mock.assert_called_once_with(initial_plugins, { "AWS::Region": "ap-southeast-1", "AWS::Partition": "aws" })
def test_throws_when_resource_not_found(self): template = {"foo": "bar"} with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def test_transform_method_must_inject_plugins_when_creating_resources(self, prepare_plugins_mock, sam_plugins_class_mock, resource_from_dict_mock): manifest = { 'Resources': { 'MyTable': { 'Type': 'AWS::Serverless::SimpleTable', 'Properties': { } } } } sam_plugins_object_mock = Mock() sam_plugins_class_mock.return_value = sam_plugins_object_mock prepare_plugins_mock.return_value = sam_plugins_object_mock resource_from_dict_mock.return_value = SamSimpleTable("MyFunction") initial_plugins = [1,2,3] sam_parser = Parser() translator = Translator({}, sam_parser, plugins=initial_plugins) translator.translate(manifest, {}) resource_from_dict_mock.assert_called_with("MyTable", manifest["Resources"]["MyTable"], sam_plugins=sam_plugins_object_mock) prepare_plugins_mock.assert_called_once_with(initial_plugins, {"AWS::Region": "ap-southeast-1"})
def test_throws_when_resource_is_not_dict(self): template = {"Resources": [1, 2, 3]} with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def is_valid(self): """ Runs the SAM Translator to determine if the template provided is valid. This is similar to running a ChangeSet in CloudFormation for a SAM Template Raises ------- InvalidSamDocumentException If the template is not valid, an InvalidSamDocumentException is raised """ managed_policy_map = self.managed_policy_loader.load() sam_translator = Translator(managed_policy_map=managed_policy_map, sam_parser=self.sam_parser, plugins=[]) self._replace_local_codeuri() try: sam_translator.translate(sam_template=self.sam_template, parameter_values={}) except InvalidDocumentException as e: raise InvalidSamDocumentException( reduce(lambda message, error: message + ' ' + error.message, e.causes, e.message))
def test_throws_when_resources_not_all_dicts(self): template = {"Resources": {"notadict": None, "MyResource": {}}} with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def test_throws_when_resource_not_found(self): template = { "foo": "bar" } with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def test_throws_when_resource_is_not_dict(self): template = { "Resources": [1,2,3] } with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def test_throws_when_resources_not_all_dicts(self): template = { "Resources": { "notadict": None, "MyResource": {} } } with self.assertRaises(InvalidDocumentException): sam_parser = Parser() translator = Translator({}, sam_parser) translator.translate(template, {})
def is_valid(self): """ Runs the SAM Translator to determine if the template provided is valid. This is similar to running a ChangeSet in CloudFormation for a SAM Template Raises ------- InvalidSamDocumentException If the template is not valid, an InvalidSamDocumentException is raised """ managed_policy_map = self.managed_policy_loader.load() sam_translator = Translator( managed_policy_map=managed_policy_map, sam_parser=self.sam_parser, plugins=[], boto_session=self.boto3_session, ) self._replace_local_codeuri() try: template = sam_translator.translate(sam_template=self.sam_template, parameter_values={}) LOG.debug("Translated template is:\n%s", yaml_dump(template)) except InvalidDocumentException as e: raise InvalidSamDocumentException( functools.reduce(lambda message, error: message + " " + str(error), e.causes, str(e)) ) from e
def transform_template(self): """ Transform the Template using the Serverless Application Model. """ matches = [] try: # Output the SAM Translator version in debug mode LOGGER.debug('SAM Translator: %s', samtranslator.__version__) sam_translator = Translator( managed_policy_map=self._managed_policy_map, sam_parser=self._sam_parser) self._replace_local_codeuri() # Tell SAM to use the region we're linting in, this has to be controlled using the default AWS mechanisms, see also: # https://github.com/awslabs/serverless-application-model/blob/master/samtranslator/translator/arn_generator.py os.environ['AWS_DEFAULT_REGION'] = self._region # In the Paser class, within the SAM Translator, they log a warning for when the template # does not match the schema. The logger they use is the root logger instead of one scoped to # their module. Currently this does not cause templates to fail, so we will suppress this # by patching the logging.warning method that is used in that class. class WarningSuppressLogger(object): """ Patch the Logger in SAM """ def __init__(self, obj_to_patch): self.obj_to_patch = obj_to_patch def __enter__(self): self.obj_to_patch.warning = self.warning def __exit__(self, exc_type, exc_val, exc_tb): self.obj_to_patch.warning = self.obj_to_patch.warning def warning(self, message): """ Ignore warnings from SAM """ with WarningSuppressLogger(parser.logging): self._template = cfnlint.helpers.convert_dict( sam_translator.translate(sam_template=self._template, parameter_values={})) except InvalidDocumentException as e: for cause in e.causes: matches.append( cfnlint.Match(1, 1, 1, 1, self._filename, cfnlint.TransformError(), cause.message)) except Exception as e: # pylint: disable=W0703 LOGGER.debug('Error transforming template: %s', str(e)) LOGGER.debug('Stack trace: %s', e, exc_info=True) message = 'Error transforming template: {0}' matches.append( cfnlint.Match(1, 1, 1, 1, self._filename, cfnlint.TransformError(), message.format(str(e)))) return matches
def is_valid(self): """ Runs the SAM Translator to determine if the template provided is valid. This is similar to running a ChangeSet in CloudFormation for a SAM Template Raises ------- InvalidSamDocumentException If the template is not valid, an InvalidSamDocumentException is raised """ managed_policy_map = self.managed_policy_loader.load() sam_translator = Translator(managed_policy_map=managed_policy_map, sam_parser=self.sam_parser, plugins=[]) self._replace_local_codeuri() # In the Paser class, within the SAM Translator, they log a warning for when the template # does not match the schema. The logger they use is the root logger instead of one scoped to # their module. Currently this does not cause templates to fail, so we will suppress this # by patching the logging.warning method that is used in that class. class WarningSuppressLogger(object): def __init__(self, obj_to_patch): self.obj_to_patch = obj_to_patch def __enter__(self): self.obj_to_patch.warning = self.warning def __exit__(self, exc_type, exc_val, exc_tb): self.obj_to_patch.warning = self.obj_to_patch.warning def warning(self, message): pass try: with WarningSuppressLogger(parser.logging): sam_translator.translate(sam_template=self.sam_template, parameter_values={}) except InvalidDocumentException as e: raise InvalidSamDocumentException( functools.reduce( lambda message, error: message + ' ' + str(error), e.causes, str(e)))
def transform_template(self): """ Transform the Template using the Serverless Application Model. """ matches = [] try: sam_translator = Translator( managed_policy_map=self._managed_policy_map, sam_parser=self._sam_parser) self._replace_local_codeuri() # In the Paser class, within the SAM Translator, they log a warning for when the template # does not match the schema. The logger they use is the root logger instead of one scoped to # their module. Currently this does not cause templates to fail, so we will suppress this # by patching the logging.warning method that is used in that class. class WarningSuppressLogger(object): """ Patch the Logger in SAM """ def __init__(self, obj_to_patch): self.obj_to_patch = obj_to_patch def __enter__(self): self.obj_to_patch.warning = self.warning def __exit__(self, exc_type, exc_val, exc_tb): self.obj_to_patch.warning = self.obj_to_patch.warning def warning(self, message): """ Ignore warnings from SAM """ pass with WarningSuppressLogger(parser.logging): sam_translator.translate(sam_template=self._template, parameter_values={}) except InvalidDocumentException as e: for cause in e.causes: matches.append( cfnlint.Match(1, 1, 1, 1, self._filename, cfnlint.TransformError(), cause.message)) return matches
def transform(input_fragment, parameter_values, managed_policy_loader): """Translates the SAM manifest provided in the and returns the translation to CloudFormation. :param dict input_fragment: the SAM template to transform :param dict parameter_values: Parameter values provided by the user :returns: the transformed CloudFormation template :rtype: dict """ sam_parser = Parser() translator = Translator(managed_policy_loader.load(), sam_parser) return translator.translate(input_fragment, parameter_values=parameter_values)
def __translate(self, parameter_values): """ This method is unused and a Work In Progress """ template_copy = self.template sam_parser = Parser() sam_translator = Translator(managed_policy_map=self.__managed_policy_map(), sam_parser=sam_parser, # Default plugins are already initialized within the Translator plugins=self.extra_plugins) return sam_translator.translate(sam_template=template_copy, parameter_values=parameter_values)
def transform_template(self): """ Transform the Template using the Serverless Application Model. """ matches = [] try: # Output the SAM Translator version in debug mode LOGGER.info('SAM Translator: %s', samtranslator.__version__) sam_translator = Translator( managed_policy_map=self._managed_policy_map, sam_parser=self._sam_parser) self._replace_local_codeuri() # Tell SAM to use the region we're linting in, this has to be # controlled using the default AWS mechanisms, see also: # https://github.com/awslabs/serverless-application-model/blob/master/samtranslator/translator/arn_generator.py LOGGER.info('Setting AWS_DEFAULT_REGION to %s', self._region) os.environ['AWS_DEFAULT_REGION'] = self._region self._template = convert_dict( sam_translator.translate(sam_template=self._template, parameter_values=self._parameters)) LOGGER.info('Transformed template: \n%s', format_json_string(self._template)) except InvalidDocumentException as e: message = 'Error transforming template: {0}' for cause in e.causes: matches.append(Match( 1, 1, 1, 1, self._filename, TransformError(), message.format(cause.message))) except Exception as e: # pylint: disable=W0703 LOGGER.debug('Error transforming template: %s', str(e)) LOGGER.debug('Stack trace: %s', e, exc_info=True) message = 'Error transforming template: {0}' matches.append(Match( 1, 1, 1, 1, self._filename, TransformError(), message.format(str(e)))) return matches
def is_valid(self): """ Runs the SAM Translator to determine if the template provided is valid. This is similar to running a ChangeSet in CloudFormation for a SAM Template Raises ------- InvalidSamDocumentException If the template is not valid, an InvalidSamDocumentException is raised """ managed_policy_map = self.managed_policy_loader.load() sam_translator = Translator(managed_policy_map=managed_policy_map, sam_parser=self.sam_parser, plugins=[]) self._replace_local_codeuri() # In the Paser class, within the SAM Translator, they log a warning for when the template # does not match the schema. The logger they use is the root logger instead of one scoped to # their module. Currently this does not cause templates to fail, so we will suppress this # by patching the logging.warning method that is used in that class. class WarningSuppressLogger(object): def __init__(self, obj_to_patch): self.obj_to_patch = obj_to_patch def __enter__(self): self.obj_to_patch.warning = self.warning def __exit__(self, exc_type, exc_val, exc_tb): self.obj_to_patch.warning = self.obj_to_patch.warning def warning(self, message): pass try: with WarningSuppressLogger(parser.logging): template = sam_translator.translate(sam_template=self.sam_template, parameter_values={}) LOG.debug("Translated template is:\n%s", yaml_dump(template)) except InvalidDocumentException as e: raise InvalidSamDocumentException( functools.reduce(lambda message, error: message + ' ' + str(error), e.causes, str(e)))