AWSTemplateFormatVersion: '2010-09-09'
Description: "Perforce-server-main-template"
Metadata:
  AWS::CloudFormation::Interface: 
    ParameterGroups:
      - Label:
          default: ' VPC Network Configuration'
        Parameters:
          - AccessCIDR
      - Label: 
          default: "Perforce Server Configuration"
        Parameters: 
          - InstanceType
          - KeyPairName
          - DepotVolumeType
          - DepotVolumeSize
          - LogVolumeSize
          - MetadataVolumeType
          - MetadataVolumeSize
          - MetadataProvisionedIops
          - LatestAmiId
          - EnableReplica
      - Label:
          default: "AWS CloudFormation Template Source Configuration"
        Parameters:
          - QSS3BucketName
          - QSS3BucketRegion
          - QSS3KeyPrefix
    ParameterLabels:
      AccessCIDR:
        default: Permitted IP range
      InstanceType: 
        default: "Instance Type"
      KeyPairName:
        default: "Key Pair Name"
      DepotVolumeType:
        default: "Volume Type for Depot"
      DepotVolumeSize:
        default: "Volume Size for Depot"
      LogVolumeSize:
        default: "Volume Size for Log"
      MetadataVolumeType:
        default: "Volume Type for Metadata"
      MetadataVolumeSize:
        default: "Volume Size for Metadata"
      MetadataProvisionedIops:
        default: "Provisioned IOPS for Metadata Volume"
      LatestAmiId:
        default: "Latest AMI ID for Amazon Linux2"
      EnableReplica:
        default: "Enable Replica"
      QSS3BucketName:
        default: "Template S3 Bucket Name"
      QSS3BucketRegion:
        default: "Template S3 bucket region"
      QSS3KeyPrefix:
        default: "Template S3 Key Prefix"

Parameters:
  AccessCIDR:
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    ConstraintDescription: "must be a valid IP CIDR range of the form x.x.x.x/x."
    Description: "The IP address range that can be used to access to the EC2 instance"
    MaxLength: '18'
    MinLength: '9'
    Default: '0.0.0.0/0'
    Type: String
  InstanceType: 
    Type: String
    Default: c5.4xlarge
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - c5.4xlarge
      - c5.9xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5.4xlarge
      - r5.8xlarge
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
      - m5.8xlarge
    Description: "Select Perforce server EC2 instance type. Default is c5.4xlarge."
  KeyPairName:
    ConstraintDescription: "You must specify the name of an existing EC2 KeyPair."
    Description: "Public/private key pairs allow you to securely connect to your instance after it launches"
    Type: AWS::EC2::KeyPair::KeyName
  LatestAmiId:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
  EnableReplica:
    Type: String
    Default: "No"
    AllowedValues: 
      - "Yes"
      - "No"
    Description: "If you build Perforce Replica Server, select Yes. Replica Server will be the same setting as Master server."
  DepotVolumeType:
    Type: String
    Default: st1
    AllowedValues: 
      - st1
      - gp2
    Description: "Select either ST1 or GP2."
  DepotVolumeSize:
    Type: String
    Default: '1024'
    Description: "The size of the EBS volume attached for Depot."
  LogVolumeSize:
    Type: String
    Default: '128'
    Description: "The size of the EBS volume attached for Log."
  MetadataVolumeType:
    Type: String
    Default: gp2
    AllowedValues: 
      - gp2
      - io1
    Description: "Select either GP2 or IO1."
  MetadataVolumeSize:
    Type: String
    Default: '64'
    Description: "The size of the EBS volume attached for Metadata."
  MetadataProvisionedIops:
    ConstraintDescription: "Range is 100 to 64000 for Provisioned IOPS SSD volumes."
    Description: "Set the provisioned IOPs between 100 and 64000. Only set if you are choosing io1 for your metadata volume type."
    Type: "String"
  QSS3BucketName:
    AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
    ConstraintDescription: |
      Template bucket name can include numbers, lowercase
      letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
    Default: gametech-cfn-templates-public
    Description: | 
      S3 bucket name for the template assets. Template bucket name
      can include numbers, lowercase letters, uppercase letters, and hyphens (-).
      It cannot start or end with a hyphen (-).
    Type: String
  QSS3BucketRegion:
    Default: 'us-east-1'
    Description: 'The AWS Region where the template S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value.'
    Type: String
  QSS3KeyPrefix:
    AllowedPattern: ^[0-9a-zA-Z-]+(/[0-9a-zA-Z-]+)*/
    ConstraintDescription: |
      Template key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and forward slash (/). It cannot start with
      forward slash (/) because it is automatically added.
    Default: aws-perforce/
    Description: |
      S3 key prefix for the template assets. Template key prefix can include
      numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash
      (/). It cannot start with forward slash (/) because it is automatically added.
    Type: String

