import logging from abc import ABC from enum import Enum from typing import Optional LOG = logging.getLogger(__name__) class LifeCycleEvents(Enum): """ Enum of LifeCycleEvents """ before_transform_template = "before_transform_template" before_transform_resource = "before_transform_resource" after_transform_template = "after_transform_template" class BasePlugin(ABC): """ Base class for a NoOp plugin that implements all available hooks """ _custom_name: Optional[str] def __init__(self, name: Optional[str] = None) -> None: """ Initialize the plugin with optional given name. The optional name argument is for compatibility purpose. In SAM-T codebase all plugins use the default name (class name). :param name: Custom name of this plugin. """ self._custom_name = name @classmethod def _class_name(cls) -> str: return cls.__name__ @property def name(self) -> str: if self._custom_name: return self._custom_name return self._class_name() # Plugins can choose to skip implementing certain hook methods. In which case we will default to a # NoOp implementation def on_before_transform_resource(self, logical_id, resource_type, resource_properties): # type: ignore[no-untyped-def] # noqa: empty-method-without-abstract-decorator """ Hook method to execute on `before_transform_resource` life cycle event. Plugins are free to modify the whole template or properties of the resource. If you have a SAM resource like: { "Type": "type", Properties: {"key": "value" } } `resource_type` equals "type" `resource_properties` equals {"key": "value" } :param string logical_id: LogicalId of the resource that is being processed :param string resource_type: Type of the resource being processed :param dict resource_properties: Properties of the resource being processed. :return: Nothing :raises InvalidResourceException: If the hook decides throw this exception on validation failures """ # Plugins can choose to skip implementing certain hook methods. In which case we will default to a # NoOp implementation def on_before_transform_template(self, template_dict): # type: ignore[no-untyped-def] # noqa: empty-method-without-abstract-decorator """ Hook method to execute on "before_transform_template" life cycle event. Plugins are free to modify the whole template, inject new resources, or modify certain sections of the template. This method is called after the template passes basic structural validation. Template dictionary contains a "Resources" object is not empty. This method is free to change the contents of template dictionary. Take care to produce a valid SAM template. Any bugs produced by plugins will be opaque to customers and create cryptic, hard-to-understand error messages for customers. :param dict template: Entire SAM template as a dictionary. :return: nothing :raises InvalidDocumentException: If the hook decides that the SAM template is invalid. """ # Plugins can choose to skip implementing certain hook methods. In which case we will default to a # NoOp implementation def on_after_transform_template(self, template): # type: ignore[no-untyped-def] # noqa: empty-method-without-abstract-decorator """ Hook method to execute on "after_transform_template" life cycle event. Plugins may further modify the template. Warning: any changes made in this lifecycle action by a plugin will not be validated and may cause the template to fail deployment with hard-to-understand error messages for customers. This method is called after the template passes all other template transform actions, right before the resources are resolved to their final logical ID names. :param dict template: Entire SAM template as a dictionary. :return: nothing :raises InvalidDocumentException: If the hook decides that the SAM template is invalid. :raises InvalidResourceException: If the hook decides that a SAM resource is invalid. """