1from enum import Enum
2from samtranslator.model.exceptions import InvalidDocumentException, InvalidTemplateException
3from samtranslator.model.types import is_str
4
5
6class SamResource(object):
7    """
8    Class representing a SAM resource. It is designed to make minimal assumptions about the resource structure.
9    Any mutating methods also touch only "Properties" and "Type" attributes of the resource. This allows compatibility
10    with any CloudFormation constructs, like DependsOn, Conditions etc.
11    """
12
13    type = None
14    properties = {}
15
16    def __init__(self, resource_dict):
17        """
18        Initialize the object given the resource as a dictionary
19
20        :param dict resource_dict: Resource dictionary containing type & properties
21        """
22
23        self.resource_dict = resource_dict
24        self.type = resource_dict.get("Type")
25        self.condition = resource_dict.get("Condition", None)
26        self.deletion_policy = resource_dict.get("DeletionPolicy", None)
27        self.update_replace_policy = resource_dict.get("UpdateReplacePolicy", None)
28
29        # Properties is *not* required. Ex: SimpleTable resource has no required properties
30        self.properties = resource_dict.get("Properties", {})
31
32    def valid(self):
33        """
34        Checks if the resource data is valid
35
36        :return: True, if the resource is valid
37        """
38        # As long as the type is valid and type string.
39        # validate the condition should be string
40
41        if self.condition:
42
43            if not is_str()(self.condition, should_raise=False):
44                raise InvalidDocumentException([InvalidTemplateException("Every Condition member must be a string.")])
45
46        if self.deletion_policy:
47
48            if not is_str()(self.deletion_policy, should_raise=False):
49                raise InvalidDocumentException(
50                    [InvalidTemplateException("Every DeletionPolicy member must be a string.")]
51                )
52
53        if self.update_replace_policy:
54
55            if not is_str()(self.update_replace_policy, should_raise=False):
56                raise InvalidDocumentException(
57                    [InvalidTemplateException("Every UpdateReplacePolicy member must be a string.")]
58                )
59
60        return SamResourceType.has_value(self.type)
61
62    def to_dict(self):
63
64        if self.valid():
65            # Touch a resource dictionary ONLY if it is valid
66            # Modify only Type & Properties section to preserve CloudFormation properties like DependsOn, Conditions etc
67            self.resource_dict["Type"] = self.type
68            self.resource_dict["Properties"] = self.properties
69
70        return self.resource_dict
71
72
73class SamResourceType(Enum):
74    """
75    Enum of supported SAM types
76    """
77
78    Api = "AWS::Serverless::Api"
79    Function = "AWS::Serverless::Function"
80    SimpleTable = "AWS::Serverless::SimpleTable"
81    Application = "AWS::Serverless::Application"
82    LambdaLayerVersion = "AWS::Serverless::LayerVersion"
83    HttpApi = "AWS::Serverless::HttpApi"
84    StateMachine = "AWS::Serverless::StateMachine"
85
86    @classmethod
87    def has_value(cls, value):
88        """
89        Checks if the given value belongs to the Enum
90
91        :param string value: Value to be checked
92        :return: True, if input is in the Enum
93        """
94        return any(value == item.value for item in cls)
95