Conditions: 
  CreateReplicaServer: !Equals [ !Ref EnableReplica, "Yes" ]
  UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'gametech-cfn-templates-public']
  GovCloudCondition: !Equals [!Ref 'AWS::Region', us-gov-west-1]

Resources:
  PerforceVPCStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${QSS3BucketName}.s3.${QSS3BucketRegion}.amazonaws.com/${QSS3KeyPrefix}templates/PerforceVPCTemplate.yaml"
      Parameters:
        EnableReplica: !Ref EnableReplica
        AccessCIDR: !Ref AccessCIDR

  # Create Perforce master server
  PerforceMasterServerInstance:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://${QSS3BucketName}.s3.${QSS3BucketRegion}.amazonaws.com/${QSS3KeyPrefix}templates/PerforceServerSetupTemplate.yaml"
      Parameters:
        PerforceAZ: !Select 
          - 0
          - Fn::GetAZs: !Ref 'AWS::Region'      
        LatestAmiId: !Ref LatestAmiId
        InstanceType: !Ref InstanceType
        KeyPairName: !Ref KeyPairName
        ServerName: "p4-awsnva-01"
        ServerDescription: "Master/commit server. The master.1 is the SDP instance name, a data set identifier."
        ServerID: "master.1" 
        DepotVolumeType: !Ref DepotVolumeType
        DepotVolumeSize: !Ref DepotVolumeSize
        LogVolumeSize: !Ref LogVolumeSize
        MetadataVolumeType: !Ref MetadataVolumeType
        MetadataVolumeSize: !Ref MetadataVolumeSize
        MetadataProvisionedIops: !Ref MetadataProvisionedIops
        SubnetId: !GetAtt PerforceVPCStack.Outputs.PerforceMasterSubnetId
        PrivateIpAddress: 10.0.0.63
        PerforceSecurityGroup: !GetAtt PerforceVPCStack.Outputs.PerforceSecurityGroupId
        gw1: !GetAtt PerforceVPCStack.Outputs.PerforceVPCGatewaySettingID
        EC2Profile: !GetAtt PerforceVPCStack.Outputs.EC2ProfileID
  # Create Perforce replica server if needed
  PerforceReplicaServerInstance:
    Type: AWS::CloudFormation::Stack
    Condition: CreateReplicaServer
    Properties:
      TemplateURL: !Sub "https://${QSS3BucketName}.s3.${QSS3BucketRegion}.amazonaws.com/${QSS3KeyPrefix}templates/PerforceServerSetupTemplate.yaml"
      Parameters:
        PerforceAZ: !Select 
          - 1
          - Fn::GetAZs: !Ref 'AWS::Region'
        LatestAmiId: !Ref LatestAmiId
        InstanceType: !Ref InstanceType
        KeyPairName: !Ref KeyPairName
        ServerName: "p4-awsnva-02"
        ServerDescription: "Replica server. The p4d-ha-awsnva is the SDP instance name, a data set identifier."
        ServerID: "p4d-ha-awsnva"
        DepotVolumeType: !Ref DepotVolumeType
        DepotVolumeSize: !Ref DepotVolumeSize
        LogVolumeSize: !Ref LogVolumeSize
        MetadataVolumeType: !Ref MetadataVolumeType
        MetadataVolumeSize: !Ref MetadataVolumeSize
        MetadataProvisionedIops: !Ref MetadataProvisionedIops
        SubnetId: !GetAtt PerforceVPCStack.Outputs.PerforceReplicaSubnetId
        PrivateIpAddress: 10.0.1.63
        PerforceSecurityGroup: !GetAtt PerforceVPCStack.Outputs.PerforceSecurityGroupId
        gw1: !GetAtt PerforceVPCStack.Outputs.PerforceVPCGatewaySettingID
        EC2Profile: !GetAtt PerforceVPCStack.Outputs.EC2ProfileID

Outputs:
  PerforceMasterEIP:
    Description: Elasic IP Adress attached to Perforce Master server
    Value: !GetAtt PerforceMasterServerInstance.Outputs.PerforceEIP
  PerforceReplicaEIP:
    Condition: CreateReplicaServer
    Description: Elasic IP Adress attached to Perforce Replica server
    Value: !GetAtt PerforceReplicaServerInstance.Outputs.PerforceEIP
  PerforceMasterInstanceId:
    Description: InstanceId of the newly created EC2 instance
    Value: !GetAtt PerforceMasterServerInstance.Outputs.EC2InstanceId
  PerforceReplicaInstanceId:
    Condition: CreateReplicaServer
    Description: InstanceId of the newly created EC2 instance
    Value: !GetAtt PerforceReplicaServerInstance.Outputs.EC2InstanceId
