AWSTemplateFormatVersion: '2010-09-09'
Description: This is the main template for Microsoft HPC (qs-1s4u7q63u)
Metadata:
  cfn-lint:
    config:
      ignore_checks:
        - W9901
        - W9002
        - W9006
  QuickStartDocumentation:
    EntrypointName: "Parameters for deploying into an existing VPC"
    Order: "2"
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Network Configuration
        Parameters:
          - VPCID
          - VPCCIDR
          - PublicSubnet1ID
          - PublicSubnet1CIDR
          - PrivateSubnet1ID
          - PrivateSubnet1CIDR
          - PrivateSubnet2ID
          - PrivateSubnet2CIDR
          - RemoteAccessCIDR
      - Label:
          default: Active Directory Configuration
        Parameters:
          - DomainDNSName
          - DomainNetBIOSName
          - DomainAdminPassword
          - ADEdition
      - Label:
          default: MSHPCPACK HeadNode Configuration
        Parameters:
          - HeadNodeInstanceType
          - HeadNodeNetBIOSName
        #  - HeadNodeAMI
          - KeyPairName
      - Label:
          default: Certificate Configuration
        Parameters:
          - CertS3Bucket
          - CertS3Key
      - Label:
          default: AWS Quick Start Configuration
        Parameters:
          - QSS3BucketName
          - QSS3BucketRegion
          - QSS3KeyPrefix
      - Label:
          default: AutoScaling Configuration for On-Demand Capacity Request
        Parameters:
          - WorkerInstanceType
          - ASGName
          - DomainJoined
          - HTCoreCount
#          - ThreadsPerCore
      # - Label:
      #     default: FSX Storage Configuration
      #   Parameters:
      #     - FileSystemName
      #     - StorageCapacity
      #     - ThroughputCapacity
    ParameterLabels:
      CertS3Bucket:
        default: Certificate S3 bucket
      CertS3Key:
        default: Certificate S3 key
      DomainJoined:
        default: Join domain
      RemoteAccessCIDR:
        default: Remote access CIDR
      PrivateSubnet1CIDR:
        default: Private Subnet 1 CIDR
      PrivateSubnet2CIDR:
        default: Private Subnet 2 CIDR
      PublicSubnet1CIDR:
        default: Public Subnet 1 CIDR
      PrivateSubnet1ID:
        default: Subnet 1 ID
      PrivateSubnet2ID:
        default: Subnet 2 ID
      PublicSubnet1ID:
        default: Subnet 1 ID
      DomainAdminPassword:
        default: Domain Admin Password
      DomainDNSName:
        default: Domain DNS Name
      DomainNetBIOSName:
        default: Domain NetBIOS Name
      KeyPairName:
        default: Key Pair Name
      ADEdition:
        default: AWS Microsoft AD edition
      VPCCIDR:
        default: VPC CIDR
      VPCID:
        default: VPC ID
      # HeadNodeAMI:
      #   default: HeadNodeAMI
      HeadNodeNetBIOSName:
        default: Head Node NetBIOS Name
      HeadNodeInstanceType:
        default: Head Node Instance Type
      # FileSystemName:
      #  default: FileSystemName
      # StorageCapacity:
      #   default: StorageCapacity
      # ThroughputCapacity:
      #   default: ThroughputCapacity
      QSS3BucketName:
        default: Quick Start S3 bucket name
      QSS3BucketRegion:
        default: Quick Start S3 bucket Region
      QSS3KeyPrefix:
        default: Quick Start S3 key prefix
