AWSTemplateFormatVersion: '2010-09-09' Description: (SO0102-api-stack-gameEvent) - DynamoDB Resources and GraphQL Resolvers for RealTime Live Sports Update Using AWS AppSync. Version %%VERSION%% Metadata: {} Parameters: SolutionId: Type: String Description: solution ID DynamoDBModelTableReadIOPS: Type: Number Description: The number of read IOPS the table should support. Default: 5 DynamoDBModelTableWriteIOPS: Type: Number Description: The number of write IOPS the table should support. Default: 5 DynamoDBBillingMode: Type: String Description: Options for DynamoDB tables with PAY_PER_REQUEST or PROVISIONED billing modes. Default: PAY_PER_REQUEST AllowedValues: - PAY_PER_REQUEST - PROVISIONED DynamoDBEnablePointInTimeRecovery: Type: String Description: Whether to enable Point in Time Recovery on the table Default: 'false' AllowedValues: - 'true' - 'false' DynamoDBEnableServerSideEncryption: Type: String Description: Enable server side encryption powered by KMS. Default: 'true' AllowedValues: - 'true' - 'false' AppSyncApiName: Type: String Description: The name of the AppSync API Default: AppSyncSimpleTransform APIKeyExpirationEpoch: Type: Number Description: The epoch time in seconds when the API Key should expire. Setting this to 0 will default to 7 days from the deployment date. Setting this to -1 will not create an API Key. Default: 0 MinValue: -1 CreateAPIKey: Type: Number Description: The boolean value to control if an API Key will be created or not. The value of the property is automatically set by the CLI. If the value is set to 0 no API Key will be created. Default: 0 MinValue: 0 MaxValue: 1 env: Type: String Description: The environment name. e.g. Dev, Test, or Production Default: NONE S3DeploymentBucket: Type: String Description: The S3 bucket containing all deployment assets for the project. S3DeploymentRootKey: Type: String Description: An S3 key relative to the S3DeploymentBucket that points to the root of the deployment directory. AppSyncApiId: Type: String Description: The id of the AppSync API associated with this project. GetAttGraphQLAPIApiId: Type: String Description: GetAttGraphQLAPIApiId through to nested stacks. Resources: GameEventTable: Type: AWS::DynamoDB::Table Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "Table name is constructed with stack name. On update, we need to keep the existing table name." Properties: TableName: !Sub "${SolutionId}-GameEvent-${env}" KeySchema: - AttributeName: id KeyType: HASH AttributeDefinitions: - AttributeName: id AttributeType: S - AttributeName: gameId AttributeType: S - AttributeName: createdAt AttributeType: S StreamSpecification: StreamViewType: NEW_AND_OLD_IMAGES BillingMode: Fn::If: - ShouldUsePayPerRequestBilling - PAY_PER_REQUEST - Ref: AWS::NoValue ProvisionedThroughput: Fn::If: - ShouldUsePayPerRequestBilling - Ref: AWS::NoValue - ReadCapacityUnits: Ref: DynamoDBModelTableReadIOPS WriteCapacityUnits: Ref: DynamoDBModelTableWriteIOPS GlobalSecondaryIndexes: - IndexName: "gsi-GameEvents" KeySchema: - AttributeName: "gameId" KeyType: "HASH" - AttributeName: "createdAt" KeyType: "RANGE" Projection: ProjectionType: "ALL" ProvisionedThroughput: Fn::If: - ShouldUsePayPerRequestBilling - Ref: AWS::NoValue - ReadCapacityUnits: Ref: DynamoDBModelTableReadIOPS WriteCapacityUnits: Ref: DynamoDBModelTableWriteIOPS SSESpecification: SSEEnabled: !If [ShouldUseServerSideEncryption, true, false] PointInTimeRecoverySpecification: Fn::If: - ShouldUsePointInTimeRecovery - PointInTimeRecoveryEnabled: true - Ref: AWS::NoValue DeletionPolicy: Delete GameEventIAMRole: Type: AWS::IAM::Role Metadata: cfn_nag: rules_to_suppress: - id: W28 reason: "Role name is constructed with graphql API id . On update, we need to keep the existing table name." Properties: RoleName: Fn::If: - HasEnvironmentParameter - Fn::Join: - "-" - - GameEvent - role - Ref: GetAttGraphQLAPIApiId - Ref: env - Fn::Join: - "-" - - GameEvent - role - Ref: GetAttGraphQLAPIApiId AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: appsync.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: DynamoDBAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - dynamodb:BatchGetItem - dynamodb:BatchWriteItem - dynamodb:PutItem - dynamodb:DeleteItem - dynamodb:GetItem - dynamodb:Scan - dynamodb:Query - dynamodb:UpdateItem Resource: - !GetAtt GameEventTable.Arn - !Sub [ "${x0}/*", { x0: !GetAtt GameEventTable.Arn } ] GameEventDataSource: Type: AWS::AppSync::DataSource Properties: ApiId: Ref: GetAttGraphQLAPIApiId Name: GameEventTable Type: AMAZON_DYNAMODB ServiceRoleArn: !GetAtt 'GameEventIAMRole.Arn' DynamoDBConfig: AwsRegion: Ref: AWS::Region TableName: Ref: GameEventTable DependsOn: - GameEventIAMRole GetGameEventResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameEventDataSource.Name' FieldName: getGameEvent TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getGameEvent - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getGameEvent - res - vtl ListGameEventResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameEventDataSource.Name' FieldName: listGameEvents TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listGameEvents - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listGameEvents - res - vtl CreateGameEventResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameEventDataSource.Name' FieldName: createGameEvent TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createGameEvent - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createGameEvent - res - vtl UpdateGameEventResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameEventDataSource.Name' FieldName: updateGameEvent TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateGameEvent - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateGameEvent - res - vtl DeleteGameEventResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameEventDataSource.Name' FieldName: deleteGameEvent TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteGameEvent - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteGameEvent - res - vtl Outputs: GetAttGameEventTableStreamArn: Description: DynamoDB table StreamArn. Value: !GetAtt 'GameEventTable.StreamArn' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameEventTable - StreamArn GetAttGameEventDataSourceName: Description: DataSource name. Value: !GetAtt 'GameEventDataSource.Name' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameEventDataSource - Name GetAttGameEventTableName: Description: DynamoDB table name. Value: Ref: GameEventTable Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameEventTable - Name Mappings: {} Conditions: ShouldUsePayPerRequestBilling: Fn::Equals: - Ref: DynamoDBBillingMode - PAY_PER_REQUEST ShouldUsePointInTimeRecovery: Fn::Equals: - Ref: DynamoDBEnablePointInTimeRecovery - 'true' ShouldUseServerSideEncryption: Fn::Equals: - Ref: DynamoDBEnableServerSideEncryption - 'true' ShouldCreateAPIKey: Fn::Equals: - Ref: CreateAPIKey - 1 APIKeyExpirationEpochIsPositive: Fn::And: - Fn::Not: - Fn::Equals: - Ref: APIKeyExpirationEpoch - -1 - Fn::Not: - Fn::Equals: - Ref: APIKeyExpirationEpoch - 0 HasEnvironmentParameter: Fn::Not: - Fn::Equals: - Ref: env - NONE