AWSTemplateFormatVersion: '2010-09-09' Description: (SO0102-api-stack-game) - 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: Option 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: Auto-generated parameter that forwards Fn.GetAtt(GraphQLAPI, ApiId) through to nested stacks. Resources: GameTable: 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}-Game-${env}" KeySchema: - AttributeName: id KeyType: HASH AttributeDefinitions: - AttributeName: id AttributeType: S - AttributeName: stageId AttributeType: S - AttributeName: plannedKickoffTime 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-StageGames" KeySchema: - AttributeName: "stageId" KeyType: "HASH" - AttributeName: "plannedKickoffTime" 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 GameIAMRole: 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: - "-" - - Game - role - Ref: GetAttGraphQLAPIApiId - Ref: env - Fn::Join: - "-" - - Game - 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 GameTable.Arn - !Sub [ "${x0}/*", { x0: !GetAtt GameTable.Arn } ] GameDataSource: Type: AWS::AppSync::DataSource Properties: ApiId: Ref: GetAttGraphQLAPIApiId Name: GameTable Type: AMAZON_DYNAMODB ServiceRoleArn: !GetAtt 'GameIAMRole.Arn' DynamoDBConfig: AwsRegion: Ref: AWS::Region TableName: Ref: GameTable DependsOn: - GameIAMRole GetGameResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameDataSource.Name' FieldName: getGame TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getGame - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getGame - res - vtl ListGameResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameDataSource.Name' FieldName: listGames TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listGames - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listGames - res - vtl CreateGameResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameDataSource.Name' FieldName: createGame TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createGame - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createGame - res - vtl UpdateGameResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameDataSource.Name' FieldName: updateGame TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateGame - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateGame - res - vtl DeleteGameResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'GameDataSource.Name' FieldName: deleteGame TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteGame - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteGame - res - vtl GamefeedConfigResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: NONE FieldName: feedConfig TypeName: Game RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Game - feedConfig - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Game - feedConfig - res - vtl Outputs: GetAttGameTableStreamArn: Description: DynamoDB table StreamArn. Value: !GetAtt 'GameTable.StreamArn' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameTable - StreamArn GetAttGameDataSourceName: Description: DataSource name. Value: !GetAtt 'GameDataSource.Name' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameDataSource - Name GetAttGameTableName: Description: DynamoDB table name. Value: Ref: GameTable Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - GameTable - 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