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 create_match_yaml_parser_error(parser_error, filename): """Create a Match for a parser error""" lineno = parser_error.problem_mark.line + 1 colno = parser_error.problem_mark.column + 1 msg = parser_error.problem return Match( lineno, colno, lineno, colno + 1, filename, ParseError(), message=msg)
def create_match_file_error(filename, msg): """Create a Match for a parser error""" return Match(linenumber=1, columnnumber=1, linenumberend=1, columnnumberend=2, filename=filename, rule=ParseError(), message=msg)
def create_match_json_parser_error(parser_error, filename): """Create a Match for a parser error""" if sys.version_info[0] == 3: lineno = parser_error.lineno colno = parser_error.colno msg = parser_error.msg elif sys.version_info[0] == 2: lineno = 1 colno = 1 msg = parser_error.message return Match( lineno, colno, lineno, colno + 1, filename, ParseError(), message=msg)
def create_match_json_parser_error(parser_error, filename): """Create a Match for a parser error""" lineno = parser_error.lineno colno = parser_error.colno msg = parser_error.msg return Match(lineno, colno, lineno, colno + 1, filename, ParseError(), message=msg)
def decode(filename, ignore_bad_template): """ Decode filename into an object """ template = None matches = [] try: template = cfn_yaml.load(filename) except IOError as e: if e.errno == 2: LOGGER.error('Template file not found: %s', filename) matches.append( create_match_file_error( filename, 'Template file not found: %s' % filename)) elif e.errno == 21: LOGGER.error('Template references a directory, not a file: %s', filename) matches.append( create_match_file_error( filename, 'Template references a directory, not a file: %s' % filename)) elif e.errno == 13: LOGGER.error('Permission denied when accessing template file: %s', filename) matches.append( create_match_file_error( filename, 'Permission denied when accessing template file: %s' % filename)) if matches: return (None, matches) except UnicodeDecodeError as err: LOGGER.error('Cannot read file contents: %s', filename) matches.append( create_match_file_error(filename, 'Cannot read file contents: %s' % filename)) except cfn_yaml.CfnParseError as err: err.match.Filename = filename matches = [err.match] except ParserError as err: matches = [create_match_yaml_parser_error(err, filename)] except ScannerError as err: if err.problem in [ 'found character \'\\t\' that cannot start any token', 'found unknown escape character' ]: try: template = cfn_json.load(filename) except cfn_json.JSONDecodeError as json_err: json_err.match.filename = filename matches = [json_err.match] except JSONDecodeError as json_err: matches = [create_match_json_parser_error(json_err, filename)] except Exception as json_err: # pylint: disable=W0703 if ignore_bad_template: LOGGER.info('Template %s is malformed: %s', filename, err.problem) LOGGER.info('Tried to parse %s as JSON but got error: %s', filename, str(json_err)) else: LOGGER.error('Template %s is malformed: %s', filename, err.problem) LOGGER.error('Tried to parse %s as JSON but got error: %s', filename, str(json_err)) return (None, [ create_match_file_error( filename, 'Tried to parse %s as JSON but got error: %s' % (filename, str(json_err))) ]) else: matches = [create_match_yaml_parser_error(err, filename)] except YAMLError as err: matches = [create_match_file_error(filename, err)] if not isinstance(template, dict) and not matches: # Template isn't a dict which means nearly nothing will work matches = [ Match(1, 1, 1, 1, filename, ParseError(), message='Template needs to be an object.') ] return (template, matches)