Beispiel #1
0
    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
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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)
Beispiel #6
0
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)