def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has passed the validation and is guaranteed to contain a non-empty "Resources" section.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """
        template = SamTemplate(template_dict)

        for api_type in [
                SamResourceType.Api.value, SamResourceType.HttpApi.value
        ]:
            for logicalId, api in template.iterate({api_type}):
                if api.properties.get("DefinitionBody") or api.properties.get(
                        "DefinitionUri"):
                    continue

                if api_type is SamResourceType.HttpApi.value:
                    # If "Properties" is not set in the template, set them here
                    if not api.properties:
                        template.set(logicalId, api)
                    api.properties[
                        "DefinitionBody"] = OpenApiEditor.gen_skeleton()

                if api_type is SamResourceType.Api.value:
                    api.properties[
                        "DefinitionBody"] = SwaggerEditor.gen_skeleton()

                api.properties["__MANAGE_SWAGGER"] = True
    def _validate(self, sam_template, parameter_values):
        """ Validates the template and parameter values and raises exceptions if there's an issue

        :param dict sam_template: SAM template
        :param dict parameter_values: Dictionary of parameter values provided by the user
        """
        if parameter_values is None:
            raise ValueError("`parameter_values` argument is required")

        if ("Resources" not in sam_template or not isinstance(sam_template["Resources"], dict) or not
                sam_template["Resources"]):
            raise InvalidDocumentException(
                [InvalidTemplateException("'Resources' section is required")])

        if (not all(isinstance(sam_resource, dict) for sam_resource in sam_template["Resources"].values())):
            raise InvalidDocumentException(
                [InvalidTemplateException(
                    "All 'Resources' must be Objects. If you're using YAML, this may be an "
                    "indentation issue."
                )])

        sam_template_instance = SamTemplate(sam_template)

        for resource_logical_id, sam_resource in sam_template_instance.iterate():
            # NOTE: Properties isn't required for SimpleTable, so we can't check
            # `not isinstance(sam_resources.get("Properties"), dict)` as this would be a breaking change.
            # sam_resource.properties defaults to {} in SamTemplate init
            if (not isinstance(sam_resource.properties, dict)):
                raise InvalidDocumentException(
                    [InvalidResourceException(resource_logical_id,
                                              "All 'Resources' must be Objects and have a 'Properties' Object. If "
                                              "you're using YAML, this may be an indentation issue."
                                              )])

        SamTemplateValidator.validate(sam_template)
Beispiel #3
0
    def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has passed the validation and is guaranteed to contain a non-empty "Resources" section.

        This plugin needs to run as soon as possible to allow some time for templates to become available.
        This verifies that the user has access to all specified applications.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """
        template = SamTemplate(template_dict)

        service_call = None
        if self._validate_only:
            service_call = self._handle_get_application_request
        else:
            service_call = self._handle_create_cfn_template_request
        for logical_id, app in template.iterate(SamResourceType.Application.value):
            if not self._can_process_application(app):
                # Handle these cases in the on_before_transform_resource event
                continue

            app_id = app.properties[self.LOCATION_KEY].get(self.APPLICATION_ID_KEY)
            semver = app.properties[self.LOCATION_KEY].get(self.SEMANTIC_VERSION_KEY)
            key = (app_id, semver)
            if key not in self._applications:
                try:
                    service_call(app_id, semver, key, logical_id)
                except InvalidResourceException as e:
                    # Catch all InvalidResourceExceptions, raise those in the before_resource_transform target.
                    self._applications[key] = e
    def on_before_transform_template(self, template_dict):
        """
        Hook method that runs before a template gets transformed. In this method, we parse and process Globals section
        from the template (if present).

        :param dict template_dict: SAM template as a dictionary
        """

        try:
            global_section = Globals(template_dict)
        except InvalidGlobalsSectionException as ex:
            raise InvalidDocumentException([ex])

        # For each resource in template, try and merge with Globals if necessary
        template = SamTemplate(template_dict)
        for logicalId, resource in template.iterate():
            resource.properties = global_section.merge(resource.type,
                                                       resource.properties)
            template.set(logicalId, resource)

        # Remove the Globals section from template if necessary
        Globals.del_section(template_dict)

        # If there was a global openApiVersion flag, check and convert swagger
        # to the right version
        Globals.fix_openapi_definitions(template_dict)
    def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has passed the validation and is guaranteed to contain a non-empty "Resources" section.

        This plugin needs to run as soon as possible to allow some time for templates to become available.
        This verifies that the user has access to all specified applications.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """
        template = SamTemplate(template_dict)
        intrinsic_resolvers = self._get_intrinsic_resolvers(
            template_dict.get("Mappings", {}))

        service_call = None
        if self._validate_only:
            service_call = self._handle_get_application_request
        else:
            service_call = self._handle_create_cfn_template_request
        for logical_id, app in template.iterate(
            {SamResourceType.Application.value}):
            if not self._can_process_application(app):
                # Handle these cases in the on_before_transform_resource event
                continue

            app_id = self._replace_value(app.properties[self.LOCATION_KEY],
                                         self.APPLICATION_ID_KEY,
                                         intrinsic_resolvers)

            semver = self._replace_value(app.properties[self.LOCATION_KEY],
                                         self.SEMANTIC_VERSION_KEY,
                                         intrinsic_resolvers)

            if isinstance(app_id, dict) or isinstance(semver, dict):
                key = (json.dumps(app_id), json.dumps(semver))
                self._applications[key] = False
                continue

            key = (app_id, semver)

            if key not in self._applications:
                try:
                    if not RegionConfiguration.is_sar_supported():
                        raise InvalidResourceException(
                            logical_id,
                            "Serverless Application Repository is not available in this region."
                        )
                    # Lazy initialization of the client- create it when it is needed
                    if not self._sar_client:
                        self._sar_client = boto3.client("serverlessrepo")
                    service_call(app_id, semver, key, logical_id)
                except InvalidResourceException as e:
                    # Catch all InvalidResourceExceptions, raise those in the before_resource_transform target.
                    self._applications[key] = e
    def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has passed the validation and is guaranteed to contain a non-empty "Resources" section.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """
        template = SamTemplate(template_dict)

        for logicalId, api in template.iterate(SamResourceType.Api.value):
            if api.properties.get('DefinitionBody') or api.properties.get('DefinitionUri'):
                continue

            api.properties['DefinitionBody'] = SwaggerEditor.gen_skeleton()
            api.properties['__MANAGE_SWAGGER'] = True
