16
16
DynamoDBConfigType ,
17
17
GraphQLApi ,
18
18
GraphQLSchema ,
19
+ LogConfigType ,
19
20
)
20
21
from samtranslator .internal .types import GetManagedPolicyMap
21
22
from samtranslator .intrinsics .resolver import IntrinsicsResolver
@@ -2136,6 +2137,7 @@ class SamGraphQLApi(SamResourceMacro):
2136
2137
"Auth" : Property (True , IS_DICT ),
2137
2138
"SchemaInline" : Property (False , IS_STR ),
2138
2139
"SchemaUri" : Property (False , IS_STR ),
2140
+ "Logging" : Property (False , one_of (IS_DICT , is_type (bool ))),
2139
2141
}
2140
2142
2141
2143
Auth : Dict [str , Any ]
@@ -2144,16 +2146,21 @@ class SamGraphQLApi(SamResourceMacro):
2144
2146
Name : Optional [str ]
2145
2147
SchemaInline : Optional [str ]
2146
2148
SchemaUri : Optional [str ]
2149
+ Logging : Optional [Union [Dict [str , Any ], bool ]]
2147
2150
2148
2151
@cw_timer
2149
2152
def to_cloudformation (self , ** kwargs : Any ) -> List [Resource ]:
2150
- appsync_api = self ._construct_appsync_api ()
2153
+ appsync_api , cloudwatch_role = self ._construct_appsync_api_resources ()
2151
2154
appsync_schema = self ._construct_appsync_schema (appsync_api .get_runtime_attr ("api_id" ))
2155
+
2152
2156
resources : List [Resource ] = [appsync_api , appsync_schema ]
2153
2157
2158
+ if cloudwatch_role :
2159
+ resources .append (cloudwatch_role )
2160
+
2154
2161
return resources
2155
2162
2156
- def _construct_appsync_api (self ) -> GraphQLApi :
2163
+ def _construct_appsync_api_resources (self ) -> Tuple [ GraphQLApi , Optional [ IAMRole ]] :
2157
2164
api = GraphQLApi (logical_id = self .logical_id , depends_on = self .depends_on , attributes = self .resource_attributes )
2158
2165
2159
2166
api .AuthenticationType = sam_expect (self .Auth .get ("Type" ), self .logical_id , "Auth.Type" ).to_be_a_string ()
@@ -2163,7 +2170,63 @@ def _construct_appsync_api(self) -> GraphQLApi:
2163
2170
if self .Tags :
2164
2171
api .Tags = get_tag_list (self .Tags )
2165
2172
2166
- return api
2173
+ # Logging has 3 possible types: dict, bool, and None.
2174
+ # GraphQLApi will not include logging if and only if the user explicity sets Logging as false boolean.
2175
+ # It will for every other value (including true boolean which is essentially same as None).
2176
+ if isinstance (self .Logging , bool ) and self .Logging is False :
2177
+ return api , None
2178
+
2179
+ api .LogConfig , cloudwatch_role = self ._parse_logging_properties ()
2180
+
2181
+ return api , cloudwatch_role
2182
+
2183
+ def _create_logging_default (self ) -> Tuple [LogConfigType , IAMRole ]:
2184
+ """
2185
+ Create a default logging configuration.
2186
+
2187
+ This function is used when "Logging" property is a False boolean or NoneType.
2188
+ """
2189
+ log_config : LogConfigType = {}
2190
+ log_config ["FieldLogLevel" ] = "ALL"
2191
+ cloudwatch_role = self ._construct_cloudwatch_role ()
2192
+ log_config ["CloudWatchLogsRoleArn" ] = cloudwatch_role .get_runtime_attr ("arn" )
2193
+
2194
+ return log_config , cloudwatch_role
2195
+
2196
+ def _parse_logging_properties (self ) -> Tuple [LogConfigType , Optional [IAMRole ]]:
2197
+ """Parse logging properties from SAM template, and use defaults if required keys dont exist."""
2198
+ if not isinstance (self .Logging , dict ):
2199
+ return self ._create_logging_default ()
2200
+
2201
+ log_config : LogConfigType = {}
2202
+
2203
+ if "ExcludeVerboseContent" in self .Logging :
2204
+ log_config ["ExcludeVerboseContent" ] = self .Logging ["ExcludeVerboseContent" ]
2205
+
2206
+ log_config ["FieldLogLevel" ] = self .Logging .get ("FieldLogLevel" , "ALL" )
2207
+ log_config ["CloudWatchLogsRoleArn" ] = self .Logging .get ("CloudWatchLogsRoleArn" , None )
2208
+
2209
+ if log_config ["CloudWatchLogsRoleArn" ]:
2210
+ return log_config , None
2211
+
2212
+ cloudwatch_role = self ._construct_cloudwatch_role ()
2213
+ log_config ["CloudWatchLogsRoleArn" ] = cloudwatch_role .get_runtime_attr ("arn" )
2214
+
2215
+ return log_config , cloudwatch_role
2216
+
2217
+ def _construct_cloudwatch_role (self ) -> IAMRole :
2218
+ role = IAMRole (
2219
+ logical_id = f"{ self .logical_id } CloudWatchRole" ,
2220
+ depends_on = self .depends_on ,
2221
+ attributes = self .resource_attributes ,
2222
+ )
2223
+ role .AssumeRolePolicyDocument = IAMRolePolicies .construct_assume_role_policy_for_service_principal (
2224
+ "appsync.amazonaws.com"
2225
+ )
2226
+ role .ManagedPolicyArns = [
2227
+ {"Fn::Sub" : "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" }
2228
+ ]
2229
+ return role
2167
2230
2168
2231
def _construct_appsync_schema (self , api_id : Intrinsicable [str ]) -> GraphQLSchema :
2169
2232
schema = GraphQLSchema (
0 commit comments