diff --git a/integration/combination/test_graphqlapi_lambda_resolver.py b/integration/combination/test_graphqlapi_lambda_resolver.py new file mode 100644 index 000000000..0db316d28 --- /dev/null +++ b/integration/combination/test_graphqlapi_lambda_resolver.py @@ -0,0 +1,101 @@ +import json +from unittest.case import skipIf + +import requests + +from integration.config.service_names import APP_SYNC +from integration.helpers.base_test import BaseTest +from integration.helpers.resource import current_region_does_not_support + + +def execute_and_verify_appsync_query(url, api_key, query): + """ + Executes a query to an AppSync GraphQLApi. + + Also checks that the response is 200 and does not contain errors before returning. + """ + headers = { + "Content-Type": "application/json", + "x-api-key": api_key, + } + payload = {"query": query} + + response = requests.post(url, json=payload, headers=headers) + response.raise_for_status() + data = response.json() + if "errors" in data: + raise Exception(json.dumps(data["errors"])) + + return data + + +@skipIf(current_region_does_not_support([APP_SYNC]), "AppSync is not supported in this testing region") +class TestGraphQLApiPipelineResolver(BaseTest): + def test_api(self): + file_name = "combination/graphqlapi_lambda_resolver" + self.create_and_verify_stack(file_name) + + outputs = self.get_stack_outputs() + + author = "AUTHORNAME" + title = "Our first post!" + content = "This is our first post." + + query = f""" + mutation addPost {{ + addPost( + id: 100 + author: "{author}" + title: "{title}" + content: "{content}" + ) {{ + id + author + title + content + }} + }} + """ + + url = outputs["SuperCoolAPI"] + api_key = outputs["SuperCoolAPIMyApiKey"] + + response = execute_and_verify_appsync_query(url, api_key, query) + + add_post = response["data"]["addPost"] + + self.assertEqual(add_post["id"], "100") + self.assertEqual(add_post["author"], author) + self.assertEqual(add_post["title"], title) + self.assertEqual(add_post["content"], content) + + query = """ + query getPost { + getPost(id:"1") { + id + author + title + content + ups + downs + } + } + """ + + response = execute_and_verify_appsync_query(url, api_key, query) + + get_post = response["data"]["getPost"] + + # These values are hardcoded inside the Lambda function for a post with id "1". + author = "Author1" + title = "First book" + content = "Book 1 has this content" + ups = 100 + downs = 10 + + self.assertEqual(get_post["id"], "1") + self.assertEqual(get_post["author"], author) + self.assertEqual(get_post["title"], title) + self.assertEqual(get_post["content"], content) + self.assertEqual(get_post["ups"], ups) + self.assertEqual(get_post["downs"], downs) diff --git a/integration/combination/test_graphqlapi_pipeline_resolver.py b/integration/combination/test_graphqlapi_pipeline_resolver.py new file mode 100644 index 000000000..58d9fa014 --- /dev/null +++ b/integration/combination/test_graphqlapi_pipeline_resolver.py @@ -0,0 +1,101 @@ +import json +from unittest.case import skipIf + +import requests + +from integration.config.service_names import APP_SYNC +from integration.helpers.base_test import BaseTest +from integration.helpers.resource import current_region_does_not_support + + +def execute_and_verify_appsync_query(url, api_key, query): + """ + Executes a query to an AppSync GraphQLApi. + + Also checks that the response is 200 and does not contain errors before returning. + """ + headers = { + "Content-Type": "application/json", + "x-api-key": api_key, + } + payload = {"query": query} + + response = requests.post(url, json=payload, headers=headers) + response.raise_for_status() + data = response.json() + if "errors" in data: + raise Exception(json.dumps(data["errors"])) + + return data + + +@skipIf(current_region_does_not_support([APP_SYNC]), "AppSync is not supported in this testing region") +class TestGraphQLApiPipelineResolver(BaseTest): + def test_api(self): + file_name = "combination/graphqlapi_pipeline_resolver" + self.create_and_verify_stack(file_name) + + outputs = self.get_stack_outputs() + + author = "AUTHORNAME" + title = "Our first post!" + content = "This is our first post." + + query = f""" + mutation addPost {{ + addPost( + author: "{author}" + title: "{title}" + content: "{content}" + ) {{ + id + author + title + content + ups + downs + version + }} + }} + """ + + url = outputs["SuperCoolAPI"] + api_key = outputs["MyApiKey"] + + response = execute_and_verify_appsync_query(url, api_key, query) + + add_post = response["data"]["addPost"] + + self.assertEqual(add_post["author"], author) + self.assertEqual(add_post["title"], title) + self.assertEqual(add_post["content"], content) + self.assertEqual(add_post["ups"], 1) + self.assertEqual(add_post["downs"], 0) + self.assertEqual(add_post["version"], 1) + + post_id = add_post["id"] + query = f""" + query getPost {{ + getPost(id:"{post_id}") {{ + id + author + title + content + ups + downs + version + }} + }} + """ + + response = execute_and_verify_appsync_query(url, api_key, query) + + get_post = response["data"]["getPost"] + + self.assertEqual(get_post["author"], author) + self.assertEqual(get_post["title"], title) + self.assertEqual(get_post["content"], content) + self.assertEqual(get_post["ups"], 1) + self.assertEqual(get_post["downs"], 0) + self.assertEqual(get_post["version"], 1) + self.assertEqual(get_post["id"], post_id) diff --git a/integration/resources/expected/combination/graphqlapi_lambda_resolver.json b/integration/resources/expected/combination/graphqlapi_lambda_resolver.json new file mode 100644 index 000000000..09dfd3236 --- /dev/null +++ b/integration/resources/expected/combination/graphqlapi_lambda_resolver.json @@ -0,0 +1,50 @@ +[ + { + "LogicalResourceId": "MyLambdaFunction", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "LambdaFunctionRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPI", + "ResourceType": "AWS::AppSync::GraphQLApi" + }, + { + "LogicalResourceId": "SuperCoolAPISchema", + "ResourceType": "AWS::AppSync::GraphQLSchema" + }, + { + "LogicalResourceId": "SuperCoolAPICloudWatchRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPIMyApiKey", + "ResourceType": "AWS::AppSync::ApiKey" + }, + { + "LogicalResourceId": "SuperCoolAPIMyLambdaDataSourceLambdaDataSource", + "ResourceType": "AWS::AppSync::DataSource" + }, + { + "LogicalResourceId": "SuperCoolAPIMyLambdaDataSourceLambdaDataSourceRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPIMyLambdaDataSourceLambdaDataSourceToLambdaConnectorPolicy", + "ResourceType": "AWS::IAM::ManagedPolicy" + }, + { + "LogicalResourceId": "SuperCoolAPIlambdaInvoker", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIMutationaddPost", + "ResourceType": "AWS::AppSync::Resolver" + }, + { + "LogicalResourceId": "SuperCoolAPIQuerygetPost", + "ResourceType": "AWS::AppSync::Resolver" + } +] diff --git a/integration/resources/expected/combination/graphqlapi_pipeline_resolver.json b/integration/resources/expected/combination/graphqlapi_pipeline_resolver.json new file mode 100644 index 000000000..d5443de12 --- /dev/null +++ b/integration/resources/expected/combination/graphqlapi_pipeline_resolver.json @@ -0,0 +1,82 @@ +[ + { + "LogicalResourceId": "MyApiKey", + "ResourceType": "AWS::AppSync::ApiKey" + }, + { + "LogicalResourceId": "DynamoDBPostsTable", + "ResourceType": "AWS::DynamoDB::Table" + }, + { + "LogicalResourceId": "DynamoDBPostsLogTable", + "ResourceType": "AWS::DynamoDB::Table" + }, + { + "LogicalResourceId": "SuperCoolAPI", + "ResourceType": "AWS::AppSync::GraphQLApi" + }, + { + "LogicalResourceId": "SuperCoolAPISchema", + "ResourceType": "AWS::AppSync::GraphQLSchema" + }, + { + "LogicalResourceId": "SuperCoolAPICloudWatchRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsDataSourceDynamoDBDataSource", + "ResourceType": "AWS::AppSync::DataSource" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsDataSourceDynamoDBDataSourceRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsDataSourceDynamoDBDataSourceToTableConnectorPolicy", + "ResourceType": "AWS::IAM::ManagedPolicy" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsLogDataSourceDynamoDBDataSource", + "ResourceType": "AWS::AppSync::DataSource" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsLogDataSourceDynamoDBDataSourceRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "SuperCoolAPIPostsLogDataSourceDynamoDBDataSourceToTableConnectorPolicy", + "ResourceType": "AWS::IAM::ManagedPolicy" + }, + { + "LogicalResourceId": "SuperCoolAPIcreatePostItem", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIcreatePostLogItem", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIformatPostLogItem", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIformatPostItem", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIMutationaddPost", + "ResourceType": "AWS::AppSync::Resolver" + }, + { + "LogicalResourceId": "SuperCoolAPIgetPostFromTable", + "ResourceType": "AWS::AppSync::FunctionConfiguration" + }, + { + "LogicalResourceId": "SuperCoolAPIQuerygetPost", + "ResourceType": "AWS::AppSync::Resolver" + }, + { + "LogicalResourceId": "SuperCoolAPINoneDataSource", + "ResourceType": "AWS::AppSync::DataSource" + } +] diff --git a/integration/resources/templates/combination/graphqlapi_lambda_resolver.yaml b/integration/resources/templates/combination/graphqlapi_lambda_resolver.yaml new file mode 100644 index 000000000..0d31c9035 --- /dev/null +++ b/integration/resources/templates/combination/graphqlapi_lambda_resolver.yaml @@ -0,0 +1,132 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + MyLambdaFunction: + Type: AWS::Lambda::Function + Properties: + Handler: index.handler + Runtime: nodejs14.x + Role: !GetAtt LambdaFunctionRole.Arn + Code: + ZipFile: | + exports.handler = async (event) => { + console.log('Received event {}', JSON.stringify(event, 3)) + + const posts = { + 1: { id: '1', title: 'First book', author: 'Author1', content: 'Book 1 has this content', ups: '100', downs: '10', }, + } + + console.log('Got an Invoke Request.') + let result + switch (event.field) { + case 'getPost': + return posts[event.arguments.id] + case 'addPost': + // return the arguments back + return event.arguments + default: + throw new Error('Unknown field, unable to resolve ' + event.field) + } + } + + LambdaFunctionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: AppendToLogsPolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: '*' + + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: MyApi + SchemaInline: | + schema { + query: Query + mutation: Mutation + } + type Query { + getPost(id:ID!): Post + } + type Mutation { + addPost(id: ID!, author: String!, title: String, content: String): Post! + } + type Post { + id: ID! + author: String! + title: String + content: String + ups: Int + downs: Int + } + Auth: + Type: API_KEY + ApiKeys: + MyApiKey: + Description: my api key + DataSources: + Lambda: + MyLambdaDataSource: + FunctionArn: !GetAtt MyLambdaFunction.Arn + Functions: + lambdaInvoker: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + DataSource: MyLambdaDataSource + InlineCode: | + import { util } from '@aws-appsync/utils'; + + export function request(ctx) { + const {source, args} = ctx + return { + operation: 'Invoke', + payload: { field: ctx.info.fieldName, arguments: args, source }, + }; + } + + export function response(ctx) { + return ctx.result; + } + Resolvers: + Mutation: + addPost: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + Pipeline: + - lambdaInvoker + Query: + getPost: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + Pipeline: + - lambdaInvoker + +Outputs: + SuperCoolAPI: + Description: AppSync API + Value: !GetAtt SuperCoolAPI.GraphQLUrl + SuperCoolAPIMyApiKey: + Description: API Key for authentication + Value: !GetAtt SuperCoolAPIMyApiKey.ApiKey +Metadata: + SamTransformTest: true diff --git a/integration/resources/templates/combination/graphqlapi_pipeline_resolver.yaml b/integration/resources/templates/combination/graphqlapi_pipeline_resolver.yaml new file mode 100644 index 000000000..9b5653721 --- /dev/null +++ b/integration/resources/templates/combination/graphqlapi_pipeline_resolver.yaml @@ -0,0 +1,198 @@ +Transform: AWS::Serverless-2016-10-31 + +Parameters: + DDBPutItemCode: + Type: String + Default: | + import { util } from "@aws-appsync/utils"; + + export function request(ctx) { + const { key, values } = ctx.prev.result; + return { + operation: "PutItem", + key: util.dynamodb.toMapValues(key), + attributeValues: util.dynamodb.toMapValues(values), + }; + } + + export function response(ctx) { + return ctx.result; + } + +Resources: + MyApiKey: + Type: AWS::AppSync::ApiKey + Properties: + ApiId: !GetAtt SuperCoolAPI.ApiId + + DynamoDBPostsTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + ProvisionedThroughput: + ReadCapacityUnits: 5 + WriteCapacityUnits: 5 + + DynamoDBPostsLogTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + ProvisionedThroughput: + ReadCapacityUnits: 5 + WriteCapacityUnits: 5 + + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: PradsApi + SchemaInline: | + schema { + query: Query + mutation: Mutation + } + + type Query { + getPost(id: String!): Post + } + + type Mutation { + addPost( + author: String!, + title: String!, + content: String!, + ): Post! + } + + type Post { + id: String! + author: String + title: String + content: String + ups: Int! + downs: Int! + version: Int! + } + Auth: + Type: API_KEY + DataSources: + DynamoDb: + PostsDataSource: + TableName: !Ref DynamoDBPostsTable + TableArn: !GetAtt DynamoDBPostsTable.Arn + PostsLogDataSource: + TableName: !Ref DynamoDBPostsLogTable + TableArn: !GetAtt DynamoDBPostsLogTable.Arn + Functions: + createPostItem: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + DataSource: PostsDataSource + InlineCode: !Ref DDBPutItemCode + createPostLogItem: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + DataSource: PostsLogDataSource + InlineCode: !Ref DDBPutItemCode + formatPostLogItem: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + DataSource: NONE + InlineCode: | + import { util } from '@aws-appsync/utils'; + + export function request(ctx) { + const id = util.autoId(); + const author = ctx.args.author + const time = "1234567890" + return { payload: { key: {id}, values: {"author": author, "time": time} } }; + } + + export function response(ctx) { + return ctx.result; + } + formatPostItem: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + DataSource: NONE + InlineCode: | + import { util } from '@aws-appsync/utils'; + + export function request(ctx) { + const id = util.autoId(); + const { ...values } = ctx.args; + values.ups = 1; + values.downs = 0; + values.version = 1; + return { payload: { key: {id}, values: values } } + } + + export function response(ctx) { + return ctx.result; + } + getPostFromTable: + DataSource: PostsDataSource + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + InlineCode: | + import { util } from '@aws-appsync/utils'; + + export function request(ctx) { + return dynamoDBGetItemRequest({ id: ctx.args.id }); + } + + export function response(ctx) { + return ctx.result; + } + + /** + * A helper function to get a DynamoDB item + */ + function dynamoDBGetItemRequest(key) { + return { + operation: 'GetItem', + key: util.dynamodb.toMapValues(key), + }; + } + Resolvers: + Mutation: + addPost: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + Pipeline: + - formatPostLogItem + - createPostLogItem + - formatPostItem + - createPostItem + Query: + getPost: + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + Pipeline: + - getPostFromTable + +Outputs: + SuperCoolAPI: + Description: AppSync API + Value: !GetAtt SuperCoolAPI.GraphQLUrl + MyApiKey: + Description: API Key for authentication + Value: !GetAtt MyApiKey.ApiKey +Metadata: + SamTransformTest: true diff --git a/samtranslator/internal/model/__init__.py b/samtranslator/internal/model/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/samtranslator/internal/model/appsync.py b/samtranslator/internal/model/appsync.py new file mode 100644 index 000000000..253ca228b --- /dev/null +++ b/samtranslator/internal/model/appsync.py @@ -0,0 +1,278 @@ +from typing import Any, Dict, List, Optional, Union + +from typing_extensions import Required, TypedDict + +from samtranslator.model import GeneratedProperty, Resource +from samtranslator.model.intrinsics import fnGetAtt, ref +from samtranslator.utils.types import Intrinsicable + +# This JavaScript default resolver code is the template AppSync provides by default as well in the AWS Console. +# Arguments are available in every function within that resolver by accessing `ctx.args`. +APPSYNC_PIPELINE_RESOLVER_JS_CODE = """ +export function request(ctx) { + return {}; +} + +export function response(ctx) { + return ctx.prev.result; +} +""" + + +class LambdaAuthorizerConfigType(TypedDict, total=False): + AuthorizerResultTtlInSeconds: float + AuthorizerUri: Required[str] + IdentityValidationExpression: str + + +class OpenIDConnectConfigType(TypedDict, total=False): + AuthTTL: float + ClientId: str + IatTTL: float + Issuer: str + + +class UserPoolConfigType(TypedDict, total=False): + AppIdClientRegex: str + AwsRegion: str + DefaultAction: str + UserPoolId: Required[str] + + +class AdditionalAuthenticationProviderType(TypedDict, total=False): + AuthenticationType: str + LambdaAuthorizerConfig: LambdaAuthorizerConfigType + OpenIDConnectConfig: OpenIDConnectConfigType + UserPoolConfig: UserPoolConfigType + + +class DeltaSyncConfigType(TypedDict): + BaseTableTTL: str + DeltaSyncTableName: str + DeltaSyncTableTTL: str + + +class DynamoDBConfigType(TypedDict, total=False): + AwsRegion: Union[str, Dict[str, str]] + TableName: str + UseCallerCredentials: bool + Versioned: bool + DeltaSyncConfig: DeltaSyncConfigType + + +class LambdaConfigType(TypedDict, total=False): + LambdaFunctionArn: str + + +class LogConfigType(TypedDict, total=False): + CloudWatchLogsRoleArn: Intrinsicable[str] + ExcludeVerboseContent: bool + FieldLogLevel: str + + +class AppSyncRuntimeType(TypedDict): + Name: str + RuntimeVersion: str + + +class LambdaConflictHandlerConfigType(TypedDict): + LambdaConflictHandlerArn: str + + +class SyncConfigType(TypedDict, total=False): + ConflictDetection: str + ConflictHandler: str + LambdaConflictHandlerConfig: LambdaConflictHandlerConfigType + + +class CachingConfigType(TypedDict, total=False): + CachingKeys: List[str] + Ttl: float + + +class PipelineConfigType(TypedDict, total=False): + Functions: List[Intrinsicable[str]] + + +class GraphQLApi(Resource): + resource_type = "AWS::AppSync::GraphQLApi" + property_types = { + "Name": GeneratedProperty(), + "Tags": GeneratedProperty(), + "XrayEnabled": GeneratedProperty(), + "AuthenticationType": GeneratedProperty(), + "LogConfig": GeneratedProperty(), + "LambdaAuthorizerConfig": GeneratedProperty(), + "OpenIDConnectConfig": GeneratedProperty(), + "UserPoolConfig": GeneratedProperty(), + "AdditionalAuthenticationProviders": GeneratedProperty(), + } + + Name: str + AuthenticationType: str + LambdaAuthorizerConfig: Optional[LambdaAuthorizerConfigType] + OpenIDConnectConfig: Optional[OpenIDConnectConfigType] + UserPoolConfig: Optional[UserPoolConfigType] + AdditionalAuthenticationProviders: Optional[List[AdditionalAuthenticationProviderType]] + Tags: Optional[List[Dict[str, Any]]] + XrayEnabled: Optional[bool] + LogConfig: Optional[LogConfigType] + + runtime_attrs = {"api_id": lambda self: fnGetAtt(self.logical_id, "ApiId")} + + +class GraphQLSchema(Resource): + resource_type = "AWS::AppSync::GraphQLSchema" + property_types = { + "ApiId": GeneratedProperty(), + "Definition": GeneratedProperty(), + "DefinitionS3Location": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + Definition: Optional[str] + DefinitionS3Location: Optional[str] + + +class DataSource(Resource): + resource_type = "AWS::AppSync::DataSource" + property_types = { + "ApiId": GeneratedProperty(), + "Description": GeneratedProperty(), + "Name": GeneratedProperty(), + "Type": GeneratedProperty(), + "ServiceRoleArn": GeneratedProperty(), + "DynamoDBConfig": GeneratedProperty(), + "LambdaConfig": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + Description: Optional[str] + Name: str + Type: str + ServiceRoleArn: str + DynamoDBConfig: Optional[DynamoDBConfigType] + LambdaConfig: Optional[LambdaConfigType] + + runtime_attrs = { + "arn": lambda self: fnGetAtt(self.logical_id, "DataSourceArn"), + "name": lambda self: fnGetAtt(self.logical_id, "Name"), + } + + +class FunctionConfiguration(Resource): + resource_type = "AWS::AppSync::FunctionConfiguration" + property_types = { + "ApiId": GeneratedProperty(), + "Code": GeneratedProperty(), + "CodeS3Location": GeneratedProperty(), + "DataSourceName": GeneratedProperty(), + "Description": GeneratedProperty(), + "MaxBatchSize": GeneratedProperty(), + "Name": GeneratedProperty(), + "Runtime": GeneratedProperty(), + "SyncConfig": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + DataSourceName: Intrinsicable[str] + Name: str + Code: Optional[str] + CodeS3Location: Optional[str] + Description: Optional[str] + MaxBatchSize: Optional[int] + Runtime: Optional[AppSyncRuntimeType] + SyncConfig: Optional[SyncConfigType] + + runtime_attrs = {"function_id": lambda self: fnGetAtt(self.logical_id, "FunctionId")} + + +class Resolver(Resource): + resource_type = "AWS::AppSync::Resolver" + property_types = { + "ApiId": GeneratedProperty(), + "CachingConfig": GeneratedProperty(), + "Code": GeneratedProperty(), + "CodeS3Location": GeneratedProperty(), + "DataSourceName": GeneratedProperty(), + "FieldName": GeneratedProperty(), + "Kind": GeneratedProperty(), + "MaxBatchSize": GeneratedProperty(), + "PipelineConfig": GeneratedProperty(), + "Runtime": GeneratedProperty(), + "SyncConfig": GeneratedProperty(), + "TypeName": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + CachingConfig: Optional[CachingConfigType] + Code: Optional[str] + CodeS3Location: Optional[str] + DataSourceName: Optional[str] + FieldName: str + Kind: Optional[str] + MaxBatchSize: Optional[int] + PipelineConfig: Optional[PipelineConfigType] + Runtime: Optional[AppSyncRuntimeType] + SyncConfig: Optional[SyncConfigType] + TypeName: str + + +class ApiKey(Resource): + resource_type = "AWS::AppSync::ApiKey" + property_types = { + "ApiId": GeneratedProperty(), + "ApiKeyId": GeneratedProperty(), + "Description": GeneratedProperty(), + "Expires": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + ApiKeyId: Optional[str] + Description: Optional[str] + Expires: Optional[float] + + +class DomainName(Resource): + resource_type = "AWS::AppSync::DomainName" + property_types = { + "CertificateArn": GeneratedProperty(), + "Description": GeneratedProperty(), + "DomainName": GeneratedProperty(), + } + + CertificateArn: str + DomainName: str + Description: Optional[str] + + runtime_attrs = {"domain_name": lambda self: ref(self.logical_id)} + + +class DomainNameApiAssociation(Resource): + resource_type = "AWS::AppSync::DomainNameApiAssociation" + property_types = { + "ApiId": GeneratedProperty(), + "DomainName": GeneratedProperty(), + } + + ApiId: Intrinsicable[str] + DomainName: str + + +class ApiCache(Resource): + resource_type = "AWS::AppSync::ApiCache" + property_types = { + "ApiCachingBehavior": GeneratedProperty(), + "ApiId": GeneratedProperty(), + "AtRestEncryptionEnabled": GeneratedProperty(), + "TransitEncryptionEnabled": GeneratedProperty(), + "Ttl": GeneratedProperty(), + "Type": GeneratedProperty(), + } + + ApiCachingBehavior: str + ApiId: Intrinsicable[str] + Type: str + Ttl: float + AtRestEncryptionEnabled: Optional[bool] + TransitEncryptionEnabled: Optional[bool] diff --git a/samtranslator/internal/schema_source/aws_serverless_connector.py b/samtranslator/internal/schema_source/aws_serverless_connector.py index bdb4295ce..4142378a6 100644 --- a/samtranslator/internal/schema_source/aws_serverless_connector.py +++ b/samtranslator/internal/schema_source/aws_serverless_connector.py @@ -2,14 +2,18 @@ from typing_extensions import Literal -from samtranslator.internal.schema_source.common import BaseModel, PassThroughProp, ResourceAttributes, get_prop +from samtranslator.internal.schema_source.common import ( + BaseModel, + PassThroughProp, + PermissionsType, + ResourceAttributes, + get_prop, +) resourcereference = get_prop("sam-property-connector-resourcereference") properties = get_prop("sam-resource-connector") sourcereference = get_prop("sam-property-connector-sourcereference") -PermissionsType = List[Literal["Read", "Write"]] - class ResourceReference(BaseModel): Id: Optional[str] = resourcereference("Id") diff --git a/samtranslator/internal/schema_source/aws_serverless_graphqlapi.py b/samtranslator/internal/schema_source/aws_serverless_graphqlapi.py new file mode 100644 index 000000000..a90b6c82c --- /dev/null +++ b/samtranslator/internal/schema_source/aws_serverless_graphqlapi.py @@ -0,0 +1,171 @@ +from typing import Dict, List, Optional, Union + +from typing_extensions import Literal + +from samtranslator.internal.schema_source.common import ( + BaseModel, + DictStrAny, + PassThroughProp, + PermissionsType, + SamIntrinsicable, + get_prop, +) + +AuthenticationTypes = Literal["AWS_IAM", "API_KEY", "AWS_LAMBDA", "OPENID_CONNECT", "AMAZON_COGNITO_USER_POOLS"] + +properties = get_prop("sam-resource-graphqlapi") + + +# TODO: add docs +class LambdaAuthorizerConfig(BaseModel): + AuthorizerResultTtlInSeconds: Optional[PassThroughProp] + AuthorizerUri: PassThroughProp + IdentityValidationExpression: Optional[PassThroughProp] + + +class OpenIDConnectConfig(BaseModel): + AuthTTL: Optional[PassThroughProp] + ClientId: Optional[PassThroughProp] + IatTTL: Optional[PassThroughProp] + Issuer: Optional[PassThroughProp] + + +class UserPoolConfig(BaseModel): + AppIdClientRegex: Optional[PassThroughProp] + AwsRegion: Optional[PassThroughProp] + DefaultAction: Optional[PassThroughProp] + UserPoolId: PassThroughProp + + +class Authorizer(BaseModel): + Type: AuthenticationTypes + LambdaAuthorizer: Optional[LambdaAuthorizerConfig] + OpenIDConnect: Optional[OpenIDConnectConfig] + UserPool: Optional[UserPoolConfig] + + +class Auth(Authorizer): + Additional: Optional[List[Authorizer]] + + +class ApiKey(BaseModel): + ApiKeyId: Optional[PassThroughProp] + Description: Optional[PassThroughProp] + ExpiresOn: Optional[PassThroughProp] + + +class Logging(BaseModel): + CloudWatchLogsRoleArn: Optional[PassThroughProp] + ExcludeVerboseContent: Optional[PassThroughProp] + FieldLogLevel: Optional[str] + + +class DeltaSync(BaseModel): + BaseTableTTL: str + DeltaSyncTableName: str + DeltaSyncTableTTL: str + + +class DynamoDBDataSource(BaseModel): + TableName: PassThroughProp + ServiceRoleArn: Optional[PassThroughProp] + TableArn: Optional[PassThroughProp] + Permissions: Optional[PermissionsType] + Name: Optional[str] + Description: Optional[PassThroughProp] + Region: Optional[PassThroughProp] + DeltaSync: Optional[DeltaSync] + UseCallerCredentials: Optional[PassThroughProp] + Versioned: Optional[PassThroughProp] + + +class LambdaDataSource(BaseModel): + FunctionArn: PassThroughProp + ServiceRoleArn: Optional[PassThroughProp] + Name: Optional[str] + Description: Optional[PassThroughProp] + + +class DataSources(BaseModel): + DynamoDb: Optional[Dict[str, DynamoDBDataSource]] + Lambda: Optional[Dict[str, LambdaDataSource]] + + +class Runtime(BaseModel): + Name: PassThroughProp + Version: PassThroughProp + + +class LambdaConflictHandlerConfig(BaseModel): + LambdaConflictHandlerArn: PassThroughProp + + +class Sync(BaseModel): + ConflictDetection: PassThroughProp + ConflictHandler: Optional[PassThroughProp] + LambdaConflictHandlerConfig: Optional[LambdaConflictHandlerConfig] + + +class Function(BaseModel): + DataSource: Optional[SamIntrinsicable[str]] + Runtime: Optional[Runtime] + InlineCode: Optional[PassThroughProp] + CodeUri: Optional[PassThroughProp] + Description: Optional[PassThroughProp] + MaxBatchSize: Optional[PassThroughProp] + Name: Optional[str] + Id: Optional[PassThroughProp] + Sync: Optional[Sync] + + +class Caching(BaseModel): + Ttl: PassThroughProp + CachingKeys: Optional[List[PassThroughProp]] + + +class Resolver(BaseModel): + FieldName: Optional[str] + Caching: Optional[Caching] + InlineCode: Optional[PassThroughProp] + CodeUri: Optional[PassThroughProp] + MaxBatchSize: Optional[PassThroughProp] + Pipeline: Optional[ + List[str] + ] # keeping it optional allows for easier validation in to_cloudformation with better error messages + Runtime: Optional[Runtime] + Sync: Optional[Sync] + + +class DomainName(BaseModel): + CertificateArn: PassThroughProp + DomainName: PassThroughProp + Description: Optional[PassThroughProp] + + +class Cache(BaseModel): + ApiCachingBehavior: PassThroughProp + Ttl: PassThroughProp + Type: PassThroughProp + AtRestEncryptionEnabled: Optional[PassThroughProp] + TransitEncryptionEnabled: Optional[PassThroughProp] + + +class Properties(BaseModel): + Auth: Auth + Tags: Optional[DictStrAny] + Name: Optional[str] + XrayEnabled: Optional[bool] + SchemaInline: Optional[PassThroughProp] + SchemaUri: Optional[PassThroughProp] + Logging: Optional[Union[Logging, bool]] + DataSources: Optional[DataSources] + Functions: Optional[Dict[str, Function]] + Resolvers: Optional[Dict[str, Dict[str, Resolver]]] + ApiKeys: Optional[Dict[str, ApiKey]] + DomainName: Optional[DomainName] + Cache: Optional[Cache] + + +class Resource(BaseModel): + Type: Literal["AWS::Serverless::GraphQLApi"] + Properties: Properties diff --git a/samtranslator/internal/schema_source/common.py b/samtranslator/internal/schema_source/common.py index 0d7d802f9..66fc77d74 100644 --- a/samtranslator/internal/schema_source/common.py +++ b/samtranslator/internal/schema_source/common.py @@ -5,6 +5,7 @@ import pydantic from pydantic import Extra, Field +from typing_extensions import Literal from samtranslator.model.types import PassThrough @@ -35,6 +36,10 @@ class PassThroughProp(pydantic.BaseModel): _DOCS = json.loads((_docdir / "sam-docs.json").read_bytes()) +# Connector Permissions +PermissionsType = List[Literal["Read", "Write"]] + + def get_prop(stem: str) -> Any: return partial(_get_prop, stem) diff --git a/samtranslator/internal/schema_source/schema.py b/samtranslator/internal/schema_source/schema.py index 552ce7ced..0aa246ec9 100644 --- a/samtranslator/internal/schema_source/schema.py +++ b/samtranslator/internal/schema_source/schema.py @@ -14,6 +14,7 @@ aws_serverless_application, aws_serverless_connector, aws_serverless_function, + aws_serverless_graphqlapi, aws_serverless_httpapi, aws_serverless_layerversion, aws_serverless_simpletable, @@ -38,6 +39,7 @@ class Globals(BaseModel): aws_serverless_api.Resource, aws_serverless_httpapi.Resource, aws_serverless_application.Resource, + aws_serverless_graphqlapi.Resource, ] diff --git a/samtranslator/internal/utils/__init__.py b/samtranslator/internal/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/samtranslator/internal/utils/utils.py b/samtranslator/internal/utils/utils.py new file mode 100644 index 000000000..89d165a6b --- /dev/null +++ b/samtranslator/internal/utils/utils.py @@ -0,0 +1,22 @@ +from typing import Any, Dict, Optional, cast + +from samtranslator.internal.schema_source.common import PassThroughProp +from samtranslator.model.types import PassThrough + + +def remove_none_values(d: Dict[Any, Any]) -> Dict[Any, Any]: + """Returns a copy of the dictionary with no items that have the value None.""" + return {k: v for k, v in d.items() if v is not None} + + +def passthrough_value(v: Optional[PassThroughProp]) -> PassThrough: + """ + Cast PassThroughProp values to PassThrough. + + PassThroughProp has a __root__ value which is of type PassThrough. But mypy + does not look deep enough to see this type, and does not recognize it as Any, + so assignments to CFN resource types fail. So we cast to PassThrough here. + + We also accept None values so that it is a one line assignment for the consumer. + """ + return cast(PassThrough, v) diff --git a/samtranslator/model/__init__.py b/samtranslator/model/__init__.py index fdd383c59..381b348bd 100644 --- a/samtranslator/model/__init__.py +++ b/samtranslator/model/__init__.py @@ -350,10 +350,8 @@ def validate_properties_and_return_model(self, cls: Type[RT]) -> RT: except ValidationError as e: error_properties: str = "" with suppress(KeyError): - error_properties = ", ".join([str(error["loc"][0]) for error in e.errors()]) - raise InvalidResourceException( - self.logical_id, f"Given resource property '{error_properties}' is invalid" - ) from e + error_properties = ".".join(str(x) for x in e.errors()[0]["loc"]) + raise InvalidResourceException(self.logical_id, f"Property '{error_properties}' is invalid.") from e def validate_properties(self) -> None: """Validates that the required properties for this Resource have been populated, and that all properties have diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 6101a4669..e21109997 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -3,6 +3,8 @@ from contextlib import suppress from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast +from typing_extensions import Literal + import samtranslator.model.eventsources import samtranslator.model.eventsources.cloudwatchlogs import samtranslator.model.eventsources.pull @@ -10,7 +12,31 @@ import samtranslator.model.eventsources.scheduler from samtranslator.feature_toggle.feature_toggle import FeatureToggle from samtranslator.internal.intrinsics import resolve_string_parameter_in_resource +from samtranslator.internal.model.appsync import ( + APPSYNC_PIPELINE_RESOLVER_JS_CODE, + AdditionalAuthenticationProviderType, + ApiCache, + ApiKey, + AppSyncRuntimeType, + CachingConfigType, + DataSource, + DomainName, + DomainNameApiAssociation, + DynamoDBConfigType, + FunctionConfiguration, + GraphQLApi, + GraphQLSchema, + LambdaAuthorizerConfigType, + LogConfigType, + OpenIDConnectConfigType, + Resolver, + SyncConfigType, + UserPoolConfigType, +) +from samtranslator.internal.schema_source import aws_serverless_graphqlapi +from samtranslator.internal.schema_source.common import PermissionsType from samtranslator.internal.types import GetManagedPolicyMap +from samtranslator.internal.utils.utils import passthrough_value, remove_none_values from samtranslator.intrinsics.resolver import IntrinsicsResolver from samtranslator.metrics.method_decorator import cw_timer from samtranslator.model import ( @@ -53,6 +79,7 @@ from samtranslator.model.exceptions import InvalidEventException, InvalidResourceException from samtranslator.model.iam import IAMManagedPolicy, IAMRole, IAMRolePolicies from samtranslator.model.intrinsics import ( + fnGetAtt, is_intrinsic, is_intrinsic_if, is_intrinsic_no_value, @@ -2127,3 +2154,842 @@ def _add_connector_metadata( except KeyError: original_metadata = {} resource.set_resource_attribute("Metadata", {**original_metadata, **metadata}) + + +class SamGraphQLApi(SamResourceMacro): + """SAM GraphQL API Macro (WIP).""" + + resource_type = "AWS::Serverless::GraphQLApi" + property_types = { + "Name": Property(False, IS_STR), + "Tags": Property(False, IS_DICT), + "XrayEnabled": PassThroughProperty(False), + "Auth": Property(True, IS_DICT), + "SchemaInline": Property(False, IS_STR), + "SchemaUri": Property(False, IS_STR), + "Logging": Property(False, one_of(IS_DICT, IS_BOOL)), + "DataSources": Property(False, IS_DICT), + "Functions": Property(False, IS_DICT), + "Resolvers": Property(False, IS_DICT), + "ApiKeys": Property(False, IS_DICT), + "DomainName": Property(False, IS_DICT), + "Cache": Property(False, IS_DICT), + } + + Auth: List[Dict[str, Any]] + Tags: Optional[Dict[str, Any]] + XrayEnabled: Optional[PassThrough] + Name: Optional[str] + SchemaInline: Optional[str] + SchemaUri: Optional[str] + Logging: Optional[Union[Dict[str, Any], bool]] + DataSources: Optional[Dict[str, Dict[str, Dict[str, Any]]]] + Functions: Optional[Dict[str, Dict[str, Any]]] + Resolvers: Optional[Dict[str, Dict[str, Dict[str, Any]]]] + ApiKeys: Optional[Dict[str, Dict[str, Any]]] + DomainName: Optional[Dict[str, Any]] + Cache: Optional[Dict[str, Any]] + + # stop validation so we can use class variables for tracking state + validate_setattr = False + + def __init__( + self, + logical_id: Optional[Any], + relative_id: Optional[str] = None, + depends_on: Optional[List[str]] = None, + attributes: Optional[Dict[str, Any]] = None, + ): + super().__init__(logical_id, relative_id=relative_id, depends_on=depends_on, attributes=attributes) + + self._none_datasource: Optional[DataSource] = None + self._datasource_name_map: Dict[str, Intrinsicable[str]] = {} + self._function_id_map: Dict[str, Intrinsicable[str]] = {} + + @cw_timer + def to_cloudformation(self, **kwargs: Any) -> List[Resource]: + model = self.validate_properties_and_return_model(aws_serverless_graphqlapi.Properties) + + appsync_api, cloudwatch_role, auth_connectors = self._construct_appsync_api_resources(model) + api_id = appsync_api.get_runtime_attr("api_id") + appsync_schema = self._construct_appsync_schema(model, api_id) + + resources: List[Resource] = [appsync_api, appsync_schema] + + for connector in auth_connectors: + resources.extend(connector.to_cloudformation(**kwargs)) + + if cloudwatch_role: + resources.append(cloudwatch_role) + + if model.ApiKeys: + api_keys = self._construct_appsync_api_keys(model.ApiKeys, api_id) + resources.extend(api_keys) + + if model.Cache: + api_cache = self._construct_appsync_api_cache(model.Cache, api_id) + resources.append(api_cache) + + if model.DataSources: + datasource_resources = self._construct_datasource_resources(model.DataSources, api_id, kwargs) + resources.extend(datasource_resources) + + if model.DomainName: + domain_name_resources = self._construct_domain_name_resources(model.DomainName, api_id) + resources.extend(domain_name_resources) + + if model.Functions: + function_configurations = self._construct_appsync_function_configurations(model.Functions, api_id) + resources.extend(function_configurations) + + if model.Resolvers: + appsync_resolver_resources = self._construct_appsync_resolver_resources( + model.Resolvers, api_id, appsync_schema.logical_id + ) + resources.extend(appsync_resolver_resources) + + if self._none_datasource: + resources.append(self._none_datasource) + + return resources + + def _construct_appsync_api_resources( + self, model: aws_serverless_graphqlapi.Properties + ) -> Tuple[GraphQLApi, Optional[IAMRole], List[SamConnector]]: + api = GraphQLApi(logical_id=self.logical_id, depends_on=self.depends_on, attributes=self.resource_attributes) + + api.Name = model.Name or self.logical_id + api.XrayEnabled = model.XrayEnabled + + lambda_auth_arns = self._parse_and_set_auth_properties(api, model.Auth) + auth_connectors = [ + self._construct_lambda_auth_connector(api, arn, i) for i, arn in enumerate(lambda_auth_arns, 1) + ] + + if model.Tags: + api.Tags = get_tag_list(model.Tags) + + # Logging has 3 possible types: dict, bool, and None. + # GraphQLApi will not include logging if and only if the user explicity sets Logging as false boolean. + # It will for every other value (including true boolean which is essentially same as None). + if isinstance(model.Logging, bool) and model.Logging is False: + return api, None, auth_connectors + + api.LogConfig, cloudwatch_role = self._parse_logging_properties(model) + + return api, cloudwatch_role, auth_connectors + + def _parse_and_set_auth_properties( + self, api: GraphQLApi, auth: aws_serverless_graphqlapi.Auth + ) -> List[Intrinsicable[str]]: + """ + Parse the Auth properties in a Serverless::GraphQLApi resource. + + Returns: List of Lambda Function arns of Lambda authorizers. If no Lambda authorizer is used, the list is empty. + """ + # Keep all lambda authorizers together to create connectors later + lambda_auth_arns: List[Intrinsicable[str]] = [] + + # Default authoriser + default_auth = aws_serverless_graphqlapi.Authorizer.parse_obj( + {k: v for k, v in auth.dict().items() if k != "Additional"} + ) + name, auth_dict = self._validate_and_extract_authorizer_config(default_auth) + api.AuthenticationType = auth.Type + + # This would be much easier and type-safe if accessing the properties in Resource + # was a dictionary. Currently, top level properties are class attributes, but nested + # properties are dictionaries... + # TODO: Access properties in Resource class as dict? + if name and auth_dict: + setattr(api, name, auth_dict) + if name == "LambdaAuthorizerConfig": + lambda_auth_arns.append(cast(LambdaAuthorizerConfigType, auth_dict)["AuthorizerUri"]) + + # Additional authentication + additional_auths: List[AdditionalAuthenticationProviderType] = [] + if auth.Additional: + for index, additional in enumerate(auth.Additional): + name, auth_dict = self._validate_and_extract_authorizer_config(additional, index) + additional_auth: AdditionalAuthenticationProviderType = {"AuthenticationType": additional.Type} + if name and auth_dict: + additional_auth[name] = auth_dict + if name == "LambdaAuthorizerConfig": + lambda_auth_arns.append(cast(LambdaAuthorizerConfigType, auth_dict)["AuthorizerUri"]) + + additional_auths.append(additional_auth) + + if additional_auths: + api.AdditionalAuthenticationProviders = additional_auths + + return lambda_auth_arns + + def _validate_and_extract_authorizer_config( + self, + auth: aws_serverless_graphqlapi.Authorizer, + index: Optional[int] = None, + ) -> Tuple[ + Optional[Literal["LambdaAuthorizerConfig", "OpenIDConnectConfig", "UserPoolConfig"]], + Optional[Union[LambdaAuthorizerConfigType, OpenIDConnectConfigType, UserPoolConfigType]], + ]: + """ + Validates the authentication type and returns the name of the config property and the respective dictionary. + + The index parameter is only required if you are validating an AdditionalAuth, so that we can correctly + format the key path for any errors that are thrown. It is not necessary for Auth. + """ + # In each Auth index, you should only define a max of two properties. The "Type" property, and if + # necessary the associated config as well. + MAX_AUTH_PROPERTIES = 2 + + keys = remove_none_values(auth.dict()).keys() + if len(keys) > MAX_AUTH_PROPERTIES: + key_path = "'Auth'" if not index else f"'Auth.Additional.{index}'" + raise InvalidResourceException( + self.logical_id, f"{key_path} has more than one authentication configuration defined." + ) + + if auth.Type == "AWS_LAMBDA": + key_path = "Auth.LambdaAuthorizer" if not index else f"Auth.Additional.{index}.LambdaAuthorizer" + lambda_authorizer = sam_expect(auth.LambdaAuthorizer, self.logical_id, key_path).to_not_be_none( + "'LambdaAuthorizer' must be defined if type is 'AWS_LAMBDA'." + ) + return "LambdaAuthorizerConfig", cast( + LambdaAuthorizerConfigType, remove_none_values(lambda_authorizer.dict()) + ) + + if auth.Type == "OPENID_CONNECT": + key_path = "Auth.OpenIDConnect" if not index else f"Auth.Additional.{index}.OpenIDConnect" + openid_connect = sam_expect(auth.OpenIDConnect, self.logical_id, key_path).to_not_be_none( + "'OpenIDConnect' must be defined if type is 'OPENID_CONNECT'." + ) + return "OpenIDConnectConfig", cast(OpenIDConnectConfigType, remove_none_values(openid_connect.dict())) + + # Last possible type is "AMAZON_COGNITO_USER_POOLS" + if auth.Type == "AMAZON_COGNITO_USER_POOLS": + key_path = "Auth.UserPool" if not index else f"Auth.Additional.{index}.UserPool" + user_pool = sam_expect(auth.UserPool, self.logical_id, key_path).to_not_be_none( + "'UserPool' must be defined if type is 'AMAZON_COGNITO_USER_POOLS'." + ) + if index is not None: + # UserPoolConfig does not have the DefaultAction property UNLESS it is the primary authentication + # method (first index). If it is an additional authentication, we nullify this value. + user_pool.DefaultAction = None + return "UserPoolConfig", cast(UserPoolConfigType, remove_none_values(user_pool.dict())) + + return None, None + + @staticmethod + def _construct_lambda_auth_connector( + api: GraphQLApi, + lambda_arn: Intrinsicable[str], + auth_number: int, + ) -> SamConnector: + logical_id = f"{api.logical_id}ToLambdaAuthConnector{auth_number}" + connector_dict = { + "Type": "AWS::Serverless::Connector", + "Properties": { + "Source": { + "Type": "AWS::AppSync::GraphQLApi", + "Arn": ref(api.logical_id), + "ResourceId": fnGetAtt(api.logical_id, "ApiId"), + }, + "Destination": { + "Type": "AWS::Lambda::Function", + "Arn": lambda_arn, + }, + "Permissions": ["Write"], + }, + } + + # mypy thinks from_dict method returns "Resource" class instead of the inheriting parent class "SamResourceMacro" + return cast( + SamConnector, + SamConnector(logical_id=logical_id).from_dict(logical_id=logical_id, resource_dict=connector_dict), + ) + + def _create_logging_default(self) -> Tuple[LogConfigType, IAMRole]: + """ + Create a default logging configuration. + + This function is used when "Logging" property is a False boolean or NoneType. + """ + log_config: LogConfigType = {} + log_config["FieldLogLevel"] = "ALL" + cloudwatch_role = self._construct_cloudwatch_role() + log_config["CloudWatchLogsRoleArn"] = cloudwatch_role.get_runtime_attr("arn") + + return log_config, cloudwatch_role + + def _parse_logging_properties( + self, model: aws_serverless_graphqlapi.Properties + ) -> Tuple[LogConfigType, Optional[IAMRole]]: + """Parse logging properties from SAM template, and use defaults if required keys dont exist.""" + if not isinstance(model.Logging, aws_serverless_graphqlapi.Logging): + return self._create_logging_default() + + log_config: LogConfigType = {} + + if model.Logging.ExcludeVerboseContent: + log_config["ExcludeVerboseContent"] = cast(PassThrough, model.Logging.ExcludeVerboseContent) + + log_config["FieldLogLevel"] = model.Logging.FieldLogLevel or "ALL" + log_config["CloudWatchLogsRoleArn"] = cast(PassThrough, model.Logging.CloudWatchLogsRoleArn) + + if log_config["CloudWatchLogsRoleArn"]: + return log_config, None + + cloudwatch_role = self._construct_cloudwatch_role() + log_config["CloudWatchLogsRoleArn"] = cloudwatch_role.get_runtime_attr("arn") + + return log_config, cloudwatch_role + + def _construct_cloudwatch_role(self) -> IAMRole: + role = IAMRole( + logical_id=f"{self.logical_id}CloudWatchRole", + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + role.AssumeRolePolicyDocument = IAMRolePolicies.construct_assume_role_policy_for_service_principal( + "appsync.amazonaws.com" + ) + role.ManagedPolicyArns = [ + {"Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs"} + ] + return role + + def _construct_appsync_schema( + self, model: aws_serverless_graphqlapi.Properties, api_id: Intrinsicable[str] + ) -> GraphQLSchema: + schema = GraphQLSchema( + logical_id=f"{self.logical_id}Schema", depends_on=self.depends_on, attributes=self.resource_attributes + ) + + if not model.SchemaInline and not model.SchemaUri: + raise InvalidResourceException(self.logical_id, "One of 'SchemaInline' or 'SchemaUri' must be set.") + + if model.SchemaInline and model.SchemaUri: + raise InvalidResourceException( + self.logical_id, "Both 'SchemaInline' and 'SchemaUri' cannot be defined at the same time." + ) + + schema.ApiId = api_id + schema.Definition = passthrough_value(model.SchemaInline) + schema.DefinitionS3Location = passthrough_value(model.SchemaUri) + + return schema + + def _construct_appsync_api_keys( + self, api_keys: Dict[str, aws_serverless_graphqlapi.ApiKey], api_id: Intrinsicable[str] + ) -> List[Resource]: + resources: List[Resource] = [] + + # TODO: Add datetime parsing for ExpiresOn; currently expects Unix timestamp + for relative_id, api_key in api_keys.items(): + cfn_api_key = ApiKey( + logical_id=f"{self.logical_id}{relative_id}", + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + cfn_api_key.ApiId = api_id + cfn_api_key.ApiKeyId = passthrough_value(api_key.ApiKeyId) + cfn_api_key.Description = passthrough_value(api_key.Description) + cfn_api_key.Expires = passthrough_value(api_key.ExpiresOn) + resources.append(cfn_api_key) + + return resources + + def _construct_domain_name_resources( + self, domain_name: aws_serverless_graphqlapi.DomainName, api_id: Intrinsicable[str] + ) -> List[Resource]: + cfn_domain_name = DomainName( + logical_id=f"{self.logical_id}DomainName", depends_on=self.depends_on, attributes=self.resource_attributes + ) + cfn_domain_name.CertificateArn = passthrough_value(domain_name.CertificateArn) + cfn_domain_name.DomainName = passthrough_value(domain_name.DomainName) + cfn_domain_name.Description = passthrough_value(domain_name.Description) + + cfn_domain_name_api_association = DomainNameApiAssociation( + logical_id=f"{self.logical_id}DomainNameApiAssociation", + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + cfn_domain_name_api_association.ApiId = api_id + cfn_domain_name_api_association.DomainName = cfn_domain_name.get_runtime_attr("domain_name") + + return [cfn_domain_name, cfn_domain_name_api_association] + + def _construct_appsync_api_cache( + self, cache: aws_serverless_graphqlapi.Cache, api_id: Intrinsicable[str] + ) -> ApiCache: + cfn_api_cache = ApiCache( + logical_id=f"{self.logical_id}ApiCache", depends_on=self.depends_on, attributes=self.resource_attributes + ) + + cfn_api_cache.ApiId = api_id + cfn_api_cache.ApiCachingBehavior = passthrough_value(cache.ApiCachingBehavior) + cfn_api_cache.Type = passthrough_value(cache.Type) + cfn_api_cache.Ttl = passthrough_value(cache.Ttl) + cfn_api_cache.AtRestEncryptionEnabled = passthrough_value(cache.AtRestEncryptionEnabled) + cfn_api_cache.TransitEncryptionEnabled = passthrough_value(cache.TransitEncryptionEnabled) + + return cfn_api_cache + + def _construct_datasource_resources( + self, + datasources: aws_serverless_graphqlapi.DataSources, + api_id: Intrinsicable[str], + kwargs: Dict[str, Any], + ) -> List[Resource]: + ddb_datasources = self._construct_ddb_datasources(datasources.DynamoDb, api_id, kwargs) + lambda_datasources = self._construct_lambda_datasources(datasources.Lambda, api_id, kwargs) + + return [*ddb_datasources, *lambda_datasources] + + def _construct_ddb_datasources( + self, + ddb_datasources: Optional[Dict[str, aws_serverless_graphqlapi.DynamoDBDataSource]], + api_id: Intrinsicable[str], + kwargs: Dict[str, Any], + ) -> List[Resource]: + if not ddb_datasources: + return [] + + resources: List[Resource] = [] + + for relative_id, ddb_datasource in ddb_datasources.items(): + datasource_logical_id = self._create_appsync_data_source_logical_id( + self.logical_id, "DynamoDB", relative_id + ) + cfn_datasource = DataSource( + logical_id=datasource_logical_id, depends_on=self.depends_on, attributes=self.resource_attributes + ) + + # Datasource "Name" property must be unique from all other datasources. + cfn_datasource.Name = ddb_datasource.Name or relative_id + cfn_datasource.Type = "AMAZON_DYNAMODB" + cfn_datasource.ApiId = api_id + cfn_datasource.Description = passthrough_value(ddb_datasource.Description) + cfn_datasource.DynamoDBConfig = self._parse_ddb_config(ddb_datasource) + + cfn_datasource.ServiceRoleArn, permissions_resources = self._parse_ddb_datasource_role( + ddb_datasource, cfn_datasource.get_runtime_attr("arn"), relative_id, datasource_logical_id, kwargs + ) + + self._datasource_name_map[relative_id] = cfn_datasource.get_runtime_attr("name") + + resources.extend([cfn_datasource, *permissions_resources]) + + return resources + + def _parse_ddb_datasource_role( + self, + ddb_datasource: aws_serverless_graphqlapi.DynamoDBDataSource, + datasource_arn: Intrinsicable[str], + relative_id: str, + datasource_logical_id: str, + kwargs: Dict[str, Any], + ) -> Tuple[str, List[Resource]]: + # If the user defined a role, then there's no need to generate role/policy for them, so we return fast. + if ddb_datasource.ServiceRoleArn: + return cast(PassThrough, ddb_datasource.ServiceRoleArn), [] + + # If the user doesn't have their own role, then we will create for them if TableArn is defined. + table_arn = passthrough_value( + sam_expect( + ddb_datasource.TableArn, relative_id, f"DataSources.DynamoDb.{relative_id}.TableArn" + ).to_not_be_none( + "'TableArn' must be defined to create the role and policy if 'ServiceRoleArn' is not defined." + ) + ) + + permissions = ddb_datasource.Permissions or ["Read", "Write"] + + role_id = f"{datasource_logical_id}Role" + role = IAMRole( + logical_id=role_id, + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + role.AssumeRolePolicyDocument = IAMRolePolicies.construct_assume_role_policy_for_service_principal( + "appsync.amazonaws.com" + ) + role_arn = role.get_runtime_attr("arn") + + connector_resources = self._construct_ddb_datasource_connector_resources( + datasource_logical_id, datasource_arn, table_arn, permissions, role.get_runtime_attr("name"), kwargs + ) + + return role_arn, [role, *connector_resources] + + def _parse_ddb_config(self, ddb_datasource: aws_serverless_graphqlapi.DynamoDBDataSource) -> DynamoDBConfigType: + ddb_config: DynamoDBConfigType = {} + + ddb_config["AwsRegion"] = cast(PassThrough, ddb_datasource.Region) or ref("AWS::Region") + ddb_config["TableName"] = passthrough_value(ddb_datasource.TableName) + + if ddb_datasource.UseCallerCredentials: + ddb_config["UseCallerCredentials"] = cast(PassThrough, ddb_datasource.UseCallerCredentials) + + if ddb_datasource.Versioned: + ddb_config["Versioned"] = cast(PassThrough, ddb_datasource.Versioned) + + if ddb_datasource.DeltaSync: + deltasync_properties = ddb_datasource.DeltaSync.dict() + ddb_config["DeltaSyncConfig"] = cast(PassThrough, deltasync_properties) + + return ddb_config + + @staticmethod + def _construct_ddb_datasource_connector_resources( + datasource_id: str, + source_arn: Intrinsicable[str], + destination_arn: str, + permissions: PermissionsType, + role_name: Intrinsicable[str], + kwargs: Dict[str, Any], + ) -> List[Resource]: + logical_id = f"{datasource_id}ToTableConnector" + connector_dict = { + "Type": "AWS::Serverless::Connector", + "Properties": { + "Source": {"Type": "AWS::AppSync::DataSource", "Arn": source_arn, "RoleName": role_name}, + "Destination": { + "Type": "AWS::DynamoDB::Table", + "Arn": destination_arn, + }, + "Permissions": permissions, + }, + } + + # mypy thinks from_dict method returns "Resource" class instead of the inheriting parent class "SamResourceMacro" + connector = cast( + SamConnector, + SamConnector(logical_id=logical_id).from_dict(logical_id=logical_id, resource_dict=connector_dict), + ) + return connector.to_cloudformation(**kwargs) + + def _construct_lambda_datasources( + self, + lambda_datasources: Optional[Dict[str, aws_serverless_graphqlapi.LambdaDataSource]], + api_id: Intrinsicable[str], + kwargs: Dict[str, Any], + ) -> List[Resource]: + if not lambda_datasources: + return [] + + resources: List[Resource] = [] + + for relative_id, lambda_datasource in lambda_datasources.items(): + datasource_logical_id = self._create_appsync_data_source_logical_id(self.logical_id, "Lambda", relative_id) + cfn_datasource = DataSource( + logical_id=datasource_logical_id, depends_on=self.depends_on, attributes=self.resource_attributes + ) + + cfn_datasource.Name = lambda_datasource.Name or relative_id + cfn_datasource.Type = "AWS_LAMBDA" + cfn_datasource.ApiId = api_id + cfn_datasource.Description = passthrough_value(lambda_datasource.Description) + cfn_datasource.LambdaConfig = {"LambdaFunctionArn": passthrough_value(lambda_datasource.FunctionArn)} + + cfn_datasource.ServiceRoleArn, permissions_resources = self._parse_lambda_datasource_role( + lambda_datasource, + cfn_datasource.get_runtime_attr("arn"), + lambda_datasource.FunctionArn, + datasource_logical_id, + kwargs, + ) + + self._datasource_name_map[relative_id] = cfn_datasource.get_runtime_attr("name") + + resources.extend([cfn_datasource, *permissions_resources]) + + return resources + + def _parse_lambda_datasource_role( + self, + lambda_datasource: aws_serverless_graphqlapi.LambdaDataSource, + datasource_arn: Intrinsicable[str], + function_arn: PassThrough, + datasource_logical_id: str, + kwargs: Dict[str, Any], + ) -> Tuple[str, List[Resource]]: + if lambda_datasource.ServiceRoleArn: + return passthrough_value(lambda_datasource.ServiceRoleArn), [] + + role_logical_id = f"{datasource_logical_id}Role" + role = IAMRole( + logical_id=role_logical_id, + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + role.AssumeRolePolicyDocument = IAMRolePolicies.construct_assume_role_policy_for_service_principal( + "appsync.amazonaws.com" + ) + role_arn = role.get_runtime_attr("arn") + + connector_resources = self._construct_lambda_datasource_connector_resources( + datasource_logical_id, datasource_arn, function_arn, role.get_runtime_attr("name"), kwargs + ) + + return role_arn, [role, *connector_resources] + + @staticmethod + def _construct_lambda_datasource_connector_resources( + datasource_id: str, + source_arn: Intrinsicable[str], + destination_arn: Intrinsicable[str], + role_name: Intrinsicable[str], + kwargs: Dict[str, Any], + ) -> List[Resource]: + logical_id = f"{datasource_id}ToLambdaConnector" + connector_dict = { + "Type": "AWS::Serverless::Connector", + "Properties": { + "Source": {"Type": "AWS::AppSync::DataSource", "Arn": source_arn, "RoleName": role_name}, + "Destination": { + "Type": "AWS::Lambda::Function", + "Arn": destination_arn, + }, + "Permissions": ["Write"], + }, + } + + # mypy thinks from_dict method returns "Resource" class instead of the inheriting parent class "SamResourceMacro" + connector = cast( + SamConnector, + SamConnector(logical_id=logical_id).from_dict(logical_id=logical_id, resource_dict=connector_dict), + ) + + return connector.to_cloudformation(**kwargs) + + def _construct_appsync_function_configurations( + self, + functions: Dict[str, aws_serverless_graphqlapi.Function], + api_id: Intrinsicable[str], + ) -> List[FunctionConfiguration]: + func_configs: List[FunctionConfiguration] = [] + + for relative_id, function in functions.items(): + # "Id" refers to the "FunctionId" attribute for a "AppSync::FunctionConfiguration" resource. + # "Id" is a mutually exclusive property to every other property. If this function has it + # defined, then we make sure it's the only property, and continue to next function. + if function.Id: + keys = remove_none_values(function.dict()).keys() # remove undefined properties, then get keys + if len(keys) != 1: + raise InvalidResourceException( + relative_id, "'Id' cannot be defined with other properties in Function." + ) + self._function_id_map[relative_id] = passthrough_value(function.Id) + continue + + func_config = FunctionConfiguration( + logical_id=self.logical_id + relative_id, + depends_on=self.depends_on, + attributes=self.resource_attributes, + ) + + func_config.ApiId = api_id + func_config.Name = function.Name or relative_id + func_config.Code, func_config.CodeS3Location = self._parse_function_code_properties(function, relative_id) + func_config.DataSourceName = self._parse_datasource_name(relative_id, function, api_id) + func_config.MaxBatchSize = passthrough_value(function.MaxBatchSize) + func_config.Description = passthrough_value(function.Description) + func_config.Runtime = self._parse_runtime(function, relative_id) + + if function.Sync: + func_config.SyncConfig = cast(SyncConfigType, remove_none_values(function.Sync.dict())) + + self._function_id_map[relative_id] = func_config.get_runtime_attr("function_id") + func_configs.append(func_config) + + return func_configs + + @staticmethod + def _is_none_datasource_input(datasource: Optional[str]) -> bool: + return datasource is not None and datasource.lower() == "none" + + def _construct_none_datasource( + self, + api_id: Intrinsicable[str], + ) -> DataSource: + """ + Create DataSource with type "NONE". + + Within a Serverless::GraphQLApi Function or Resolver resource, customers can create + a DataSource of Type "NONE" for quick use. To do so, a customer can input "none" case + insensitive in the "DataSource" property. Only one DataSource will be created for each + GraphQLApi, and all GraphQLApi functions and resolvers with this none input will reference it. + + If a datasource is created, it is assigned to the class variable "none_datasource". This is so + we can reference when parsing both functions and resolvers. This function does not return any + value itself. + """ + none_datasource_logical_id = f"{self.logical_id}NoneDataSource" + none_datasource = DataSource( + logical_id=none_datasource_logical_id, depends_on=self.depends_on, attributes=self.resource_attributes + ) + none_datasource.ApiId = api_id + none_datasource.Name = none_datasource_logical_id + none_datasource.Type = "NONE" + + return none_datasource + + def _parse_datasource_name( + self, relative_id: str, function: aws_serverless_graphqlapi.Function, api_id: Intrinsicable[str] + ) -> Intrinsicable[str]: + """ + Parse DataSource name from a Serverless::GraphQLApi function or resolver. + + There are 3 different cases for the DataSource name: + + 1. Customer defines the "DataSource" property as a string or intrinsics, and we can simply return this value. + + 2. Customer defines "DataSource" propery as "NONE", so we return the name of the NoneDataSource + for this Serverless::GraphQLApi resource. + + 3. Customer defines "DataSource" property with a logical id of a datasource defined in + Serverless::GraphQLApi. We can then search if this DataSource exists, and return the name. + If it does not exist, throw an InvalidResourceException. + """ + if not function.DataSource: + raise InvalidResourceException(relative_id, "'DataSource' must be set.") + + if isinstance(function.DataSource, str): + if self._is_none_datasource_input(function.DataSource): + if not self._none_datasource: + self._none_datasource = self._construct_none_datasource(api_id) + return cast(Intrinsicable[str], self._none_datasource.get_runtime_attr("name")) + + if function.DataSource in self._datasource_name_map: + return self._datasource_name_map[function.DataSource] + + raise InvalidResourceException( + relative_id, + f"Either define DataSource '{function.DataSource}' in 'DataSources' or use intrinsic function like GetAtt, ImportValue, Sub or another one to reference a DataSource defined outside of this GraphQLApi resource.", + ) + + # if DataSource is intrinsic function like !GetAttr AppSyncDataSource.Name + # but it can also be ImportValue or Sub or maybe something else + return function.DataSource # it's an intrinsic function Dict here + + @staticmethod + def _parse_function_code_properties( + function: aws_serverless_graphqlapi.Function, + relative_id: str, + ) -> Tuple[Optional[PassThrough], Optional[PassThrough]]: + """ + Parses the code properties from Serverless::GraphQLApi function. + + This function parses the "CodeUri" and "InlineCode" properties for Function resources. + It also raises exceptions when the customer template is invalid. The return is a tuple of the values + (InlineCode, CodeUri). + """ + if function.InlineCode and function.CodeUri: + raise InvalidResourceException( + relative_id, "Both 'InlineCode' and 'CodeUri' cannot be defined at the same time." + ) + + if function.InlineCode: + return passthrough_value(function.InlineCode), None + + if function.CodeUri: + return None, passthrough_value(function.CodeUri) + + raise InvalidResourceException(relative_id, "One of 'InlineCode' or 'CodeUri' must be set.") + + @staticmethod + def _parse_runtime( + resource: Union[aws_serverless_graphqlapi.Function, aws_serverless_graphqlapi.Resolver], + relative_id: str, + ) -> AppSyncRuntimeType: + """ + Parse Runtime property of Function and Resolver. + """ + if resource.Runtime: + return { + "Name": passthrough_value(resource.Runtime.Name), + "RuntimeVersion": passthrough_value(resource.Runtime.Version), + } + + # Runtime is not defined, raise error. + raise InvalidResourceException(relative_id, f"'Runtime' must be defined as a property in {relative_id}.") + + def _construct_appsync_resolver_resources( + self, + resolvers: Dict[str, Dict[str, aws_serverless_graphqlapi.Resolver]], + api_id: Intrinsicable[str], + schema_logical_id: str, + ) -> List[Resource]: + resources: List[Resource] = [] + + for type_name, relative_id_to_resolver in resolvers.items(): + for relative_id, resolver in relative_id_to_resolver.items(): + cfn_resolver = Resolver( + logical_id=self.logical_id + type_name + relative_id, + depends_on=[schema_logical_id], + attributes=self.resource_attributes, + ) + + if resolver.CodeUri and resolver.InlineCode: + raise InvalidResourceException( + relative_id, "Both 'InlineCode' and 'CodeUri' cannot be defined at the same time." + ) + + cfn_resolver.Code = passthrough_value(resolver.InlineCode) + cfn_resolver.CodeS3Location = passthrough_value(resolver.CodeUri) + + # If InlineCode and CodeUri were not defined, then we will set the resolver code + # to a default snippet which has basic definition of request/response functions. + if not cfn_resolver.Code and not cfn_resolver.CodeS3Location: + cfn_resolver.Code = APPSYNC_PIPELINE_RESOLVER_JS_CODE + + cfn_resolver.ApiId = api_id + cfn_resolver.FieldName = resolver.FieldName or relative_id + cfn_resolver.TypeName = type_name + cfn_resolver.Runtime = self._parse_runtime(resolver, relative_id) + + if resolver.Pipeline: + cfn_resolver.Kind = "PIPELINE" + function_ids = self._parse_appsync_resolver_functions(resolver, relative_id) + cfn_resolver.PipelineConfig = {"Functions": function_ids} + else: + raise InvalidResourceException( + relative_id, + f"Resolver '{relative_id}' must have Pipeline defined. Unit resolvers are not supported. If you need a Unit resolver you can use AppSync resource.", + ) + + if resolver.Caching: + cfn_resolver.CachingConfig = cast(CachingConfigType, resolver.Caching.dict(exclude_none=True)) + + if resolver.MaxBatchSize: + cfn_resolver.MaxBatchSize = passthrough_value(resolver.MaxBatchSize) + + resources.append(cfn_resolver) + + return resources + + def _parse_appsync_resolver_functions( + self, appsync_resolver: aws_serverless_graphqlapi.Resolver, relative_id: str + ) -> List[Intrinsicable[str]]: + """ + Parse functions property in GraphQLApi Resolver. + + When a resolver has the functions property defined, it is a pipeline resolver. These functions are + executed in the order they are listed in the template. + """ + function_ids = [] + + # This function is only called if it is a pipeline resolver, in which case this property is checked to exist before. + # Because the type of the variable does not update, we must cast here. + + for resolver_function in appsync_resolver.Pipeline or []: + if resolver_function not in self._function_id_map: + raise InvalidResourceException(relative_id, f"Function '{resolver_function}' does not exist.") + function_ids.append(self._function_id_map[resolver_function]) + + return function_ids + + @staticmethod + def _create_appsync_data_source_logical_id(api_id: str, data_source_type: str, data_source_relative_id: str) -> str: + return f"{api_id}{data_source_relative_id}{data_source_type}DataSource" diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 9b57cc83b..fad615e71 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -236261,6 +236261,99 @@ "title": "ApiAuth", "type": "object" }, + "ApiKey": { + "additionalProperties": false, + "properties": { + "ApiKeyId": { + "$ref": "#/definitions/PassThroughProp" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExpiresOn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "ApiKey", + "type": "object" + }, + "Authorizer": { + "additionalProperties": false, + "properties": { + "LambdaAuthorizer": { + "$ref": "#/definitions/LambdaAuthorizerConfig" + }, + "OpenIDConnect": { + "$ref": "#/definitions/OpenIDConnectConfig" + }, + "Type": { + "enum": [ + "AWS_IAM", + "API_KEY", + "AWS_LAMBDA", + "OPENID_CONNECT", + "AMAZON_COGNITO_USER_POOLS" + ], + "title": "Type", + "type": "string" + }, + "UserPool": { + "$ref": "#/definitions/UserPoolConfig" + } + }, + "required": [ + "Type" + ], + "title": "Authorizer", + "type": "object" + }, + "Cache": { + "additionalProperties": false, + "properties": { + "ApiCachingBehavior": { + "$ref": "#/definitions/PassThroughProp" + }, + "AtRestEncryptionEnabled": { + "$ref": "#/definitions/PassThroughProp" + }, + "TransitEncryptionEnabled": { + "$ref": "#/definitions/PassThroughProp" + }, + "Ttl": { + "$ref": "#/definitions/PassThroughProp" + }, + "Type": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "ApiCachingBehavior", + "Ttl", + "Type" + ], + "title": "Cache", + "type": "object" + }, + "Caching": { + "additionalProperties": false, + "properties": { + "CachingKeys": { + "items": { + "$ref": "#/definitions/PassThroughProp" + }, + "title": "Cachingkeys", + "type": "array" + }, + "Ttl": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Ttl" + ], + "title": "Caching", + "type": "object" + }, "CloudWatchLogsEvent": { "additionalProperties": false, "properties": { @@ -236580,6 +236673,27 @@ ], "type": "object" }, + "DataSources": { + "additionalProperties": false, + "properties": { + "DynamoDb": { + "additionalProperties": { + "$ref": "#/definitions/DynamoDBDataSource" + }, + "title": "Dynamodb", + "type": "object" + }, + "Lambda": { + "additionalProperties": { + "$ref": "#/definitions/LambdaDataSource" + }, + "title": "Lambda", + "type": "object" + } + }, + "title": "DataSources", + "type": "object" + }, "DeadLetterQueue": { "additionalProperties": false, "properties": { @@ -236605,6 +236719,30 @@ "title": "DeadLetterQueue", "type": "object" }, + "DeltaSync": { + "additionalProperties": false, + "properties": { + "BaseTableTTL": { + "title": "Basetablettl", + "type": "string" + }, + "DeltaSyncTableName": { + "title": "Deltasynctablename", + "type": "string" + }, + "DeltaSyncTableTTL": { + "title": "Deltasynctablettl", + "type": "string" + } + }, + "required": [ + "BaseTableTTL", + "DeltaSyncTableName", + "DeltaSyncTableTTL" + ], + "title": "DeltaSync", + "type": "object" + }, "DeploymentPreference": { "additionalProperties": false, "properties": { @@ -236836,6 +236974,75 @@ "title": "DocumentDBEventProperties", "type": "object" }, + "DomainName": { + "additionalProperties": false, + "properties": { + "CertificateArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "DomainName": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "CertificateArn", + "DomainName" + ], + "title": "DomainName", + "type": "object" + }, + "DynamoDBDataSource": { + "additionalProperties": false, + "properties": { + "DeltaSync": { + "$ref": "#/definitions/DeltaSync" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Permissions": { + "items": { + "enum": [ + "Read", + "Write" + ], + "type": "string" + }, + "title": "Permissions", + "type": "array" + }, + "Region": { + "$ref": "#/definitions/PassThroughProp" + }, + "ServiceRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "TableArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "TableName": { + "$ref": "#/definitions/PassThroughProp" + }, + "UseCallerCredentials": { + "$ref": "#/definitions/PassThroughProp" + }, + "Versioned": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "TableName" + ], + "title": "DynamoDBDataSource", + "type": "object" + }, "DynamoDBEvent": { "additionalProperties": false, "properties": { @@ -237284,6 +237491,49 @@ "title": "EventsScheduleProperties", "type": "object" }, + "Function": { + "additionalProperties": false, + "properties": { + "CodeUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "DataSource": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "title": "Datasource" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "Id": { + "$ref": "#/definitions/PassThroughProp" + }, + "InlineCode": { + "$ref": "#/definitions/PassThroughProp" + }, + "MaxBatchSize": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Runtime": { + "$ref": "#/definitions/Runtime" + }, + "Sync": { + "$ref": "#/definitions/Sync" + } + }, + "title": "Function", + "type": "object" + }, "FunctionUrlConfig": { "additionalProperties": false, "properties": { @@ -237756,6 +238006,25 @@ "title": "LambdaAuthorizer", "type": "object" }, + "LambdaAuthorizerConfig": { + "additionalProperties": false, + "properties": { + "AuthorizerResultTtlInSeconds": { + "$ref": "#/definitions/PassThroughProp" + }, + "AuthorizerUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "IdentityValidationExpression": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "AuthorizerUri" + ], + "title": "LambdaAuthorizerConfig", + "type": "object" + }, "LambdaAuthorizerIdentity": { "additionalProperties": false, "properties": { @@ -237800,6 +238069,42 @@ "title": "LambdaAuthorizerIdentity", "type": "object" }, + "LambdaConflictHandlerConfig": { + "additionalProperties": false, + "properties": { + "LambdaConflictHandlerArn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "LambdaConflictHandlerArn" + ], + "title": "LambdaConflictHandlerConfig", + "type": "object" + }, + "LambdaDataSource": { + "additionalProperties": false, + "properties": { + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "FunctionArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "ServiceRoleArn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "FunctionArn" + ], + "title": "LambdaDataSource", + "type": "object" + }, "LambdaRequestAuthorizer": { "additionalProperties": false, "properties": { @@ -238029,6 +238334,23 @@ "title": "Location", "type": "object" }, + "Logging": { + "additionalProperties": false, + "properties": { + "CloudWatchLogsRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExcludeVerboseContent": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldLogLevel": { + "title": "Fieldloglevel", + "type": "string" + } + }, + "title": "Logging", + "type": "object" + }, "MQEvent": { "additionalProperties": false, "properties": { @@ -238282,6 +238604,25 @@ "title": "OAuth2Authorizer", "type": "object" }, + "OpenIDConnectConfig": { + "additionalProperties": false, + "properties": { + "AuthTTL": { + "$ref": "#/definitions/PassThroughProp" + }, + "ClientId": { + "$ref": "#/definitions/PassThroughProp" + }, + "IatTTL": { + "$ref": "#/definitions/PassThroughProp" + }, + "Issuer": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "OpenIDConnectConfig", + "type": "object" + }, "Parameter": { "additionalProperties": false, "properties": { @@ -238458,6 +238799,42 @@ "title": "RequestParameters", "type": "object" }, + "Resolver": { + "additionalProperties": false, + "properties": { + "Caching": { + "$ref": "#/definitions/Caching" + }, + "CodeUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldName": { + "title": "Fieldname", + "type": "string" + }, + "InlineCode": { + "$ref": "#/definitions/PassThroughProp" + }, + "MaxBatchSize": { + "$ref": "#/definitions/PassThroughProp" + }, + "Pipeline": { + "items": { + "type": "string" + }, + "title": "Pipeline", + "type": "array" + }, + "Runtime": { + "$ref": "#/definitions/Runtime" + }, + "Sync": { + "$ref": "#/definitions/Sync" + } + }, + "title": "Resolver", + "type": "object" + }, "ResourceReference": { "additionalProperties": false, "properties": { @@ -238529,6 +238906,23 @@ "title": "ResourceReference", "type": "object" }, + "Runtime": { + "additionalProperties": false, + "properties": { + "Name": { + "$ref": "#/definitions/PassThroughProp" + }, + "Version": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Name", + "Version" + ], + "title": "Runtime", + "type": "object" + }, "S3Event": { "additionalProperties": false, "properties": { @@ -239054,6 +239448,25 @@ "title": "SqsSubscription", "type": "object" }, + "Sync": { + "additionalProperties": false, + "properties": { + "ConflictDetection": { + "$ref": "#/definitions/PassThroughProp" + }, + "ConflictHandler": { + "$ref": "#/definitions/PassThroughProp" + }, + "LambdaConflictHandlerConfig": { + "$ref": "#/definitions/LambdaConflictHandlerConfig" + } + }, + "required": [ + "ConflictDetection" + ], + "title": "Sync", + "type": "object" + }, "Tag": { "additionalProperties": false, "properties": { @@ -239142,6 +239555,28 @@ "title": "UsagePlan", "type": "object" }, + "UserPoolConfig": { + "additionalProperties": false, + "properties": { + "AppIdClientRegex": { + "$ref": "#/definitions/PassThroughProp" + }, + "AwsRegion": { + "$ref": "#/definitions/PassThroughProp" + }, + "DefaultAction": { + "$ref": "#/definitions/PassThroughProp" + }, + "UserPoolId": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "UserPoolId" + ], + "title": "UserPoolConfig", + "type": "object" + }, "__main____Globals": { "additionalProperties": false, "properties": { @@ -241476,6 +241911,139 @@ "title": "ScheduleV2EventProperties", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Auth": { + "additionalProperties": false, + "properties": { + "Additional": { + "items": { + "$ref": "#/definitions/Authorizer" + }, + "title": "Additional", + "type": "array" + }, + "LambdaAuthorizer": { + "$ref": "#/definitions/LambdaAuthorizerConfig" + }, + "OpenIDConnect": { + "$ref": "#/definitions/OpenIDConnectConfig" + }, + "Type": { + "enum": [ + "AWS_IAM", + "API_KEY", + "AWS_LAMBDA", + "OPENID_CONNECT", + "AMAZON_COGNITO_USER_POOLS" + ], + "title": "Type", + "type": "string" + }, + "UserPool": { + "$ref": "#/definitions/UserPoolConfig" + } + }, + "required": [ + "Type" + ], + "title": "Auth", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties": { + "additionalProperties": false, + "properties": { + "ApiKeys": { + "additionalProperties": { + "$ref": "#/definitions/ApiKey" + }, + "title": "Apikeys", + "type": "object" + }, + "Auth": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Auth" + }, + "Cache": { + "$ref": "#/definitions/Cache" + }, + "DataSources": { + "$ref": "#/definitions/DataSources" + }, + "DomainName": { + "$ref": "#/definitions/DomainName" + }, + "Functions": { + "additionalProperties": { + "$ref": "#/definitions/Function" + }, + "title": "Functions", + "type": "object" + }, + "Logging": { + "anyOf": [ + { + "$ref": "#/definitions/Logging" + }, + { + "type": "boolean" + } + ], + "title": "Logging" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Resolvers": { + "additionalProperties": { + "additionalProperties": { + "$ref": "#/definitions/Resolver" + }, + "type": "object" + }, + "title": "Resolvers", + "type": "object" + }, + "SchemaInline": { + "$ref": "#/definitions/PassThroughProp" + }, + "SchemaUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "Tags": { + "title": "Tags", + "type": "object" + }, + "XrayEnabled": { + "title": "Xrayenabled", + "type": "boolean" + } + }, + "required": [ + "Auth" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Resource": { + "additionalProperties": false, + "properties": { + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::GraphQLApi" + ], + "title": "Type", + "type": "string" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_httpapi__Auth": { "additionalProperties": false, "properties": { @@ -243122,6 +243690,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_application__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Resource" + }, { "$ref": "#/definitions/AWS::ACMPCA::Certificate" }, diff --git a/samtranslator/translator/verify_logical_id.py b/samtranslator/translator/verify_logical_id.py index 71e5b0471..4dd27882c 100644 --- a/samtranslator/translator/verify_logical_id.py +++ b/samtranslator/translator/verify_logical_id.py @@ -16,6 +16,7 @@ "AWS::ApiGateway::DomainName": "AWS::ApiGateway::DomainName", "AWS::ApiGateway::BasePathMapping": "AWS::ApiGateway::BasePathMapping", "AWS::StepFunctions::StateMachine": "AWS::Serverless::StateMachine", + "AWS::AppSync::GraphQLApi": "AWS::Serverless::GraphQLApi", } diff --git a/samtranslator/validator/sam_schema/schema_new.json b/samtranslator/validator/sam_schema/schema_new.json index 0dd7e0592..1b55fdbe3 100644 --- a/samtranslator/validator/sam_schema/schema_new.json +++ b/samtranslator/validator/sam_schema/schema_new.json @@ -110,8 +110,8 @@ "AWS::Serverless::LayerVersion", "AWS::Serverless::SimpleTable", "AWS::Serverless::StateMachine", - "AWS::Serverless::Connector" - ] + "AWS::Serverless::Connector", + "AWS::Serverless::GraphQLApi" ] } } } diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 6de0adf76..d391887ad 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -86,6 +86,99 @@ "title": "ApiAuth", "type": "object" }, + "ApiKey": { + "additionalProperties": false, + "properties": { + "ApiKeyId": { + "$ref": "#/definitions/PassThroughProp" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExpiresOn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "ApiKey", + "type": "object" + }, + "Authorizer": { + "additionalProperties": false, + "properties": { + "LambdaAuthorizer": { + "$ref": "#/definitions/LambdaAuthorizerConfig" + }, + "OpenIDConnect": { + "$ref": "#/definitions/OpenIDConnectConfig" + }, + "Type": { + "enum": [ + "AWS_IAM", + "API_KEY", + "AWS_LAMBDA", + "OPENID_CONNECT", + "AMAZON_COGNITO_USER_POOLS" + ], + "title": "Type", + "type": "string" + }, + "UserPool": { + "$ref": "#/definitions/UserPoolConfig" + } + }, + "required": [ + "Type" + ], + "title": "Authorizer", + "type": "object" + }, + "Cache": { + "additionalProperties": false, + "properties": { + "ApiCachingBehavior": { + "$ref": "#/definitions/PassThroughProp" + }, + "AtRestEncryptionEnabled": { + "$ref": "#/definitions/PassThroughProp" + }, + "TransitEncryptionEnabled": { + "$ref": "#/definitions/PassThroughProp" + }, + "Ttl": { + "$ref": "#/definitions/PassThroughProp" + }, + "Type": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "ApiCachingBehavior", + "Ttl", + "Type" + ], + "title": "Cache", + "type": "object" + }, + "Caching": { + "additionalProperties": false, + "properties": { + "CachingKeys": { + "items": { + "$ref": "#/definitions/PassThroughProp" + }, + "title": "Cachingkeys", + "type": "array" + }, + "Ttl": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Ttl" + ], + "title": "Caching", + "type": "object" + }, "CloudWatchLogsEvent": { "additionalProperties": false, "properties": { @@ -415,6 +508,27 @@ "title": "Cors", "type": "object" }, + "DataSources": { + "additionalProperties": false, + "properties": { + "DynamoDb": { + "additionalProperties": { + "$ref": "#/definitions/DynamoDBDataSource" + }, + "title": "Dynamodb", + "type": "object" + }, + "Lambda": { + "additionalProperties": { + "$ref": "#/definitions/LambdaDataSource" + }, + "title": "Lambda", + "type": "object" + } + }, + "title": "DataSources", + "type": "object" + }, "DeadLetterQueue": { "additionalProperties": false, "properties": { @@ -440,6 +554,30 @@ "title": "DeadLetterQueue", "type": "object" }, + "DeltaSync": { + "additionalProperties": false, + "properties": { + "BaseTableTTL": { + "title": "Basetablettl", + "type": "string" + }, + "DeltaSyncTableName": { + "title": "Deltasynctablename", + "type": "string" + }, + "DeltaSyncTableTTL": { + "title": "Deltasynctablettl", + "type": "string" + } + }, + "required": [ + "BaseTableTTL", + "DeltaSyncTableName", + "DeltaSyncTableTTL" + ], + "title": "DeltaSync", + "type": "object" + }, "DeploymentPreference": { "additionalProperties": false, "properties": { @@ -682,6 +820,75 @@ "title": "DocumentDBEventProperties", "type": "object" }, + "DomainName": { + "additionalProperties": false, + "properties": { + "CertificateArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "DomainName": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "CertificateArn", + "DomainName" + ], + "title": "DomainName", + "type": "object" + }, + "DynamoDBDataSource": { + "additionalProperties": false, + "properties": { + "DeltaSync": { + "$ref": "#/definitions/DeltaSync" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Permissions": { + "items": { + "enum": [ + "Read", + "Write" + ], + "type": "string" + }, + "title": "Permissions", + "type": "array" + }, + "Region": { + "$ref": "#/definitions/PassThroughProp" + }, + "ServiceRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "TableArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "TableName": { + "$ref": "#/definitions/PassThroughProp" + }, + "UseCallerCredentials": { + "$ref": "#/definitions/PassThroughProp" + }, + "Versioned": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "TableName" + ], + "title": "DynamoDBDataSource", + "type": "object" + }, "DynamoDBEvent": { "additionalProperties": false, "properties": { @@ -1148,6 +1355,49 @@ "title": "EventsScheduleProperties", "type": "object" }, + "Function": { + "additionalProperties": false, + "properties": { + "CodeUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "DataSource": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ], + "title": "Datasource" + }, + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "Id": { + "$ref": "#/definitions/PassThroughProp" + }, + "InlineCode": { + "$ref": "#/definitions/PassThroughProp" + }, + "MaxBatchSize": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Runtime": { + "$ref": "#/definitions/Runtime" + }, + "Sync": { + "$ref": "#/definitions/Sync" + } + }, + "title": "Function", + "type": "object" + }, "FunctionUrlConfig": { "additionalProperties": false, "properties": { @@ -1620,6 +1870,25 @@ "title": "LambdaAuthorizer", "type": "object" }, + "LambdaAuthorizerConfig": { + "additionalProperties": false, + "properties": { + "AuthorizerResultTtlInSeconds": { + "$ref": "#/definitions/PassThroughProp" + }, + "AuthorizerUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "IdentityValidationExpression": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "AuthorizerUri" + ], + "title": "LambdaAuthorizerConfig", + "type": "object" + }, "LambdaAuthorizerIdentity": { "additionalProperties": false, "properties": { @@ -1664,6 +1933,42 @@ "title": "LambdaAuthorizerIdentity", "type": "object" }, + "LambdaConflictHandlerConfig": { + "additionalProperties": false, + "properties": { + "LambdaConflictHandlerArn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "LambdaConflictHandlerArn" + ], + "title": "LambdaConflictHandlerConfig", + "type": "object" + }, + "LambdaDataSource": { + "additionalProperties": false, + "properties": { + "Description": { + "$ref": "#/definitions/PassThroughProp" + }, + "FunctionArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "ServiceRoleArn": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "FunctionArn" + ], + "title": "LambdaDataSource", + "type": "object" + }, "LambdaRequestAuthorizer": { "additionalProperties": false, "properties": { @@ -1893,6 +2198,23 @@ "title": "Location", "type": "object" }, + "Logging": { + "additionalProperties": false, + "properties": { + "CloudWatchLogsRoleArn": { + "$ref": "#/definitions/PassThroughProp" + }, + "ExcludeVerboseContent": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldLogLevel": { + "title": "Fieldloglevel", + "type": "string" + } + }, + "title": "Logging", + "type": "object" + }, "MQEvent": { "additionalProperties": false, "properties": { @@ -2146,6 +2468,25 @@ "title": "OAuth2Authorizer", "type": "object" }, + "OpenIDConnectConfig": { + "additionalProperties": false, + "properties": { + "AuthTTL": { + "$ref": "#/definitions/PassThroughProp" + }, + "ClientId": { + "$ref": "#/definitions/PassThroughProp" + }, + "IatTTL": { + "$ref": "#/definitions/PassThroughProp" + }, + "Issuer": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "title": "OpenIDConnectConfig", + "type": "object" + }, "PassThroughProp": {}, "PrimaryKey": { "additionalProperties": false, @@ -2253,6 +2594,42 @@ "title": "RequestParameters", "type": "object" }, + "Resolver": { + "additionalProperties": false, + "properties": { + "Caching": { + "$ref": "#/definitions/Caching" + }, + "CodeUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "FieldName": { + "title": "Fieldname", + "type": "string" + }, + "InlineCode": { + "$ref": "#/definitions/PassThroughProp" + }, + "MaxBatchSize": { + "$ref": "#/definitions/PassThroughProp" + }, + "Pipeline": { + "items": { + "type": "string" + }, + "title": "Pipeline", + "type": "array" + }, + "Runtime": { + "$ref": "#/definitions/Runtime" + }, + "Sync": { + "$ref": "#/definitions/Sync" + } + }, + "title": "Resolver", + "type": "object" + }, "ResourceReference": { "additionalProperties": false, "properties": { @@ -2324,6 +2701,23 @@ "title": "ResourceReference", "type": "object" }, + "Runtime": { + "additionalProperties": false, + "properties": { + "Name": { + "$ref": "#/definitions/PassThroughProp" + }, + "Version": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "Name", + "Version" + ], + "title": "Runtime", + "type": "object" + }, "S3Event": { "additionalProperties": false, "properties": { @@ -2849,6 +3243,25 @@ "title": "SqsSubscription", "type": "object" }, + "Sync": { + "additionalProperties": false, + "properties": { + "ConflictDetection": { + "$ref": "#/definitions/PassThroughProp" + }, + "ConflictHandler": { + "$ref": "#/definitions/PassThroughProp" + }, + "LambdaConflictHandlerConfig": { + "$ref": "#/definitions/LambdaConflictHandlerConfig" + } + }, + "required": [ + "ConflictDetection" + ], + "title": "Sync", + "type": "object" + }, "UsagePlan": { "additionalProperties": false, "properties": { @@ -2921,6 +3334,28 @@ "title": "UsagePlan", "type": "object" }, + "UserPoolConfig": { + "additionalProperties": false, + "properties": { + "AppIdClientRegex": { + "$ref": "#/definitions/PassThroughProp" + }, + "AwsRegion": { + "$ref": "#/definitions/PassThroughProp" + }, + "DefaultAction": { + "$ref": "#/definitions/PassThroughProp" + }, + "UserPoolId": { + "$ref": "#/definitions/PassThroughProp" + } + }, + "required": [ + "UserPoolId" + ], + "title": "UserPoolConfig", + "type": "object" + }, "__main____Globals": { "additionalProperties": false, "properties": { @@ -6007,6 +6442,139 @@ "title": "ScheduleV2EventProperties", "type": "object" }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Auth": { + "additionalProperties": false, + "properties": { + "Additional": { + "items": { + "$ref": "#/definitions/Authorizer" + }, + "title": "Additional", + "type": "array" + }, + "LambdaAuthorizer": { + "$ref": "#/definitions/LambdaAuthorizerConfig" + }, + "OpenIDConnect": { + "$ref": "#/definitions/OpenIDConnectConfig" + }, + "Type": { + "enum": [ + "AWS_IAM", + "API_KEY", + "AWS_LAMBDA", + "OPENID_CONNECT", + "AMAZON_COGNITO_USER_POOLS" + ], + "title": "Type", + "type": "string" + }, + "UserPool": { + "$ref": "#/definitions/UserPoolConfig" + } + }, + "required": [ + "Type" + ], + "title": "Auth", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties": { + "additionalProperties": false, + "properties": { + "ApiKeys": { + "additionalProperties": { + "$ref": "#/definitions/ApiKey" + }, + "title": "Apikeys", + "type": "object" + }, + "Auth": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Auth" + }, + "Cache": { + "$ref": "#/definitions/Cache" + }, + "DataSources": { + "$ref": "#/definitions/DataSources" + }, + "DomainName": { + "$ref": "#/definitions/DomainName" + }, + "Functions": { + "additionalProperties": { + "$ref": "#/definitions/Function" + }, + "title": "Functions", + "type": "object" + }, + "Logging": { + "anyOf": [ + { + "$ref": "#/definitions/Logging" + }, + { + "type": "boolean" + } + ], + "title": "Logging" + }, + "Name": { + "title": "Name", + "type": "string" + }, + "Resolvers": { + "additionalProperties": { + "additionalProperties": { + "$ref": "#/definitions/Resolver" + }, + "type": "object" + }, + "title": "Resolvers", + "type": "object" + }, + "SchemaInline": { + "$ref": "#/definitions/PassThroughProp" + }, + "SchemaUri": { + "$ref": "#/definitions/PassThroughProp" + }, + "Tags": { + "title": "Tags", + "type": "object" + }, + "XrayEnabled": { + "title": "Xrayenabled", + "type": "boolean" + } + }, + "required": [ + "Auth" + ], + "title": "Properties", + "type": "object" + }, + "samtranslator__internal__schema_source__aws_serverless_graphqlapi__Resource": { + "additionalProperties": false, + "properties": { + "Properties": { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Properties" + }, + "Type": { + "enum": [ + "AWS::Serverless::GraphQLApi" + ], + "title": "Type", + "type": "string" + } + }, + "required": [ + "Type", + "Properties" + ], + "title": "Resource", + "type": "object" + }, "samtranslator__internal__schema_source__aws_serverless_httpapi__Auth": { "additionalProperties": false, "properties": { @@ -7706,6 +8274,9 @@ { "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_application__Resource" }, + { + "$ref": "#/definitions/samtranslator__internal__schema_source__aws_serverless_graphqlapi__Resource" + }, { "$ref": "#/definitions/samtranslator__internal__schema_source__any_cfn_resource__Resource" } diff --git a/tests/model/test_resource_validator.py b/tests/model/test_resource_validator.py index 580746833..6e5ada8e6 100644 --- a/tests/model/test_resource_validator.py +++ b/tests/model/test_resource_validator.py @@ -75,7 +75,7 @@ def test_connector_without_source(self): InvalidResourceException, ): invalid_connector.validate_properties_and_return_model(ConnectorProperties) - self.assertRegex(".+Given resource property 'Source'.+ is invalid.") + self.assertRegex(".+Property 'Source'.+ is invalid.") def test_connector_with_invalid_permission(self): invalid_connector = SamConnector("foo") @@ -86,7 +86,7 @@ def test_connector_with_invalid_permission(self): InvalidResourceException, ): invalid_connector.validate_properties_and_return_model(ConnectorProperties) - self.assertRegex(".+Given resource property 'Permissions'.+ is invalid.") + self.assertRegex(".+Property 'Permissions'.+ is invalid.") def test_connector_with_invalid_permission_type(self): invalid_connector = SamConnector("foo") @@ -97,4 +97,4 @@ def test_connector_with_invalid_permission_type(self): InvalidResourceException, ): invalid_connector.validate_properties_and_return_model(ConnectorProperties) - self.assertRegex(".+Given resource property 'Permissions'.+ is invalid.") + self.assertRegex(".+Property 'Permissions'.+ is invalid.") diff --git a/tests/model/test_sam_resources.py b/tests/model/test_sam_resources.py index 303adf66c..9aed256a2 100644 --- a/tests/model/test_sam_resources.py +++ b/tests/model/test_sam_resources.py @@ -13,6 +13,7 @@ SamApi, SamConnector, SamFunction, + SamGraphQLApi, SamHttpApi, SamLayerVersion, ) @@ -708,3 +709,9 @@ def test_unsupported_permissions_combination(self): "Unsupported 'Permissions' provided for connector from AWS::SQS::Queue to AWS::Lambda::Function; valid combinations are: Read \\+ Write.", ): connector.to_cloudformation(**self.kwargs)[0] + + +def test_function_datasource_set_with_none(): + api = SamGraphQLApi("MyApi") + none_datasource = api._construct_none_datasource("foo") + assert none_datasource diff --git a/tests/translator/input/error_graphqlapi.yaml b/tests/translator/input/error_graphqlapi.yaml new file mode 100644 index 000000000..e2fda6a38 --- /dev/null +++ b/tests/translator/input/error_graphqlapi.yaml @@ -0,0 +1,496 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + # ===== AppSync Function ===== + MyFunction: + Type: AWS::AppSync::FunctionConfiguration + Properties: + ApiId: some-api-id + Code: this is my epic code + DataSourceName: some-cool-datasource + Name: MyFunction + Runtime: + Name: some-runtime + RuntimeVersion: 1.2.3 + + # ===== SAM Error Resources ===== + NoAuthAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + XrayEnabled: true + Tags: + Key1: Value1 + Key2: Value2 + + NoSchemaPropertiesAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + + BothSchemaInlineAndUriAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + SchemaUri: https://bucket-name.s3.region-code.amazonaws.com/key-name + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + + GraphQLApiInvalidFieldInLogging: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Logging: + CloudWatchLogsRoleArn: some-arn + FieldLogLevel: ERROR + ExcludeVerboseContent: true + NotSupposedToBeHere: yo + + DataSourceNoServiceRoleArnOrTableArn: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + + IdDefinedWithOtherProperties: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + Functions: + IdNotMutuallyExclusive: + Id: some-id + DataSource: MyDataSource + + BothInlineCodeAndCodeUriDefined: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + Functions: + BothCodeProperties: + DataSource: MyDataSource + InlineCode: blahblahblah + CodeUri: MyCodeUri + Runtime: + Name: some-name + Version: 1.2.3 + + NoDataSource: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + Functions: + NoDataSourceProperties: + CodeUri: my-code + + UnknownDataSource: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + InternalDataSource: + TableName: SomeTable + ServiceRoleArn: SomeRoleArn + Functions: + UnknownDataSource: + CodeUri: my-code + DataSource: HardCodedDataSource + + NeitherInlineCodeNorCodeUriDefined: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + Functions: + BothCodeProperties: + DataSource: MyDataSource + + RuntimeNotDefined: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + Functions: + NoRuntime: + DataSource: MyDataSource + InlineCode: blahblahblah + + ResolverFunctionDoesNotExist: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + Functions: + MyFunction: + CodeUri: my-code-uri + DataSource: !ImportValue SomeDataSourceName + Runtime: + Name: some-runtime + Version: 1.2.3 + Resolvers: + Mutation: + ReferenceFunctionThatDoesNotExist: + InlineCode: blahblahblah + Runtime: + Name: some-runtime + Version: 1.2.3 + Pipeline: + - ThisFunctionDoesntExist + + ResolverWithNoFunctions: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Resolvers: + Mutation: + HasNoFunctions: + InlineCode: blahblahblah + FieldName: my_field + Runtime: + Name: some-runtime + Version: 1.2.3 + + ResolverBothCodePropertiesDefined: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Resolvers: + Mutation: + BothCodePropertiesDefined: + InlineCode: blahblahblah + CodeUri: somecodeuri + FieldName: my_field + Runtime: + Name: some-runtime + Version: 1.2.3 + Pipeline: + - MyFunction + Functions: + MyFunction: + DataSource: NONE + Runtime: + Name: some-runtime + Version: 1.2.3 + InlineCode: this is my epic code + + ResolverBothDatasourcePropertiesDefined: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Resolvers: + Mutation: + BothDatasourcePropertiesDefined: + FieldName: my_field + Runtime: + Name: some-runtime + Version: 1.2.3 + Pipeline: + - MyFunction + Functions: + MyFunction: + DataSource: NONE + Runtime: + Name: some-runtime + Version: 1.2.3 + InlineCode: this is my epic code + + ResolverWithNoRuntime: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Resolvers: + Mutation: + NoRuntimeForResolver: + FieldName: my_field + Pipeline: + - MyFunction + Functions: + MyFunction: + DataSource: NONE + Runtime: + Name: some-runtime + Version: 1.2.3 + InlineCode: this is my epic code + + MultipleAuthConfigs: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_LAMBDA + LambdaAuthorizer: + AuthorizerUri: blah + AuthorizerResultTtlInSeconds: 10 + IdentityValidationExpression: hello + OpenIDConnect: + AuthTTL: 10 + ClientId: myid + IatTTL: 10 + Issuer: prad + Tags: + key1: value1 + key2: value2 + + MultipleAdditionalAuthConfigs: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: API_KEY + Additional: + Type: AWS_LAMBDA + LambdaAuthorizer: + AuthorizerUri: blah + AuthorizerResultTtlInSeconds: 10 + IdentityValidationExpression: hello + OpenIDConnect: + AuthTTL: 10 + ClientId: myid + IatTTL: 10 + Issuer: prad + Tags: + key1: value1 + key2: value2 + + AuthTypeLambdaAuthorizerWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_LAMBDA + Tags: + key1: value1 + key2: value2 + + AdditionalAuthTypeLambdaAuthorizerWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: API_KEY + Additional: + Type: AWS_LAMBDA + Tags: + key1: value1 + key2: value2 + + AuthTypeOpenIDWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: OPENID_CONNECT + Tags: + key1: value1 + key2: value2 + + AdditionalAuthTypeOpenIDWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: API_KEY + Additional: + Type: OPENID_CONNECT + Tags: + key1: value1 + key2: value2 + + AuthTypeUserPoolWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AMAZON_COGNITO_USER_POOLS + Tags: + key1: value1 + key2: value2 + + AdditionalAuthUserPoolWithNoConfig: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: API_KEY + Additional: + Type: AMAZON_COGNITO_USER_POOLS + Tags: + key1: value1 + key2: value2 + + NotAnAuthType: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: PRAD_AUTH + Tags: + key1: value1 + key2: value2 diff --git a/tests/translator/input/graphqlapi_api_cache.yaml b/tests/translator/input/graphqlapi_api_cache.yaml new file mode 100644 index 000000000..47881da74 --- /dev/null +++ b/tests/translator/input/graphqlapi_api_cache.yaml @@ -0,0 +1,21 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Cache: + ApiCachingBehavior: somebehaviour + Type: mytype + Ttl: 60 + AtRestEncryptionEnabled: true + TransitEncryptionEnabled: false diff --git a/tests/translator/input/graphqlapi_api_keys.yaml b/tests/translator/input/graphqlapi_api_keys.yaml new file mode 100644 index 000000000..1b2b2d4bb --- /dev/null +++ b/tests/translator/input/graphqlapi_api_keys.yaml @@ -0,0 +1,22 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + ApiKeys: + MyApiKey: + Description: an api key + AnotherApiKey: + Description: another api key + ApiKeyId: some-id + ExpiresOn: 1234567890 diff --git a/tests/translator/input/graphqlapi_cognito_default_auth.yaml b/tests/translator/input/graphqlapi_cognito_default_auth.yaml new file mode 100644 index 000000000..7754ffa96 --- /dev/null +++ b/tests/translator/input/graphqlapi_cognito_default_auth.yaml @@ -0,0 +1,23 @@ +# This test exists so we can confirm that we are translating over the "DefaultAction" property over, since +# this is nullified when it is in the additional authentications. +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AMAZON_COGNITO_USER_POOLS + UserPool: + AppIdClientRegex: myregex + AwsRegion: na-east-1 + # This default action will exist post transform since this is our default authentication. + DefaultAction: something + UserPoolId: myid + Tags: + key1: value1 + key2: value2 diff --git a/tests/translator/input/graphqlapi_ddb_datasource_all_properties.yaml b/tests/translator/input/graphqlapi_ddb_datasource_all_properties.yaml new file mode 100644 index 000000000..8cb2cfdfa --- /dev/null +++ b/tests/translator/input/graphqlapi_ddb_datasource_all_properties.yaml @@ -0,0 +1,30 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + ServiceRoleArn: some-arn + Name: AwesomeDataSourceName + Description: This data source is special to me + Region: na-west-2 + UseCallerCredentials: true + Versioned: true + DeltaSync: + BaseTableTTL: '60' + DeltaSyncTableName: '60' + DeltaSyncTableTTL: '60' diff --git a/tests/translator/input/graphqlapi_ddb_datasource_connector.yaml b/tests/translator/input/graphqlapi_ddb_datasource_connector.yaml new file mode 100644 index 000000000..1f6567fc1 --- /dev/null +++ b/tests/translator/input/graphqlapi_ddb_datasource_connector.yaml @@ -0,0 +1,24 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + AnotherDataSource: + TableName: cool-table + TableArn: table-arn diff --git a/tests/translator/input/graphqlapi_default_logging.yaml b/tests/translator/input/graphqlapi_default_logging.yaml new file mode 100644 index 000000000..71b89c8de --- /dev/null +++ b/tests/translator/input/graphqlapi_default_logging.yaml @@ -0,0 +1,15 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 diff --git a/tests/translator/input/graphqlapi_defined_name.yaml b/tests/translator/input/graphqlapi_defined_name.yaml new file mode 100644 index 000000000..9ae3af995 --- /dev/null +++ b/tests/translator/input/graphqlapi_defined_name.yaml @@ -0,0 +1,9 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SuperDuperCoolAPI + Auth: + Type: AWS_IAM + SchemaUri: https://bucket-name.s3.region-code.amazonaws.com/key-name diff --git a/tests/translator/input/graphqlapi_domain_name.yaml b/tests/translator/input/graphqlapi_domain_name.yaml new file mode 100644 index 000000000..f1ab3f370 --- /dev/null +++ b/tests/translator/input/graphqlapi_domain_name.yaml @@ -0,0 +1,19 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DomainName: + CertificateArn: !Sub arn:${AWS::Partition}:acm:region:123456789012:certificate/certificate_ID + DomainName: prad.com + Description: cool domain diff --git a/tests/translator/input/graphqlapi_function_by_id.yaml b/tests/translator/input/graphqlapi_function_by_id.yaml new file mode 100644 index 000000000..6c45cc637 --- /dev/null +++ b/tests/translator/input/graphqlapi_function_by_id.yaml @@ -0,0 +1,26 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + Functions: + MyFunction: + Id: !GetAtt MyFunction.FunctionId + + MyFunction: + Type: AWS::AppSync::FunctionConfiguration + Properties: + ApiId: !GetAtt SuperCoolAPI.ApiId + Code: this is my epic code + DataSourceName: some-cool-datasource + Name: MyFunction + Runtime: + Name: some-runtime + RuntimeVersion: 1.2.3 diff --git a/tests/translator/input/graphqlapi_function_datasource_property.yaml b/tests/translator/input/graphqlapi_function_datasource_property.yaml new file mode 100644 index 000000000..b1c50285d --- /dev/null +++ b/tests/translator/input/graphqlapi_function_datasource_property.yaml @@ -0,0 +1,57 @@ +Transform: AWS::Serverless-2016-10-31 + +Parameters: + HarcodedDataSourceName: + Type: String + Description: Harcoded Data Source name + +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + DataSources: + DynamoDb: + InternalDataSource: + TableName: SomeTable + ServiceRoleArn: SomeRoleArn + Functions: + UseInternal: + InlineCode: this is my epic code + DataSource: InternalDataSource + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + UseAppSync: + InlineCode: this is my epic code + DataSource: !GetAtt AppSyncHttpDataSource.Name + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + UseHardcoded: + CodeUri: my-code-uri + DataSource: !Sub '${HarcodedDataSourceName}' + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + UseImported: + CodeUri: my-code-uri + DataSource: !ImportValue SomeSharedDataSourceName + Runtime: + Name: APPSYNC_JS + Version: 1.0.0 + + AppSyncHttpDataSource: + Type: AWS::AppSync::DataSource + Properties: + ApiId: !GetAtt SuperCoolAPI.ApiId + Name: AppSyncHttpDataSource + Type: HTTP + HttpConfig: + Endpoint: https://test-generator.ai diff --git a/tests/translator/input/graphqlapi_lambda_and_ddb_datasource.yaml b/tests/translator/input/graphqlapi_lambda_and_ddb_datasource.yaml new file mode 100644 index 000000000..8aca479ea --- /dev/null +++ b/tests/translator/input/graphqlapi_lambda_and_ddb_datasource.yaml @@ -0,0 +1,26 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + Lambda: + MyDataSource: + FunctionArn: blah + ServiceRoleArn: my-lambda-role + DynamoDb: + MyDataSource: + TableName: some-table + TableArn: big-arn + ServiceRoleArn: my-ddb-role diff --git a/tests/translator/input/graphqlapi_lambda_datasource_connector.yaml b/tests/translator/input/graphqlapi_lambda_datasource_connector.yaml new file mode 100644 index 000000000..0493731a2 --- /dev/null +++ b/tests/translator/input/graphqlapi_lambda_datasource_connector.yaml @@ -0,0 +1,20 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + Lambda: + MyDataSource: + FunctionArn: blah diff --git a/tests/translator/input/graphqlapi_logging_defined.yaml b/tests/translator/input/graphqlapi_logging_defined.yaml new file mode 100644 index 000000000..37a3b014e --- /dev/null +++ b/tests/translator/input/graphqlapi_logging_defined.yaml @@ -0,0 +1,19 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Logging: + CloudWatchLogsRoleArn: some-arn + FieldLogLevel: ERROR + ExcludeVerboseContent: true diff --git a/tests/translator/input/graphqlapi_logging_true.yaml b/tests/translator/input/graphqlapi_logging_true.yaml new file mode 100644 index 000000000..557e74a87 --- /dev/null +++ b/tests/translator/input/graphqlapi_logging_true.yaml @@ -0,0 +1,17 @@ +# This is not an expected user use case (they should just not define Logging if they want defaults), but still testing. +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Logging: true diff --git a/tests/translator/input/graphqlapi_multiple_auth.yaml b/tests/translator/input/graphqlapi_multiple_auth.yaml new file mode 100644 index 000000000..69bee9ac9 --- /dev/null +++ b/tests/translator/input/graphqlapi_multiple_auth.yaml @@ -0,0 +1,66 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_LAMBDA + LambdaAuthorizer: + AuthorizerUri: !GetAtt Authorizer1.Arn + AuthorizerResultTtlInSeconds: 10 + IdentityValidationExpression: hello + Additional: + - Type: AWS_IAM + - Type: API_KEY + - Type: AWS_LAMBDA + LambdaAuthorizer: + AuthorizerUri: !GetAtt Authorizer2.Arn + - Type: OPENID_CONNECT + OpenIDConnect: + AuthTTL: 10 + ClientId: myid + IatTTL: 10 + Issuer: prad + - Type: AMAZON_COGNITO_USER_POOLS + UserPool: + AppIdClientRegex: myregex + AwsRegion: na-east-1 + # This default action will be discarded since it is in the additional authentications. + DefaultAction: something + UserPoolId: myid + Tags: + key1: value1 + key2: value2 + + Authorizer1: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return { + isAuthorized: true, + deniedFields: [], + } + } + PackageType: Zip + Runtime: nodejs14.x + Handler: index.handler + + Authorizer2: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return { + isAuthorized: true, + deniedFields: [], + } + } + PackageType: Zip + Runtime: nodejs14.x + Handler: index.handler diff --git a/tests/translator/input/graphqlapi_multiple_none_datasource_functions.yaml b/tests/translator/input/graphqlapi_multiple_none_datasource_functions.yaml new file mode 100644 index 000000000..f71751ecc --- /dev/null +++ b/tests/translator/input/graphqlapi_multiple_none_datasource_functions.yaml @@ -0,0 +1,37 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + Auth: + Type: AWS_IAM + Functions: + MyFunction: + CodeUri: my-code-uri + DataSource: NONE + Runtime: + Name: some-runtime + Version: 1.2.3 + AnotherFunction: + CodeUri: my-code-uri + DataSource: None + Runtime: + Name: some-runtime + Version: 1.2.3 + SimilarFunction: + CodeUri: my-code-uri + DataSource: none + Runtime: + Name: some-runtime + Version: 1.2.3 + GoodFunction: + CodeUri: my-code-uri + DataSource: nOnE + Runtime: + Name: some-runtime + Version: 1.2.3 diff --git a/tests/translator/input/graphqlapi_no_logging.yaml b/tests/translator/input/graphqlapi_no_logging.yaml new file mode 100644 index 000000000..969d079f9 --- /dev/null +++ b/tests/translator/input/graphqlapi_no_logging.yaml @@ -0,0 +1,16 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + Logging: false diff --git a/tests/translator/input/graphqlapi_no_name.yaml b/tests/translator/input/graphqlapi_no_name.yaml new file mode 100644 index 000000000..71b89c8de --- /dev/null +++ b/tests/translator/input/graphqlapi_no_name.yaml @@ -0,0 +1,15 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 diff --git a/tests/translator/input/graphqlapi_resolver_function_with_lambda_datasource.yaml b/tests/translator/input/graphqlapi_resolver_function_with_lambda_datasource.yaml new file mode 100644 index 000000000..e5391f797 --- /dev/null +++ b/tests/translator/input/graphqlapi_resolver_function_with_lambda_datasource.yaml @@ -0,0 +1,46 @@ +Transform: AWS::Serverless-2016-10-31 +Resources: + SuperCoolAPI: + Type: AWS::Serverless::GraphQLApi + Properties: + Name: SomeApi + SchemaInline: | + type Mutation { + addTodo(id: ID!, name: String, description: String, priority: Int): Todo + } + XrayEnabled: true + Auth: + Type: AWS_IAM + Tags: + key1: value1 + key2: value2 + DataSources: + Lambda: + MyDataSource: + FunctionArn: my-lambda-arn + ServiceRoleArn: some-role-arn + Name: PradsLambdaDataSource + Description: lambda datasources are nice + Resolvers: + Mutation: + myResolver: + FieldName: my_field + MaxBatchSize: 10 + Runtime: + Name: some-runtime + Version: 1.2.3 + Caching: + Ttl: 20 + CachingKeys: + - key1 + - key2 + Pipeline: + - MyFunction + Functions: + MyFunction: + Runtime: + Name: some-runtime + Version: 1.2.3 + InlineCode: this is my epic code + DataSource: MyDataSource + MaxBatchSize: 10 diff --git a/tests/translator/output/aws-cn/graphqlapi_api_cache.json b/tests/translator/output/aws-cn/graphqlapi_api_cache.json new file mode 100644 index 000000000..2da790fbd --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_api_cache.json @@ -0,0 +1,85 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIApiCache": { + "Properties": { + "ApiCachingBehavior": "somebehaviour", + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "AtRestEncryptionEnabled": true, + "TransitEncryptionEnabled": false, + "Ttl": 60, + "Type": "mytype" + }, + "Type": "AWS::AppSync::ApiCache" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_api_keys.json b/tests/translator/output/aws-cn/graphqlapi_api_keys.json new file mode 100644 index 000000000..c053b991c --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_api_keys.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "ApiKeyId": "some-id", + "Description": "another api key", + "Expires": 1234567890 + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "an api key" + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_cognito_default_auth.json b/tests/translator/output/aws-cn/graphqlapi_cognito_default_auth.json new file mode 100644 index 000000000..1bb290535 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_cognito_default_auth.json @@ -0,0 +1,75 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "DefaultAction": "something", + "UserPoolId": "myid" + }, + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_all_properties.json b/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_all_properties.json new file mode 100644 index 000000000..b91187e0b --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_all_properties.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "This data source is special to me", + "DynamoDBConfig": { + "AwsRegion": "na-west-2", + "DeltaSyncConfig": { + "BaseTableTTL": "60", + "DeltaSyncTableName": "60", + "DeltaSyncTableTTL": "60" + }, + "TableName": "some-table", + "UseCallerCredentials": true, + "Versioned": true + }, + "Name": "AwesomeDataSourceName", + "ServiceRoleArn": "some-arn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_connector.json b/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_connector.json new file mode 100644 index 000000000..5cb741624 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_ddb_datasource_connector.json @@ -0,0 +1,305 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "cool-table" + }, + "Name": "AnotherDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_default_logging.json b/tests/translator/output/aws-cn/graphqlapi_default_logging.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_default_logging.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_defined_name.json b/tests/translator/output/aws-cn/graphqlapi_defined_name.json new file mode 100644 index 000000000..39d19fba4 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_defined_name.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperDuperCoolAPI" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DefinitionS3Location": "https://bucket-name.s3.region-code.amazonaws.com/key-name" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_domain_name.json b/tests/translator/output/aws-cn/graphqlapi_domain_name.json new file mode 100644 index 000000000..f4f47bcef --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_domain_name.json @@ -0,0 +1,93 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIDomainName": { + "Properties": { + "CertificateArn": { + "Fn::Sub": "arn:${AWS::Partition}:acm:region:123456789012:certificate/certificate_ID" + }, + "Description": "cool domain", + "DomainName": "prad.com" + }, + "Type": "AWS::AppSync::DomainName" + }, + "SuperCoolAPIDomainNameApiAssociation": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DomainName": { + "Ref": "SuperCoolAPIDomainName" + } + }, + "Type": "AWS::AppSync::DomainNameApiAssociation" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_function_by_id.json b/tests/translator/output/aws-cn/graphqlapi_function_by_id.json new file mode 100644 index 000000000..d26ec3c08 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_function_by_id.json @@ -0,0 +1,76 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": "some-cool-datasource", + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_function_datasource_property.json b/tests/translator/output/aws-cn/graphqlapi_function_datasource_property.json new file mode 100644 index 000000000..6e6b21929 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_function_datasource_property.json @@ -0,0 +1,186 @@ +{ + "Parameters": { + "HarcodedDataSourceName": { + "Description": "Harcoded Data Source name", + "Type": "String" + } + }, + "Resources": { + "AppSyncHttpDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "HttpConfig": { + "Endpoint": "https://test-generator.ai" + }, + "Name": "AppSyncHttpDataSource", + "Type": "HTTP" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIInternalDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "SomeTable" + }, + "Name": "InternalDataSource", + "ServiceRoleArn": "SomeRoleArn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIUseAppSync": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "AppSyncHttpDataSource", + "Name" + ] + }, + "Name": "UseAppSync", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseHardcoded": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::Sub": "${HarcodedDataSourceName}" + }, + "Name": "UseHardcoded", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseImported": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::ImportValue": "SomeSharedDataSourceName" + }, + "Name": "UseImported", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseInternal": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIInternalDataSourceDynamoDBDataSource", + "Name" + ] + }, + "Name": "UseInternal", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_lambda_and_ddb_datasource.json b/tests/translator/output/aws-cn/graphqlapi_lambda_and_ddb_datasource.json new file mode 100644 index 000000000..b44fe7df7 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_lambda_and_ddb_datasource.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-ddb-role", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-lambda-role", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_lambda_datasource_connector.json b/tests/translator/output/aws-cn/graphqlapi_lambda_datasource_connector.json new file mode 100644 index 000000000..07656725e --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_lambda_datasource_connector.json @@ -0,0 +1,157 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSourceRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + "blah", + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": "blah" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceLambdaDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_logging_defined.json b/tests/translator/output/aws-cn/graphqlapi_logging_defined.json new file mode 100644 index 000000000..8fc5815f5 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_logging_defined.json @@ -0,0 +1,39 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": "some-arn", + "ExcludeVerboseContent": true, + "FieldLogLevel": "ERROR" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_logging_true.json b/tests/translator/output/aws-cn/graphqlapi_logging_true.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_logging_true.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_multiple_auth.json b/tests/translator/output/aws-cn/graphqlapi_multiple_auth.json new file mode 100644 index 000000000..0d1dc6992 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_multiple_auth.json @@ -0,0 +1,297 @@ +{ + "Resources": { + "Authorizer1": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer1Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Authorizer2": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer2Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPI": { + "Properties": { + "AdditionalAuthenticationProviders": [ + { + "AuthenticationType": "AWS_IAM" + }, + { + "AuthenticationType": "API_KEY" + }, + { + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + } + } + }, + { + "AuthenticationType": "OPENID_CONNECT", + "OpenIDConnectConfig": { + "AuthTTL": 10, + "ClientId": "myid", + "IatTTL": 10, + "Issuer": "prad" + } + }, + { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "UserPoolId": "myid" + } + } + ], + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerResultTtlInSeconds": 10, + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "IdentityValidationExpression": "hello" + }, + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIToLambdaAuthConnector1WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector1": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, + "SuperCoolAPIToLambdaAuthConnector2WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector2": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_multiple_none_datasource_functions.json b/tests/translator/output/aws-cn/graphqlapi_multiple_none_datasource_functions.json new file mode 100644 index 000000000..be21f85df --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_multiple_none_datasource_functions.json @@ -0,0 +1,163 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "AnotherFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIGoodFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "GoodFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPINoneDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Name": "SuperCoolAPINoneDataSource", + "Type": "NONE" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPISimilarFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "SimilarFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_no_logging.json b/tests/translator/output/aws-cn/graphqlapi_no_logging.json new file mode 100644 index 000000000..3b22de27d --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_no_logging.json @@ -0,0 +1,34 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_no_name.json b/tests/translator/output/aws-cn/graphqlapi_no_name.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_no_name.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-cn/graphqlapi_resolver_function_with_lambda_datasource.json b/tests/translator/output/aws-cn/graphqlapi_resolver_function_with_lambda_datasource.json new file mode 100644 index 000000000..614275f6b --- /dev/null +++ b/tests/translator/output/aws-cn/graphqlapi_resolver_function_with_lambda_datasource.json @@ -0,0 +1,151 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMutationmyResolver": { + "DependsOn": [ + "SuperCoolAPISchema" + ], + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CachingConfig": { + "CachingKeys": [ + "key1", + "key2" + ], + "Ttl": 20 + }, + "Code": "\nexport function request(ctx) {\n return {};\n}\n\nexport function response(ctx) {\n return ctx.prev.result;\n}\n", + "FieldName": "my_field", + "Kind": "PIPELINE", + "MaxBatchSize": 10, + "PipelineConfig": { + "Functions": [ + { + "Fn::GetAtt": [ + "SuperCoolAPIMyFunction", + "FunctionId" + ] + } + ] + }, + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + }, + "TypeName": "Mutation" + }, + "Type": "AWS::AppSync::Resolver" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "lambda datasources are nice", + "LambdaConfig": { + "LambdaFunctionArn": "my-lambda-arn" + }, + "Name": "PradsLambdaDataSource", + "ServiceRoleArn": "some-role-arn", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSource", + "Name" + ] + }, + "MaxBatchSize": 10, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_api_cache.json b/tests/translator/output/aws-us-gov/graphqlapi_api_cache.json new file mode 100644 index 000000000..2da790fbd --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_api_cache.json @@ -0,0 +1,85 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIApiCache": { + "Properties": { + "ApiCachingBehavior": "somebehaviour", + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "AtRestEncryptionEnabled": true, + "TransitEncryptionEnabled": false, + "Ttl": 60, + "Type": "mytype" + }, + "Type": "AWS::AppSync::ApiCache" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_api_keys.json b/tests/translator/output/aws-us-gov/graphqlapi_api_keys.json new file mode 100644 index 000000000..c053b991c --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_api_keys.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "ApiKeyId": "some-id", + "Description": "another api key", + "Expires": 1234567890 + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "an api key" + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_cognito_default_auth.json b/tests/translator/output/aws-us-gov/graphqlapi_cognito_default_auth.json new file mode 100644 index 000000000..1bb290535 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_cognito_default_auth.json @@ -0,0 +1,75 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "DefaultAction": "something", + "UserPoolId": "myid" + }, + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_all_properties.json b/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_all_properties.json new file mode 100644 index 000000000..b91187e0b --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_all_properties.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "This data source is special to me", + "DynamoDBConfig": { + "AwsRegion": "na-west-2", + "DeltaSyncConfig": { + "BaseTableTTL": "60", + "DeltaSyncTableName": "60", + "DeltaSyncTableTTL": "60" + }, + "TableName": "some-table", + "UseCallerCredentials": true, + "Versioned": true + }, + "Name": "AwesomeDataSourceName", + "ServiceRoleArn": "some-arn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_connector.json b/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_connector.json new file mode 100644 index 000000000..5cb741624 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_ddb_datasource_connector.json @@ -0,0 +1,305 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "cool-table" + }, + "Name": "AnotherDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_default_logging.json b/tests/translator/output/aws-us-gov/graphqlapi_default_logging.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_default_logging.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_defined_name.json b/tests/translator/output/aws-us-gov/graphqlapi_defined_name.json new file mode 100644 index 000000000..39d19fba4 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_defined_name.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperDuperCoolAPI" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DefinitionS3Location": "https://bucket-name.s3.region-code.amazonaws.com/key-name" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_domain_name.json b/tests/translator/output/aws-us-gov/graphqlapi_domain_name.json new file mode 100644 index 000000000..f4f47bcef --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_domain_name.json @@ -0,0 +1,93 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIDomainName": { + "Properties": { + "CertificateArn": { + "Fn::Sub": "arn:${AWS::Partition}:acm:region:123456789012:certificate/certificate_ID" + }, + "Description": "cool domain", + "DomainName": "prad.com" + }, + "Type": "AWS::AppSync::DomainName" + }, + "SuperCoolAPIDomainNameApiAssociation": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DomainName": { + "Ref": "SuperCoolAPIDomainName" + } + }, + "Type": "AWS::AppSync::DomainNameApiAssociation" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_function_by_id.json b/tests/translator/output/aws-us-gov/graphqlapi_function_by_id.json new file mode 100644 index 000000000..d26ec3c08 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_function_by_id.json @@ -0,0 +1,76 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": "some-cool-datasource", + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_function_datasource_property.json b/tests/translator/output/aws-us-gov/graphqlapi_function_datasource_property.json new file mode 100644 index 000000000..6e6b21929 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_function_datasource_property.json @@ -0,0 +1,186 @@ +{ + "Parameters": { + "HarcodedDataSourceName": { + "Description": "Harcoded Data Source name", + "Type": "String" + } + }, + "Resources": { + "AppSyncHttpDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "HttpConfig": { + "Endpoint": "https://test-generator.ai" + }, + "Name": "AppSyncHttpDataSource", + "Type": "HTTP" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIInternalDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "SomeTable" + }, + "Name": "InternalDataSource", + "ServiceRoleArn": "SomeRoleArn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIUseAppSync": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "AppSyncHttpDataSource", + "Name" + ] + }, + "Name": "UseAppSync", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseHardcoded": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::Sub": "${HarcodedDataSourceName}" + }, + "Name": "UseHardcoded", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseImported": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::ImportValue": "SomeSharedDataSourceName" + }, + "Name": "UseImported", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseInternal": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIInternalDataSourceDynamoDBDataSource", + "Name" + ] + }, + "Name": "UseInternal", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_lambda_and_ddb_datasource.json b/tests/translator/output/aws-us-gov/graphqlapi_lambda_and_ddb_datasource.json new file mode 100644 index 000000000..b44fe7df7 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_lambda_and_ddb_datasource.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-ddb-role", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-lambda-role", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_lambda_datasource_connector.json b/tests/translator/output/aws-us-gov/graphqlapi_lambda_datasource_connector.json new file mode 100644 index 000000000..07656725e --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_lambda_datasource_connector.json @@ -0,0 +1,157 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSourceRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + "blah", + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": "blah" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceLambdaDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_logging_defined.json b/tests/translator/output/aws-us-gov/graphqlapi_logging_defined.json new file mode 100644 index 000000000..8fc5815f5 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_logging_defined.json @@ -0,0 +1,39 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": "some-arn", + "ExcludeVerboseContent": true, + "FieldLogLevel": "ERROR" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_logging_true.json b/tests/translator/output/aws-us-gov/graphqlapi_logging_true.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_logging_true.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_multiple_auth.json b/tests/translator/output/aws-us-gov/graphqlapi_multiple_auth.json new file mode 100644 index 000000000..2354d6884 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_multiple_auth.json @@ -0,0 +1,297 @@ +{ + "Resources": { + "Authorizer1": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer1Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Authorizer2": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer2Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPI": { + "Properties": { + "AdditionalAuthenticationProviders": [ + { + "AuthenticationType": "AWS_IAM" + }, + { + "AuthenticationType": "API_KEY" + }, + { + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + } + } + }, + { + "AuthenticationType": "OPENID_CONNECT", + "OpenIDConnectConfig": { + "AuthTTL": 10, + "ClientId": "myid", + "IatTTL": 10, + "Issuer": "prad" + } + }, + { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "UserPoolId": "myid" + } + } + ], + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerResultTtlInSeconds": 10, + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "IdentityValidationExpression": "hello" + }, + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIToLambdaAuthConnector1WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector1": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, + "SuperCoolAPIToLambdaAuthConnector2WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector2": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_multiple_none_datasource_functions.json b/tests/translator/output/aws-us-gov/graphqlapi_multiple_none_datasource_functions.json new file mode 100644 index 000000000..be21f85df --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_multiple_none_datasource_functions.json @@ -0,0 +1,163 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "AnotherFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIGoodFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "GoodFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPINoneDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Name": "SuperCoolAPINoneDataSource", + "Type": "NONE" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPISimilarFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "SimilarFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_no_logging.json b/tests/translator/output/aws-us-gov/graphqlapi_no_logging.json new file mode 100644 index 000000000..3b22de27d --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_no_logging.json @@ -0,0 +1,34 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_no_name.json b/tests/translator/output/aws-us-gov/graphqlapi_no_name.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_no_name.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/aws-us-gov/graphqlapi_resolver_function_with_lambda_datasource.json b/tests/translator/output/aws-us-gov/graphqlapi_resolver_function_with_lambda_datasource.json new file mode 100644 index 000000000..614275f6b --- /dev/null +++ b/tests/translator/output/aws-us-gov/graphqlapi_resolver_function_with_lambda_datasource.json @@ -0,0 +1,151 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMutationmyResolver": { + "DependsOn": [ + "SuperCoolAPISchema" + ], + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CachingConfig": { + "CachingKeys": [ + "key1", + "key2" + ], + "Ttl": 20 + }, + "Code": "\nexport function request(ctx) {\n return {};\n}\n\nexport function response(ctx) {\n return ctx.prev.result;\n}\n", + "FieldName": "my_field", + "Kind": "PIPELINE", + "MaxBatchSize": 10, + "PipelineConfig": { + "Functions": [ + { + "Fn::GetAtt": [ + "SuperCoolAPIMyFunction", + "FunctionId" + ] + } + ] + }, + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + }, + "TypeName": "Mutation" + }, + "Type": "AWS::AppSync::Resolver" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "lambda datasources are nice", + "LambdaConfig": { + "LambdaFunctionArn": "my-lambda-arn" + }, + "Name": "PradsLambdaDataSource", + "ServiceRoleArn": "some-role-arn", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSource", + "Name" + ] + }, + "MaxBatchSize": 10, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/error_graphqlapi.json b/tests/translator/output/error_graphqlapi.json new file mode 100644 index 000000000..de6372d2d --- /dev/null +++ b/tests/translator/output/error_graphqlapi.json @@ -0,0 +1,57 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 24. ", + "Resource with id [AdditionalAuthTypeLambdaAuthorizerWithNoConfig] is invalid. ", + "Property 'Auth.Additional' is invalid. ", + "Resource with id [AdditionalAuthTypeOpenIDWithNoConfig] is invalid. ", + "Property 'Auth.Additional' is invalid. ", + "Resource with id [AdditionalAuthUserPoolWithNoConfig] is invalid. ", + "Property 'Auth.Additional' is invalid. ", + "Resource with id [AuthTypeLambdaAuthorizerWithNoConfig] is invalid. ", + "'LambdaAuthorizer' must be defined if type is 'AWS_LAMBDA'. ", + "Resource with id [AuthTypeOpenIDWithNoConfig] is invalid. ", + "'OpenIDConnect' must be defined if type is 'OPENID_CONNECT'. ", + "Resource with id [AuthTypeUserPoolWithNoConfig] is invalid. ", + "'UserPool' must be defined if type is 'AMAZON_COGNITO_USER_POOLS'. ", + "Resource with id [BothCodeProperties] is invalid. ", + "Both 'InlineCode' and 'CodeUri' cannot be defined at the same time. ", + "Resource with id [BothCodeProperties] is invalid. ", + "One of 'InlineCode' or 'CodeUri' must be set. ", + "Resource with id [BothCodePropertiesDefined] is invalid. ", + "Both 'InlineCode' and 'CodeUri' cannot be defined at the same time. ", + "Resource with id [BothSchemaInlineAndUriAPI] is invalid. ", + "Both 'SchemaInline' and 'SchemaUri' cannot be defined at the same time. ", + "Resource with id [GraphQLApiInvalidFieldInLogging] is invalid. ", + "Property 'Logging.NotSupposedToBeHere' is invalid. ", + "Resource with id [HasNoFunctions] is invalid. ", + "Resolver 'HasNoFunctions' must have Pipeline defined. ", + "Unit resolvers are not supported. ", + "If you need a Unit resolver you can use AppSync resource. ", + "Resource with id [IdNotMutuallyExclusive] is invalid. ", + "'Id' cannot be defined with other properties in Function. ", + "Resource with id [MultipleAdditionalAuthConfigs] is invalid. ", + "Property 'Auth.Additional' is invalid. ", + "Resource with id [MultipleAuthConfigs] is invalid. ", + "'Auth' has more than one authentication configuration defined. ", + "Resource with id [MyDataSource] is invalid. ", + "'TableArn' must be defined to create the role and policy if 'ServiceRoleArn' is not defined. ", + "Resource with id [NoAuthAPI] is invalid. ", + "Missing required property 'Auth'. ", + "Resource with id [NoDataSourceProperties] is invalid. ", + "'DataSource' must be set. ", + "Resource with id [NoRuntime] is invalid. ", + "'Runtime' must be defined as a property in NoRuntime. ", + "Resource with id [NoRuntimeForResolver] is invalid. ", + "'Runtime' must be defined as a property in NoRuntimeForResolver. ", + "Resource with id [NoSchemaPropertiesAPI] is invalid. ", + "One of 'SchemaInline' or 'SchemaUri' must be set. ", + "Resource with id [NotAnAuthType] is invalid. ", + "Property 'Auth.Type' is invalid. ", + "Resource with id [ReferenceFunctionThatDoesNotExist] is invalid. ", + "Function 'ThisFunctionDoesntExist' does not exist. ", + "Resource with id [UnknownDataSource] is invalid. ", + "Either define DataSource 'HardCodedDataSource' in 'DataSources' or use intrinsic function like GetAtt, ImportValue, Sub or another one to reference a DataSource defined outside of this GraphQLApi resource." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 24. Resource with id [AdditionalAuthTypeLambdaAuthorizerWithNoConfig] is invalid. Property 'Auth.Additional' is invalid. Resource with id [AdditionalAuthTypeOpenIDWithNoConfig] is invalid. Property 'Auth.Additional' is invalid. Resource with id [AdditionalAuthUserPoolWithNoConfig] is invalid. Property 'Auth.Additional' is invalid. Resource with id [AuthTypeLambdaAuthorizerWithNoConfig] is invalid. 'LambdaAuthorizer' must be defined if type is 'AWS_LAMBDA'. Resource with id [AuthTypeOpenIDWithNoConfig] is invalid. 'OpenIDConnect' must be defined if type is 'OPENID_CONNECT'. Resource with id [AuthTypeUserPoolWithNoConfig] is invalid. 'UserPool' must be defined if type is 'AMAZON_COGNITO_USER_POOLS'. Resource with id [BothCodeProperties] is invalid. Both 'InlineCode' and 'CodeUri' cannot be defined at the same time. Resource with id [BothCodeProperties] is invalid. One of 'InlineCode' or 'CodeUri' must be set. Resource with id [BothCodePropertiesDefined] is invalid. Both 'InlineCode' and 'CodeUri' cannot be defined at the same time. Resource with id [BothSchemaInlineAndUriAPI] is invalid. Both 'SchemaInline' and 'SchemaUri' cannot be defined at the same time. Resource with id [GraphQLApiInvalidFieldInLogging] is invalid. Property 'Logging.NotSupposedToBeHere' is invalid. Resource with id [HasNoFunctions] is invalid. Resolver 'HasNoFunctions' must have Pipeline defined. Unit resolvers are not supported. If you need a Unit resolver you can use AppSync resource. Resource with id [IdNotMutuallyExclusive] is invalid. 'Id' cannot be defined with other properties in Function. Resource with id [MultipleAdditionalAuthConfigs] is invalid. Property 'Auth.Additional' is invalid. Resource with id [MultipleAuthConfigs] is invalid. 'Auth' has more than one authentication configuration defined. Resource with id [MyDataSource] is invalid. 'TableArn' must be defined to create the role and policy if 'ServiceRoleArn' is not defined. Resource with id [NoAuthAPI] is invalid. Missing required property 'Auth'. Resource with id [NoDataSourceProperties] is invalid. 'DataSource' must be set. Resource with id [NoRuntime] is invalid. 'Runtime' must be defined as a property in NoRuntime. Resource with id [NoRuntimeForResolver] is invalid. 'Runtime' must be defined as a property in NoRuntimeForResolver. Resource with id [NoSchemaPropertiesAPI] is invalid. One of 'SchemaInline' or 'SchemaUri' must be set. Resource with id [NotAnAuthType] is invalid. Property 'Auth.Type' is invalid. Resource with id [ReferenceFunctionThatDoesNotExist] is invalid. Function 'ThisFunctionDoesntExist' does not exist. Resource with id [UnknownDataSource] is invalid. Either define DataSource 'HardCodedDataSource' in 'DataSources' or use intrinsic function like GetAtt, ImportValue, Sub or another one to reference a DataSource defined outside of this GraphQLApi resource." +} diff --git a/tests/translator/output/graphqlapi_api_cache.json b/tests/translator/output/graphqlapi_api_cache.json new file mode 100644 index 000000000..2da790fbd --- /dev/null +++ b/tests/translator/output/graphqlapi_api_cache.json @@ -0,0 +1,85 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIApiCache": { + "Properties": { + "ApiCachingBehavior": "somebehaviour", + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "AtRestEncryptionEnabled": true, + "TransitEncryptionEnabled": false, + "Ttl": 60, + "Type": "mytype" + }, + "Type": "AWS::AppSync::ApiCache" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_api_keys.json b/tests/translator/output/graphqlapi_api_keys.json new file mode 100644 index 000000000..c053b991c --- /dev/null +++ b/tests/translator/output/graphqlapi_api_keys.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "ApiKeyId": "some-id", + "Description": "another api key", + "Expires": 1234567890 + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyApiKey": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "an api key" + }, + "Type": "AWS::AppSync::ApiKey" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_cognito_default_auth.json b/tests/translator/output/graphqlapi_cognito_default_auth.json new file mode 100644 index 000000000..1bb290535 --- /dev/null +++ b/tests/translator/output/graphqlapi_cognito_default_auth.json @@ -0,0 +1,75 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "DefaultAction": "something", + "UserPoolId": "myid" + }, + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_ddb_datasource_all_properties.json b/tests/translator/output/graphqlapi_ddb_datasource_all_properties.json new file mode 100644 index 000000000..b91187e0b --- /dev/null +++ b/tests/translator/output/graphqlapi_ddb_datasource_all_properties.json @@ -0,0 +1,95 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "This data source is special to me", + "DynamoDBConfig": { + "AwsRegion": "na-west-2", + "DeltaSyncConfig": { + "BaseTableTTL": "60", + "DeltaSyncTableName": "60", + "DeltaSyncTableTTL": "60" + }, + "TableName": "some-table", + "UseCallerCredentials": true, + "Versioned": true + }, + "Name": "AwesomeDataSourceName", + "ServiceRoleArn": "some-arn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_ddb_datasource_connector.json b/tests/translator/output/graphqlapi_ddb_datasource_connector.json new file mode 100644 index 000000000..5cb741624 --- /dev/null +++ b/tests/translator/output/graphqlapi_ddb_datasource_connector.json @@ -0,0 +1,305 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "cool-table" + }, + "Name": "AnotherDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "table-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "table-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIAnotherDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole", + "Arn" + ] + }, + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceDynamoDBDataSourceToTableConnector": { + "Destination": { + "Type": "AWS::DynamoDB::Table" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:BatchGetItem", + "dynamodb:ConditionCheckItem", + "dynamodb:PartiQLSelect" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + }, + { + "Action": [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:PartiQLDelete", + "dynamodb:PartiQLInsert", + "dynamodb:PartiQLUpdate" + ], + "Effect": "Allow", + "Resource": [ + "big-arn", + { + "Fn::Sub": [ + "${DestinationArn}/index/*", + { + "DestinationArn": "big-arn" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceDynamoDBDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_default_logging.json b/tests/translator/output/graphqlapi_default_logging.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/graphqlapi_default_logging.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_defined_name.json b/tests/translator/output/graphqlapi_defined_name.json new file mode 100644 index 000000000..39d19fba4 --- /dev/null +++ b/tests/translator/output/graphqlapi_defined_name.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperDuperCoolAPI" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DefinitionS3Location": "https://bucket-name.s3.region-code.amazonaws.com/key-name" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_domain_name.json b/tests/translator/output/graphqlapi_domain_name.json new file mode 100644 index 000000000..f4f47bcef --- /dev/null +++ b/tests/translator/output/graphqlapi_domain_name.json @@ -0,0 +1,93 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIDomainName": { + "Properties": { + "CertificateArn": { + "Fn::Sub": "arn:${AWS::Partition}:acm:region:123456789012:certificate/certificate_ID" + }, + "Description": "cool domain", + "DomainName": "prad.com" + }, + "Type": "AWS::AppSync::DomainName" + }, + "SuperCoolAPIDomainNameApiAssociation": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DomainName": { + "Ref": "SuperCoolAPIDomainName" + } + }, + "Type": "AWS::AppSync::DomainNameApiAssociation" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_function_by_id.json b/tests/translator/output/graphqlapi_function_by_id.json new file mode 100644 index 000000000..d26ec3c08 --- /dev/null +++ b/tests/translator/output/graphqlapi_function_by_id.json @@ -0,0 +1,76 @@ +{ + "Resources": { + "MyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": "some-cool-datasource", + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_function_datasource_property.json b/tests/translator/output/graphqlapi_function_datasource_property.json new file mode 100644 index 000000000..6e6b21929 --- /dev/null +++ b/tests/translator/output/graphqlapi_function_datasource_property.json @@ -0,0 +1,186 @@ +{ + "Parameters": { + "HarcodedDataSourceName": { + "Description": "Harcoded Data Source name", + "Type": "String" + } + }, + "Resources": { + "AppSyncHttpDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "HttpConfig": { + "Endpoint": "https://test-generator.ai" + }, + "Name": "AppSyncHttpDataSource", + "Type": "HTTP" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIInternalDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "SomeTable" + }, + "Name": "InternalDataSource", + "ServiceRoleArn": "SomeRoleArn", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIUseAppSync": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "AppSyncHttpDataSource", + "Name" + ] + }, + "Name": "UseAppSync", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseHardcoded": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::Sub": "${HarcodedDataSourceName}" + }, + "Name": "UseHardcoded", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseImported": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::ImportValue": "SomeSharedDataSourceName" + }, + "Name": "UseImported", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIUseInternal": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIInternalDataSourceDynamoDBDataSource", + "Name" + ] + }, + "Name": "UseInternal", + "Runtime": { + "Name": "APPSYNC_JS", + "RuntimeVersion": "1.0.0" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/graphqlapi_lambda_and_ddb_datasource.json b/tests/translator/output/graphqlapi_lambda_and_ddb_datasource.json new file mode 100644 index 000000000..b44fe7df7 --- /dev/null +++ b/tests/translator/output/graphqlapi_lambda_and_ddb_datasource.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceDynamoDBDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "DynamoDBConfig": { + "AwsRegion": { + "Ref": "AWS::Region" + }, + "TableName": "some-table" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-ddb-role", + "Type": "AMAZON_DYNAMODB" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": "my-lambda-role", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_lambda_datasource_connector.json b/tests/translator/output/graphqlapi_lambda_datasource_connector.json new file mode 100644 index 000000000..07656725e --- /dev/null +++ b/tests/translator/output/graphqlapi_lambda_datasource_connector.json @@ -0,0 +1,157 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": "blah" + }, + "Name": "MyDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSourceRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIMyDataSourceLambdaDataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + "blah", + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": "blah" + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "SuperCoolAPIMyDataSourceLambdaDataSourceRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_logging_defined.json b/tests/translator/output/graphqlapi_logging_defined.json new file mode 100644 index 000000000..8fc5815f5 --- /dev/null +++ b/tests/translator/output/graphqlapi_logging_defined.json @@ -0,0 +1,39 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": "some-arn", + "ExcludeVerboseContent": true, + "FieldLogLevel": "ERROR" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_logging_true.json b/tests/translator/output/graphqlapi_logging_true.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/graphqlapi_logging_true.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_multiple_auth.json b/tests/translator/output/graphqlapi_multiple_auth.json new file mode 100644 index 000000000..0f714f414 --- /dev/null +++ b/tests/translator/output/graphqlapi_multiple_auth.json @@ -0,0 +1,297 @@ +{ + "Resources": { + "Authorizer1": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer1Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer1Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "Authorizer2": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return {\n isAuthorized: true,\n deniedFields: [],\n }\n}\n" + }, + "Handler": "index.handler", + "PackageType": "Zip", + "Role": { + "Fn::GetAtt": [ + "Authorizer2Role", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "Authorizer2Role": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPI": { + "Properties": { + "AdditionalAuthenticationProviders": [ + { + "AuthenticationType": "AWS_IAM" + }, + { + "AuthenticationType": "API_KEY" + }, + { + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + } + } + }, + { + "AuthenticationType": "OPENID_CONNECT", + "OpenIDConnectConfig": { + "AuthTTL": 10, + "ClientId": "myid", + "IatTTL": 10, + "Issuer": "prad" + } + }, + { + "AuthenticationType": "AMAZON_COGNITO_USER_POOLS", + "UserPoolConfig": { + "AppIdClientRegex": "myregex", + "AwsRegion": "na-east-1", + "UserPoolId": "myid" + } + } + ], + "AuthenticationType": "AWS_LAMBDA", + "LambdaAuthorizerConfig": { + "AuthorizerResultTtlInSeconds": 10, + "AuthorizerUri": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "IdentityValidationExpression": "hello" + }, + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPIToLambdaAuthConnector1WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector1": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer1", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + }, + "SuperCoolAPIToLambdaAuthConnector2WriteLambdaPermission": { + "Metadata": { + "aws:sam:connectors": { + "SuperCoolAPIToLambdaAuthConnector2": { + "Destination": { + "Type": "AWS::Lambda::Function" + }, + "Source": { + "Type": "AWS::AppSync::GraphQLApi" + } + } + } + }, + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "Authorizer2", + "Arn" + ] + }, + "Principal": "appsync.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:${AWS::Partition}:appsync:${AWS::Region}:${AWS::AccountId}:apis/${SourceResourceId}", + { + "SourceResourceId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + } + } + ] + } + }, + "Type": "AWS::Lambda::Permission" + } + } +} diff --git a/tests/translator/output/graphqlapi_multiple_none_datasource_functions.json b/tests/translator/output/graphqlapi_multiple_none_datasource_functions.json new file mode 100644 index 000000000..be21f85df --- /dev/null +++ b/tests/translator/output/graphqlapi_multiple_none_datasource_functions.json @@ -0,0 +1,163 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPIAnotherFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "AnotherFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIGoodFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "GoodFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPINoneDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Name": "SuperCoolAPINoneDataSource", + "Type": "NONE" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "SuperCoolAPISimilarFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CodeS3Location": "my-code-uri", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPINoneDataSource", + "Name" + ] + }, + "Name": "SimilarFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + } + } +} diff --git a/tests/translator/output/graphqlapi_no_logging.json b/tests/translator/output/graphqlapi_no_logging.json new file mode 100644 index 000000000..3b22de27d --- /dev/null +++ b/tests/translator/output/graphqlapi_no_logging.json @@ -0,0 +1,34 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_no_name.json b/tests/translator/output/graphqlapi_no_name.json new file mode 100644 index 000000000..be30d7483 --- /dev/null +++ b/tests/translator/output/graphqlapi_no_name.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SuperCoolAPI", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/translator/output/graphqlapi_resolver_function_with_lambda_datasource.json b/tests/translator/output/graphqlapi_resolver_function_with_lambda_datasource.json new file mode 100644 index 000000000..614275f6b --- /dev/null +++ b/tests/translator/output/graphqlapi_resolver_function_with_lambda_datasource.json @@ -0,0 +1,151 @@ +{ + "Resources": { + "SuperCoolAPI": { + "Properties": { + "AuthenticationType": "AWS_IAM", + "LogConfig": { + "CloudWatchLogsRoleArn": { + "Fn::GetAtt": [ + "SuperCoolAPICloudWatchRole", + "Arn" + ] + }, + "FieldLogLevel": "ALL" + }, + "Name": "SomeApi", + "Tags": [ + { + "Key": "key1", + "Value": "value1" + }, + { + "Key": "key2", + "Value": "value2" + } + ], + "XrayEnabled": true + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "SuperCoolAPICloudWatchRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "appsync.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + } + ] + }, + "Type": "AWS::IAM::Role" + }, + "SuperCoolAPIMutationmyResolver": { + "DependsOn": [ + "SuperCoolAPISchema" + ], + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "CachingConfig": { + "CachingKeys": [ + "key1", + "key2" + ], + "Ttl": 20 + }, + "Code": "\nexport function request(ctx) {\n return {};\n}\n\nexport function response(ctx) {\n return ctx.prev.result;\n}\n", + "FieldName": "my_field", + "Kind": "PIPELINE", + "MaxBatchSize": 10, + "PipelineConfig": { + "Functions": [ + { + "Fn::GetAtt": [ + "SuperCoolAPIMyFunction", + "FunctionId" + ] + } + ] + }, + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + }, + "TypeName": "Mutation" + }, + "Type": "AWS::AppSync::Resolver" + }, + "SuperCoolAPIMyDataSourceLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Description": "lambda datasources are nice", + "LambdaConfig": { + "LambdaFunctionArn": "my-lambda-arn" + }, + "Name": "PradsLambdaDataSource", + "ServiceRoleArn": "some-role-arn", + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "SuperCoolAPIMyFunction": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Code": "this is my epic code", + "DataSourceName": { + "Fn::GetAtt": [ + "SuperCoolAPIMyDataSourceLambdaDataSource", + "Name" + ] + }, + "MaxBatchSize": 10, + "Name": "MyFunction", + "Runtime": { + "Name": "some-runtime", + "RuntimeVersion": "1.2.3" + } + }, + "Type": "AWS::AppSync::FunctionConfiguration" + }, + "SuperCoolAPISchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "SuperCoolAPI", + "ApiId" + ] + }, + "Definition": "type Mutation {\n addTodo(id: ID!, name: String, description: String, priority: Int): Todo\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + } + } +} diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index 62eb62686..88b2f712d 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -1,6 +1,13 @@ from unittest import TestCase -from samtranslator.utils.utils import InvalidValueType, as_array, dict_deep_get, dict_deep_set, insert_unique +from samtranslator.internal.utils.utils import remove_none_values +from samtranslator.utils.utils import ( + InvalidValueType, + as_array, + dict_deep_get, + dict_deep_set, + insert_unique, +) class TestUtils(TestCase): @@ -62,3 +69,10 @@ def test_dict_deep_set_invalid_path(self): d = {"a": {"b": {"c": "hi"}}} with self.assertRaisesRegex(ValueError, r"path cannot be empty"): dict_deep_set(d, "", "world") + + def test_remove_none_values(self): + d = {"a": "hello", "b": None} + self.assertEqual(remove_none_values(d), {"a": "hello"}) + + d = {"a": None, "b": None, "c": None} + self.assertEqual(remove_none_values(d), {}) diff --git a/tests/validator/output/root/error_resources.json b/tests/validator/output/root/error_resources.json index b7b85913b..1f74d1152 100644 --- a/tests/validator/output/root/error_resources.json +++ b/tests/validator/output/root/error_resources.json @@ -2,5 +2,5 @@ "[Resources.EmptyResource] Must not be empty", "[Resources.TypeCustomThreePartsInsteadOfTwo.Type] 'Custom::My::Custom' must use format Custom::X", "[Resources.TypeMissingSemiColon.Type] 'AWS::Serverless:Api' must use format X::Y::Z", - "[Resources.TypeUnknownServerless.Type] 'AWS::Serverless::UnknownType' is not one of ['AWS::Serverless::Api', 'AWS::Serverless::Application', 'AWS::Serverless::Function', 'AWS::Serverless::HttpApi', 'AWS::Serverless::LayerVersion', 'AWS::Serverless::SimpleTable', 'AWS::Serverless::StateMachine', 'AWS::Serverless::Connector']" + "[Resources.TypeUnknownServerless.Type] 'AWS::Serverless::UnknownType' is not one of ['AWS::Serverless::Api', 'AWS::Serverless::Application', 'AWS::Serverless::Function', 'AWS::Serverless::HttpApi', 'AWS::Serverless::LayerVersion', 'AWS::Serverless::SimpleTable', 'AWS::Serverless::StateMachine', 'AWS::Serverless::Connector', 'AWS::Serverless::GraphQLApi']" ]