Beispiel #7
0
    def _validate(self, sam_template, parameter_values):
        """ Validates the template and parameter values and raises exceptions if there's an issue

        :param dict sam_template: SAM template
        :param dict parameter_values: Dictionary of parameter values provided by the user
        """
        if parameter_values is None:
            raise ValueError("`parameter_values` argument is required")

        if (
            "Resources" not in sam_template
            or not isinstance(sam_template["Resources"], dict)
            or not sam_template["Resources"]
        ):
            raise InvalidDocumentException([InvalidTemplateException("'Resources' section is required")])

        if not all(isinstance(sam_resource, dict) for sam_resource in sam_template["Resources"].values()):
            raise InvalidDocumentException(
                [
                    InvalidTemplateException(
                        "All 'Resources' must be Objects. If you're using YAML, this may be an " "indentation issue."
                    )
                ]
            )

        sam_template_instance = SamTemplate(sam_template)

        for resource_logical_id, sam_resource in sam_template_instance.iterate():
            # NOTE: Properties isn't required for SimpleTable, so we can't check
            # `not isinstance(sam_resources.get("Properties"), dict)` as this would be a breaking change.
            # sam_resource.properties defaults to {} in SamTemplate init
            if not isinstance(sam_resource.properties, dict):
                raise InvalidDocumentException(
                    [
                        InvalidResourceException(
                            resource_logical_id,
                            "All 'Resources' must be Objects and have a 'Properties' Object. If "
                            "you're using YAML, this may be an indentation issue.",
                        )
                    ]
                )

        SamTemplateValidator.validate(sam_template)
    def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has pass the validation and is guaranteed to contain a non-empty "Resources" section.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """

        template = SamTemplate(template_dict)

        # Temporarily add Serverless::Api resource corresponding to Implicit API to the template.
        # This will allow the processing code to work the same way for both Implicit & Explicit APIs
        # If there are no implicit APIs, we will remove from the template later.

        # If the customer has explicitly defined a resource with the id of "ServerlessRestApi",
        # capture it.  If the template ends up not defining any implicit api's, instead of just
        # removing the "ServerlessRestApi" resource, we just restore what the author defined.
        self.existing_implicit_api_resource = copy.deepcopy(template.get(self.implicit_api_logical_id))

        template.set(self.implicit_api_logical_id, ImplicitApiResource().to_dict())

        errors = []
        for logicalId, function in template.iterate(SamResourceType.Function.value):

            api_events = self._get_api_events(function)
            condition = function.condition
            if len(api_events) == 0:
                continue

            try:
                self._process_api_events(function, api_events, template, condition)

            except InvalidEventException as ex:
                errors.append(InvalidResourceException(logicalId, ex.message))

        self._maybe_add_condition_to_implicit_api(template_dict)
        self._maybe_add_conditions_to_implicit_api_paths(template)
        self._maybe_remove_implicit_api(template)

        if len(errors) > 0:
            raise InvalidDocumentException(errors)
    def on_before_transform_template(self, template_dict):
        """
        Hook method that runs before a template gets transformed. In this method, we parse and process Globals section
        from the template (if present).

        :param dict template_dict: SAM template as a dictionary
        """

        try:
            global_section = Globals(template_dict)
        except InvalidGlobalsSectionException as ex:
            raise InvalidDocumentException([ex])

        # For each resource in template, try and merge with Globals if necessary
        template = SamTemplate(template_dict)
        for logicalId, resource in template.iterate():
            resource.properties = global_section.merge(resource.type, resource.properties)
            template.set(logicalId, resource)

        # Remove the Globals section from template if necessary
        Globals.del_section(template_dict)
Beispiel #10
0
    def on_before_transform_template(self, template_dict):
        """
        Hook method that gets called before the SAM template is processed.
        The template has pass the validation and is guaranteed to contain a non-empty "Resources" section.

        :param dict template_dict: Dictionary of the SAM template
        :return: Nothing
        """

        template = SamTemplate(template_dict)

        # Temporarily add Serverless::Api resource corresponding to Implicit API to the template.
        # This will allow the processing code to work the same way for both Implicit & Explicit APIs
        # If there are no implicit APIs, we will remove from the template later.

        # If the customer has explicitly defined a resource with the id of "ServerlessRestApi",
        # capture it.  If the template ends up not defining any implicit api's, instead of just
        # removing the "ServerlessRestApi" resource, we just restore what the author defined.
        self.existing_implicit_api_resource = copy.deepcopy(
            template.get(self.implicit_api_logical_id))

        template.set(self.implicit_api_logical_id,
                     self._generate_implicit_api_resource())

        errors = []
        for logicalId, resource in template.iterate({
                SamResourceType.Function.value,
                SamResourceType.StateMachine.value
        }):

            api_events = self._get_api_events(resource)
            condition = resource.condition
            deletion_policy = resource.deletion_policy
            update_replace_policy = resource.update_replace_policy
            if len(api_events) == 0:
                continue

            try:
                self._process_api_events(resource, api_events, template,
                                         condition, deletion_policy,
                                         update_replace_policy)

            except InvalidEventException as ex:
                errors.append(InvalidResourceException(logicalId, ex.message))

        self._maybe_add_condition_to_implicit_api(template_dict)
        self._maybe_add_deletion_policy_to_implicit_api(template_dict)
        self._maybe_add_update_replace_policy_to_implicit_api(template_dict)
        self._maybe_add_conditions_to_implicit_api_paths(template)
        self._maybe_remove_implicit_api(template)

        if len(errors) > 0:
            raise InvalidDocumentException(errors)