Parameters:
  CertS3Bucket:
    AllowedPattern: '^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$'
    Description: S3 bucket containing the certificate
    Type: String
    Default: aws-quickstart
  CertS3Key:
    Description: S3 key for the certificate
    Type: String
    Default: quickstart-microsoft-hpc/mypfx.pfx
  DomainJoined:
    Description: Join worker nodes to Active Directory
    Type: String
    AllowedValues:
      - 'True'
      - 'False'
    Default: 'False'
  RemoteAccessCIDR:
    Description: Remote access CIDR
    Default: "0.0.0.0/0"
    Type: String
  PrivateSubnet1CIDR:
    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])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    Default: 10.0.2.0/24
    Description: CIDR Block for private subnet 1 located in Availability Zone 1.
    Type: String
  PrivateSubnet2CIDR:
    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])(\/([0-9]|[1-2][0-9]|3[0-2]))$
    Default: 10.0.4.0/24
    Description: CIDR Block for private subnet 2 located in Availability Zone 2.
    Type: String
  PublicSubnet1CIDR:
    Default: 10.0.1.0/24
    Description: CIDR Block for the public DMZ subnet  located in Availability Zone
      1
    Type: String
  PrivateSubnet1ID:
    Description: ID of subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd)
    Type: AWS::EC2::Subnet::Id
  PrivateSubnet2ID:
    Description: ID of subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd)
    Type: AWS::EC2::Subnet::Id
  PublicSubnet1ID:
    Description: ID of subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd)
    Type: AWS::EC2::Subnet::Id
  VPCID:
    Description: ID of the VPC (e.g., vpc-0343606e)
    Type: AWS::EC2::VPC::Id
  DomainAdminPassword:
    AllowedPattern: (?=^.{6,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*
    Description: Password for the domain admin user. Must be at least 8 characters
      containing letters, numbers and symbols
    MaxLength: '32'
    MinLength: '8'
    NoEcho: 'true'
    Type: String
  DomainDNSName:
    AllowedPattern: '[a-zA-Z0-9\-]+\..+'
    Default: example.com
    Description: Fully qualified domain name (FQDN) of the forest root domain e.g.
      example.com
    MaxLength: '255'
    MinLength: '2'
    Type: String
  DomainNetBIOSName:
    AllowedPattern: '[a-zA-Z0-9\-]+'
    Default: EXAMPLE
    Description: NetBIOS name of the domain (up to 15 characters) for users of earlier
      versions of Windows e.g. EXAMPLE
    MaxLength: '15'
    MinLength: '1'
    Type: String
  ADEdition:
    AllowedValues:
      - Standard
      - Enterprise
    Default: Standard
    Description: The AWS Microsoft AD edition. Valid values include Standard and Enterprise.
    Type: String
  KeyPairName:
    Description: Public/private key pairs allow you to securely connect to your instance
      after it launches
    Type: AWS::EC2::KeyPair::KeyName
  QSS3BucketName:
    AllowedPattern: '^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$'
    ConstraintDescription:
      The Quick Start bucket name can include numbers, lowercase
      letters, uppercase letters, and hyphens (-). It cannot start or end with a 
      hyphen (-).
    Default: aws-quickstart
    Description:
      Name of the S3 bucket for your copy of the Quick Start assets. 
      Keep the default name unless you are customizing the template. 
      Changing the name updates code references to point to a new Quick 
      Start location. This name can include numbers, lowercase letters, 
      uppercase letters, and hyphens, but do not start or end with a hyphen (-). 
      See https://aws-quickstart.github.io/option1.html.
    Type: String
  QSS3BucketRegion:
    Default: 'us-east-1'
    Description: 'AWS Region where the Quick Start S3 bucket (QSS3BucketName) is 
    hosted. Keep the default Region unless you are customizing the template. 
    Changing this Region updates code references to point to a new Quick Start location. 
    When using your own bucket, specify the Region. 
    See https://aws-quickstart.github.io/option1.html.'
    Type: String
  QSS3KeyPrefix:
    AllowedPattern: '^[0-9a-zA-Z-/]*$'
    ConstraintDescription:
      The Quick Start S3 key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and forward slashes (/). The prefix should
      end with a forward slash (/).
    Default: quickstart-microsoft-hpc/
    Description:
      S3 key prefix that is used to simulate a directory for your copy of the 
      Quick Start assets. Keep the default prefix unless you are customizing 
      the template. Changing this prefix updates code references to point to 
      a new Quick Start location. This prefix can include numbers, lowercase 
      letters, uppercase letters, hyphens (-), and forward slashes (/). End with 
      a forward slash. See https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html 
      and https://aws-quickstart.github.io/option1.html.
    Type: String
  VPCCIDR:
    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: CIDR block parameter must be in the form x.x.x.x/16-28
    Default: 10.0.0.0/16
    Description: CIDR Block for the VPC
    Type: String
  HeadNodeInstanceType:
    AllowedValues:
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - t3.medium
    Default: c5.xlarge
    Description: Amazon EC2 instance type for GRID Server
    Type: String
  HeadNodeNetBIOSName:
    AllowedPattern: '[a-zA-Z0-9\-]+'
    Default: hpcbar
    Description: NetBIOS name of the GRID Server
    MaxLength: '15'
    MinLength: '1'
    Type: String
  # FileSystemName:
  #   AllowedPattern: '[a-zA-Z0-9\-]+'
  #   Default: hpcstorage
  #   Description: Please provide the name of the filesystem for Windows FSX Storage
  #   MaxLength: '15'
  #   MinLength: '1'
  #   Type: String
  # StorageCapacity:
  #   AllowedValues:
  #     - '40'
  #     - '50'
  #     - '60'
  #   Default: '40'
  #   Description: Provide the Storage capacity required for FSX shared storage
  #   Type: String
  # ThroughputCapacity:
  #   AllowedValues:
  #     - '8'
  #     - '16'
  #   Default: '8'
  #   Description: Provide the throughput capacity required for FSX shared storage
  #   Type: String
  WorkerInstanceType:
    AllowedValues:
      - c5d.large
      - c5d.xlarge
      - c5d.2xlarge
      - c5d.4xlarge
      - c5d.9xlarge
      - c5d.18xlarge
    Default: c5d.xlarge
    Description: Amazon EC2 instance type for Worker NOde
    Type: String
  ASGName:
    AllowedPattern: '[a-zA-Z0-9\-]+'
    Default: HPCASG
    Description: AutoScaling Group Name for Worker Node
    MaxLength: '15'
    MinLength: '1'
    Type: String
  HTCoreCount:
    Default: '2'
    Description: This depends on Instance Type. For example To disable HT for c5d.18xlarge,
      specify 32.
    Type: String
#  ThreadsPerCore:
#    AllowedValues:
#      - '1'
#    Default: '1'
#    Description: Setting this to 1 disables HYPERTHREADING
#    Type: String
Conditions:
  UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart']
Resources:
  ADUserSecrets:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: !Sub 'ADUserSecrets-${AWS::StackName}'
      Description: AD Admin User
      SecretString: !Sub '{ "username" : "admin", "password" : "${DomainAdminPassword}" }'
  ADStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL:
        !Sub
          - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/adstack.template.yaml
          - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion]
            S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
      Parameters:
        ADEdition: !Ref 'ADEdition'
        DomainAdminPassword: !Ref 'DomainAdminPassword'
        DomainDNSName: !Ref 'DomainDNSName'
        DomainNetBIOSName: !Ref 'DomainNetBIOSName'
        PrivateSubnet1CIDR: !Ref 'PrivateSubnet1CIDR'
        PrivateSubnet1ID: !Ref 'PrivateSubnet1ID'
        PrivateSubnet2ID: !Ref 'PrivateSubnet2ID'
        PrivateSubnet2CIDR: !Ref 'PrivateSubnet2CIDR'
        VPCCIDR: !Ref 'VPCCIDR'
        VPCID: !Ref 'VPCID'
  Headnode:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL:
        !Sub
          - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/headnode.template.yaml
          - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion]
            S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
      Parameters:
        ADUserSecrets: !Ref ADUserSecrets
        DomainDNSName: !Ref 'DomainDNSName'
        QSS3BucketName: !Ref 'QSS3BucketName'
        QSS3BucketRegion: !Ref 'QSS3BucketRegion'
        QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
        DomainMemberSGID: !GetAtt 'ADStack.Outputs.DomainMemberSGID'
        HeadNodeSGID: !GetAtt 'ADStack.Outputs.HeadNodeSGID'
        DomainNetBIOSName: !Ref 'DomainNetBIOSName'
        KeyPairName: !Ref 'KeyPairName'
        PrivateSubnet1ID: !Ref 'PrivateSubnet1ID'
        PublicSubnet1ID: !Ref 'PublicSubnet1ID'
        VPCID: !Ref 'VPCID'
        MicrosoftAD: !GetAtt 'ADStack.Outputs.MicrosoftAD'
        HeadNodeInstanceType: !Ref 'HeadNodeInstanceType'
        HeadNodeNetBIOSName: !Ref 'HeadNodeNetBIOSName'
        RemoteAccessCIDR: !Ref 'RemoteAccessCIDR'
        CertS3Bucket: !Ref 'CertS3Bucket'
        CertS3Key: !Ref 'CertS3Key'
  WorkerStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL:
        !Sub
          - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/workerstack.template.yaml
          - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion]
            S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
      Parameters:
        WorkerSGID: !GetAtt 'ADStack.Outputs.WorkerSGID'
        KeyPairName: !Ref 'KeyPairName'
        PrivateSubnet1ID: !Ref 'PrivateSubnet1ID'
#        PrivateSubnet2ID: !Ref 'PrivateSubnet2ID'
#        VPCID: !Ref 'VPCID'
        ASGName: !Ref 'ASGName'
        HeadNodeNetBIOSName: !Ref 'HeadNodeNetBIOSName'
        DomainDNSName: !Ref 'DomainDNSName'
        DomainNetBIOSName: !Ref 'DomainNetBIOSName'
        ADUserSecrets: !Ref ADUserSecrets
        WorkerInstanceType: !Ref 'WorkerInstanceType'
        HTCoreCount: !Ref 'HTCoreCount'
#        ThreadsPerCore: !Ref 'ThreadsPerCore'
        QSS3BucketName: !Ref 'QSS3BucketName'
        QSS3BucketRegion: !Ref 'QSS3BucketRegion'
        QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
        CertS3Bucket: !Ref 'CertS3Bucket'
        CertS3Key: !Ref 'CertS3Key'
Outputs:
  ADUserSecrets: 
    Value: !Ref 'ADUserSecrets'
    Description: "AD user secrets"