AWSTemplateFormatVersion: '2010-09-09' Description: (SO0102-api-stack-sports) - 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: RealTime Live Sports API 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: SportTable: 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}-Sport-${env}" KeySchema: - AttributeName: id KeyType: HASH AttributeDefinitions: - AttributeName: id 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 SSESpecification: SSEEnabled: !If [ShouldUseServerSideEncryption, true, false] PointInTimeRecoverySpecification: Fn::If: - ShouldUsePointInTimeRecovery - PointInTimeRecoveryEnabled: true - Ref: AWS::NoValue DeletionPolicy: Delete SportIAMRole: 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: - "-" - - Sport - role - Ref: GetAttGraphQLAPIApiId - Ref: env - Fn::Join: - "-" - - Sport - 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 SportTable.Arn - !Sub [ "${x0}/*", { x0: !GetAtt SportTable.Arn } ] SportDataSource: Type: AWS::AppSync::DataSource Properties: ApiId: Ref: GetAttGraphQLAPIApiId Name: SportTable Type: AMAZON_DYNAMODB ServiceRoleArn: !GetAtt 'SportIAMRole.Arn' DynamoDBConfig: AwsRegion: Ref: AWS::Region TableName: !Ref SportTable DependsOn: - SportIAMRole GetSportResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'SportDataSource.Name' FieldName: getSport TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getSport - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - getSport - res - vtl ListSportResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'SportDataSource.Name' FieldName: listSports TypeName: Query RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listSports - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Query - listSports - res - vtl CreateSportResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'SportDataSource.Name' FieldName: createSport TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createSport - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - createSport - res - vtl UpdateSportResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'SportDataSource.Name' FieldName: updateSport TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateSport - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - updateSport - res - vtl DeleteSportResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: !GetAtt 'SportDataSource.Name' FieldName: deleteSport TypeName: Mutation RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteSport - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Mutation - deleteSport - res - vtl SportfeedConfigResolver: Type: AWS::AppSync::Resolver Properties: ApiId: Ref: GetAttGraphQLAPIApiId DataSourceName: NONE FieldName: feedConfig TypeName: Sport RequestMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Sport - feedConfig - req - vtl ResponseMappingTemplateS3Location: Fn::Sub: - s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName} - S3DeploymentBucket: Ref: S3DeploymentBucket S3DeploymentRootKey: Ref: S3DeploymentRootKey ResolverFileName: Fn::Join: - "." - - Sport - feedConfig - res - vtl Outputs: GetAttSportTableStreamArn: Description: DynamoDB Sport table StreamArn. Value: !GetAtt 'SportTable.StreamArn' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - SportTable - StreamArn GetAttSportDataSourceName: Description: DataSource name. Value: !GetAtt 'SportDataSource.Name' Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - SportDataSource - Name GetAttSportTableName: Description: DynamoDB Sport table name. Value: Ref: SportTable Export: Name: Fn::Join: - ":" - - Ref: AppSyncApiId - GetAtt - SportTable - 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