AWSTemplateFormatVersion: 2010-09-09 Description: AWS ParallelCluster Slurm Accounting Database Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "Database Cluster Configuration" Parameters: - ClusterName - ClusterAdmin - AdminPasswordSecretString - MinCapacity - MaxCapacity - Label: default: "Network Configuration" Parameters: - Vpc - DatabaseClusterSubnetOne - DatabaseClusterSubnetTwo - Subnet1CidrBlock - Subnet2CidrBlock ParameterLabels: Vpc: default: "The VPC to use for the database cluster." ClusterName: default: "The name of the database cluster" ClusterAdmin: default: "The database administrator user name." AdminPasswordSecretString: default: "The administrator password." MinCapacity: default: "The minimum scaling capacity of the database cluster." MaxCapacity: default: "The maximum scaling capacity of the database cluster." DatabaseClusterSubnetOne: default: "The first subnet to use for the database cluster." DatabaseClusterSubnetTwo: default: "The second subnet to use for the database cluster." Subnet1CidrBlock: default: "The CIDR block to be used for the first Subnet if its creation is requested." Subnet2CidrBlock: default: "The CIDR block to be used for the second Subnet if its creation is requested." Parameters: ClusterName: Description: Database Cluster Name Type: String Default: "slurm-accounting-cluster" MinLength: 1 MaxLength: 63 AllowedPattern: ^[a-z][-a-z0-9]{0,62}$ ConstraintDescription: >- Cluster name must be between 1 and 63 characters, start with a lower case character, and be followed by a mix of lower case characters, digits, and - (hyphens). AdminPasswordSecretString: Description: >- Password must be at least 8 characters long and contain at least 1 upper case, 1 lower case, 1 digit, and 1 non-alphanumeric character. It must not contain any of the following: # (hash), / (slash), ' (single quote), " (double quote) or @ (at sign). Type: String NoEcho: true MinLength: 8 # Only allow 'Medium' or better strength passwords according to https://dev.mysql.com/doc/refman/8.0/en/validate-password.html AllowedPattern: (?=^.{8,}$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\s])(?!.*[@/'"#])^.* ConstraintDescription: >- Password must be at least 8 characters with at least one uppercase letter, one lower case letter, one numeric digit, and one special (non-alphanumeric) character. It can not contain any of the following: # (hash), / (slash), ' (single quote), " (double quote) and @ (at sign). ClusterAdmin: Description: Administrator user name. Type: String Default: clusteradmin MinLength: 3 MaxLength: 64 Vpc: Description: VPC ID. Type: AWS::EC2::VPC::Id DatabaseClusterSubnetOne: Description: First Subnet ID (leave BLANK to create a new subnet). Type: String # Type: AWS::EC2::Subnet::Id Default: '' DatabaseClusterSubnetTwo: Description: Second subnet ID (leave BLANK to create a new subnet). This subnet must be in different availability zone from the first subnet. Type: String # Type: AWS::EC2::Subnet::Id Default: '' Subnet1CidrBlock: Description: CIDR block for first Subnet (used only if creation is requested - IN THIS CASE THE DEFAULT VALUE MUST BE CHANGED). Type: String Default: '0.0.0.0/24' AllowedPattern: >- ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ ConstraintDescription: >- The CIDR block must be formatted as W.X.Y.Z/prefix , where prefix must be between 16 and 28. Subnet2CidrBlock: Description: CIDR block for the second Subnet (used only if creation is requested - IN THIS CASE THE DEFAULT VALUE MUST BE CHANGED). Type: String Default: '0.0.0.0/24' AllowedPattern: >- ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$ ConstraintDescription: >- The CIDR block must be formatted as W.X.Y.Z/prefix , where prefix must be between 16 and 28. MinCapacity: Description: Must be less than the maximum capacity. Type: Number Default: 1 MinValue: .5 MaxValue: 127.5 MaxCapacity: Description: Must be greater than or equal to the minimum capacity. Type: Number Default: 4 MinValue: 1 MaxValue: 128 Transform: AWS::Serverless-2016-10-31 Conditions: CreateSubnets: !Or [!Equals [!Ref DatabaseClusterSubnetOne, ''], !Equals [!Ref DatabaseClusterSubnetTwo, '']] InUsIsobEast1: !Equals [ !Ref AWS::Region, 'us-isob-east-1' ] InUsIsoEast1: !Equals [ !Ref AWS::Region, 'us-iso-east-1' ] UseServerlessDatabase: !Not [!Or [Condition: InUsIsobEast1, Condition: InUsIsoEast1]] Rules: BadSubnetsCidrsAssertion: RuleCondition: !Or - !Equals - !Ref DatabaseClusterSubnetOne - '' - !Equals - !Ref DatabaseClusterSubnetTwo - '' Assertions: - Assert: !Not - !Equals - !Ref Subnet1CidrBlock - '0.0.0.0/24' AssertDescription: The default CIDR block for the first subnet must be changed if the subnet creation is requested. - Assert: !Not - !Equals - !Ref Subnet2CidrBlock - '0.0.0.0/24' AssertDescription: The default CIDR block for the second subnet must be changed if the subnet creation is requested. Resources: # # Optional Networking # AccountingClusterSubnet1: Type: 'AWS::EC2::Subnet' Condition: CreateSubnets Properties: VpcId: !Ref Vpc AvailabilityZone: !Sub - "${AWS::Region}${AzLetter}" - { AzLetter: !If [ InUsIsobEast1, 'c', 'a'] } CidrBlock: !Ref Subnet1CidrBlock MapPublicIpOnLaunch: false Tags: - Key: Name Value: AccountingClusterSubnet1 - Key: 'parallelcluster:infrastructure' Value: 'slurm accounting' AccountingClusterSubnet1RouteTable: Type: 'AWS::EC2::RouteTable' Condition: CreateSubnets Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: AccountingClusterSubnet1 - Key: 'parallelcluster:infrastructure' Value: 'slurm accounting' AccountingClusterSubnet1RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Condition: CreateSubnets Properties: RouteTableId: !Ref AccountingClusterSubnet1RouteTable SubnetId: !Ref AccountingClusterSubnet1 AccountingClusterSubnet2: Type: 'AWS::EC2::Subnet' Condition: CreateSubnets Properties: VpcId: !Ref Vpc AvailabilityZone: !Sub '${AWS::Region}b' CidrBlock: !Ref Subnet2CidrBlock MapPublicIpOnLaunch: false Tags: - Key: Name Value: AccountingClusterSubnet2 - Key: 'parallelcluster:infrastructure' Value: 'slurm accounting' AccountingClusterSubnet2RouteTable: Type: 'AWS::EC2::RouteTable' Condition: CreateSubnets Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: AccountingClusterSubnet2 - Key: 'parallelcluster:infrastructure' Value: 'slurm accounting' AccountingClusterSubnet2RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Condition: CreateSubnets Properties: RouteTableId: !Ref AccountingClusterSubnet2RouteTable SubnetId: !Ref AccountingClusterSubnet2 # # Database Cluster # AccountingClusterParameterGroup: Type: 'AWS::RDS::DBClusterParameterGroup' Properties: Description: Cluster parameter group for aurora-mysql Family: aurora-mysql8.0 Parameters: require_secure_transport: 'ON' innodb_lock_wait_timeout: '900' Tags: - Key: 'parallelcluster:usecase' Value: 'slurm accounting' AccountingClusterSubnetGroup: Type: 'AWS::RDS::DBSubnetGroup' Properties: DBSubnetGroupDescription: !Sub 'Subnets for AccountingCluster-${AWS::Region} database' SubnetIds: - !If [CreateSubnets, !Ref AccountingClusterSubnet1, !Ref DatabaseClusterSubnetOne] - !If [CreateSubnets, !Ref AccountingClusterSubnet2, !Ref DatabaseClusterSubnetTwo] Tags: - Key: 'parallelcluster:usecase' Value: 'slurm accounting' AccountingClusterSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: RDS security group SecurityGroupEgress: - CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic by default IpProtocol: '-1' Tags: - Key: 'parallelcluster:usecase' Value: 'slurm accounting' VpcId: !Ref Vpc AccountingClusterSecurityGroupInboundRule: Type: 'AWS::EC2::SecurityGroupIngress' Properties: IpProtocol: tcp Description: Allow incoming connections from client security group FromPort: !GetAtt - AccountingCluster - Endpoint.Port GroupId: !GetAtt - AccountingClusterSecurityGroup - GroupId SourceSecurityGroupId: !GetAtt - AccountingClusterClientSecurityGroup - GroupId ToPort: !GetAtt - AccountingCluster - Endpoint.Port AccountingClusterAdminSecret: Type: 'AWS::SecretsManager::Secret' Properties: Description: 'Serverless Database Cluster Administrator Password' SecretString: !Ref AdminPasswordSecretString Tags: - Key: 'parallelcluster:usecase' Value: 'slurm accounting' AccountingCluster: Type: 'AWS::RDS::DBCluster' Properties: DBClusterIdentifier: !Ref ClusterName Engine: "aurora-mysql" EngineVersion: "8.0.mysql_aurora.3.03.0" CopyTagsToSnapshot: true DBClusterParameterGroupName: !Ref AccountingClusterParameterGroup DBSubnetGroupName: !Ref AccountingClusterSubnetGroup EnableHttpEndpoint: false MasterUsername: !Ref ClusterAdmin MasterUserPassword: !Ref AdminPasswordSecretString ServerlessV2ScalingConfiguration: !If - UseServerlessDatabase - MaxCapacity: !Ref MaxCapacity MinCapacity: !Ref MinCapacity - !Ref AWS::NoValue StorageEncrypted: true Tags: - Key: 'parallelcluster:usecase' Value: 'slurm accounting' VpcSecurityGroupIds: - !GetAtt - AccountingClusterSecurityGroup - GroupId UpdateReplacePolicy: Delete DeletionPolicy: Delete AccountingClusterInstance1: Type: 'AWS::RDS::DBInstance' Properties: DBInstanceClass: !If [UseServerlessDatabase, 'db.serverless', 'db.r5.large'] DBClusterIdentifier: !Ref AccountingCluster DBInstanceIdentifier: !Sub '${ClusterName}-instance-1' Engine: "aurora-mysql" PubliclyAccessible: false UpdateReplacePolicy: Delete DeletionPolicy: Delete AccountingClusterInstance2: Type: 'AWS::RDS::DBInstance' Properties: DBInstanceClass: !If [UseServerlessDatabase, 'db.serverless', 'db.r5.large'] DBClusterIdentifier: !Ref AccountingCluster DBInstanceIdentifier: !Sub '${ClusterName}-instance-2' Engine: "aurora-mysql" PubliclyAccessible: false UpdateReplacePolicy: Delete DeletionPolicy: Delete AccountingClusterClientSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Security Group to allow connection to Serverless DB Cluster Tags: - Key: 'parallel-cluster:usecase' Value: 'slurm accounting' VpcId: !Ref Vpc AccountingClusterClientSecurityGroupOutboundRule: Type: 'AWS::EC2::SecurityGroupEgress' Properties: GroupId: !GetAtt - AccountingClusterClientSecurityGroup - GroupId IpProtocol: tcp Description: Allow incoming connections from PCluster DestinationSecurityGroupId: !GetAtt - AccountingClusterSecurityGroup - GroupId FromPort: !GetAtt - AccountingCluster - Endpoint.Port ToPort: !GetAtt - AccountingCluster - Endpoint.Port Outputs: ClusterName: Value: !Ref ClusterName DatabaseHost: Value: !GetAtt - AccountingCluster - Endpoint.Address DatabasePort: Value: !GetAtt - AccountingCluster - Endpoint.Port DatabaseAdminUser: Value: !Ref ClusterAdmin DatabaseSecretArn: Value: !Ref AccountingClusterAdminSecret DatabaseVpcId: Value: !Ref Vpc DatabaseClusterSecurityGroup: Value: !GetAtt - AccountingClusterSecurityGroup - GroupId DatabaseClusterSubnet1: Value: !If [CreateSubnets, !Ref AccountingClusterSubnet1, !Ref DatabaseClusterSubnetOne] DatabaseClusterSubnet2: Value: !If [CreateSubnets, !Ref AccountingClusterSubnet2, !Ref DatabaseClusterSubnetTwo] DatabaseClientSecurityGroup: Value: !GetAtt - AccountingClusterClientSecurityGroup - GroupId