AWSTemplateFormatVersion: "2010-09-09"

Description: Multi-tenant Amazon Aurora MySQL with RDS Proxy and an optional load test (uksb-1rkqqff0c).

Metadata:
  Version: 0.0.9

  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Region configuration
        Parameters:
          - AvailabilityZones
      - Label:
          default: Main configuration
        Parameters:
          - DBReaderInstanceClass
          - DBWriterInstanceClass
          - PerformanceInsightsRetentionPeriod
          - LambdaRuntimeEnv
          - Environment
          - EnableFlowLogs
      - Label:
          default: Load test configuration
        Parameters:
          - CreateLoadTest
          - UsersToCreate
          - LocustAmiId
          - LocustInstanceType
          - LocustVersion
          - LocustSecondaryInstanceCapacity
          - ApiEndpointType
          - CIDRRange
    ParameterLabels:
      AvailabilityZones:
        default: Availability Zones
      DBReaderInstanceClass:
        default: Database Reader Instance Class
      DBWriterInstanceClass:
        default: Database Writer Instance Class
      PerformanceInsightsRetentionPeriod:
        default: Performance Insights Retention Period
      LambdaRuntimeEnv:
        default: Lambda Runtime Environment
      Environment:
        default: Infrastructure Environment
      CreateLoadTest:
        default: Create Load Test Stack
      UsersToCreate:
        default: Number of Tenants to Create
      LocustAmiId:
        default: Latest Amazon Linux AMI
      LocustInstanceType:
        default: Locust Instance Type
      LocustVersion:
        default: Locust App Version
      LocustSecondaryInstanceCapacity:
        default: Locust Worker Instances
      ApiEndpointType:
        default: API Endpoint Type
      CIDRRange:
        default: ISP/Public IPv4
      EnableFlowLogs:
        default: Flow Logs

Parameters:
  CreateLoadTest:
    Description: If False, this creates a Proxy VPC and accompanying reosurces. If True, this additionally creates a Load Test VPC, No Proxy VPC, and accompanying reosurces, in order to run a load test and compare metrics between the Proxy and No Proxy VPCs.
    Type: String
    AllowedValues:
      - false
      - true
    Default: true
    ConstraintDescription: Must specify 'true' or 'false'

  UsersToCreate:
    Description: The number of tenants to create in the Proxy and No Proxy VPC Aurora clusters. Each tenant has their own dedicated database containing dummy data. Allowed values are 1-200.
    Type: String
    Default: 200
    AllowedPattern: ^(20[0]|1[0-9][0-9]|[1-9]?[1-9])$
    ConstraintDescription: This parameter must be in the range 1-200

  AvailabilityZones:
    Description: The list of Availability Zones to use for the subnets in the VPCs. Select two Availability Zones from the list.
    Type: List<AWS::EC2::AvailabilityZone::Name>

  DBReaderInstanceClass:
    Description: The database instance class for the Proxy and No Proxy VPC Amazon Aurora Replicas, for example db.m5.large.
    Type: String
    Default: db.r5.large
    MinLength: 6

  DBWriterInstanceClass:
    Description: The database instance class for the Proxy and No Proxy VPC Amazon Aurora Writer, for example db.m5.large.
    Type: String
    Default: db.t3.medium
    MinLength: 6

  PerformanceInsightsRetentionPeriod:
    Description: The amount of time, in days, to retain RDS Performance Insights data. Valid values are 7 and 731 (2 years).
    Type: String
    AllowedValues:
      - 7
      - 731
    Default: 7

  LambdaRuntimeEnv:
    Description: The runtime for the Lambda access function. Valid values are (Python, Nodejs).
    Type: String
    AllowedValues:
      - Python
      - Nodejs
    Default: Nodejs

  LocustAmiId:
    Description: The latest Amazon Linux AMI from AWS Systems Manager Parameter Store.
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

  LocustInstanceType:
    Description: The Amazon EC2 instance type used in the Load Test VPC that runs Locust.
    Type: String
    Default: c5.large
    MinLength: 6

  LocustVersion:
    Description: The Locust version to deploy.
    Type: String
    Default: latest
    MinLength: 1

  LocustSecondaryInstanceCapacity:
    Description: The number of secondary Amazon EC2s for the Load Test Cluster. Allowed values are 2-20.
    Type: String
    Default: 2
    AllowedPattern: ^(20|[2-9]|1[0-9])$
    ConstraintDescription: This parameter must be in the range 2-20
    MinLength: 1

  ApiEndpointType:
    Description: The Amazon API Gateway endpoint type. Valid values are (EDGE, REGIONAL, PRIVATE).
    Type: String
    AllowedValues:
      - EDGE
      - REGIONAL
      - PRIVATE
    Default: PRIVATE

  CIDRRange:
    Description: The CIDR block or your IP address that you will use to connect to the Locust Dashboard (e.g. 192.168.192.168/32). This limits the CIDR range from which the Locust dashboard can be accessed. You can use an open CIDR range (e.g. 0.0.0.0/0) to access from anywhere, but this is not recommended.
    Type: String
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/0-32
    MinLength: 1

  Environment:
    Description: The type of environment with which to tag your infrastructure. Valid values are DEV (development), TEST (test), or PROD (production).
    Type: String
    AllowedValues:
      - DEV
      - TEST
      - PROD
    Default: DEV

  EnableFlowLogs:
    Description: Creates an optional CloudWatch Logs group to send the VPC flow logs to. Flow Logs incur additional costs. Set to "false" to disable.
    Type: String
    AllowedValues:
      - true
      - false
    Default: false

Mappings:
  StackMap:
    ProxyMap:
      VPCCidr: 10.0.0.0/16
      PublicSubnet1Cidr: 10.0.0.0/24
      PublicSubnet2Cidr: 10.0.1.0/24
      PrivateSubnet1Cidr: 10.0.2.0/24
      PrivateSubnet2Cidr: 10.0.3.0/24
      ResourceTags: rds-proxy
      CreateRDSProxy: true
    NoProxyMap:
      VPCCidr: 10.1.0.0/16
      PublicSubnet1Cidr: 10.1.0.0/24
      PublicSubnet2Cidr: 10.1.1.0/24
      PrivateSubnet1Cidr: 10.1.2.0/24
      PrivateSubnet2Cidr: 10.1.3.0/24
      ResourceTags: rds-no-proxy
      CreateRDSProxy: false
    LoadTestMap:
      VPCCidr: 10.2.0.0/16
      PublicSubnet1Cidr: 10.2.0.0/24
      PublicSubnet2Cidr: 10.2.1.0/24
      PrivateSubnet1Cidr: 10.2.2.0/24
      PrivateSubnet2Cidr: 10.2.3.0/24
      ResourceTags: rds-load-test

Conditions:
  IsLoadTest: !Equals [!Ref CreateLoadTest, true]

  IsPython: !Equals [!Ref LambdaRuntimeEnv, Python]

Resources:
  ProxyVPCStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: vpc.template
      Parameters:
        AvailabilityZones: !Join [',', !Ref AvailabilityZones]
        VPCCidr: !FindInMap [StackMap, ProxyMap, VPCCidr]
        PublicSubnet1Cidr: !FindInMap [StackMap, ProxyMap, PublicSubnet1Cidr]
        PublicSubnet2Cidr: !FindInMap [StackMap, ProxyMap, PublicSubnet2Cidr]
        PrivateSubnet1Cidr: !FindInMap [StackMap, ProxyMap, PrivateSubnet1Cidr]
        PrivateSubnet2Cidr: !FindInMap [StackMap, ProxyMap, PrivateSubnet2Cidr]
        ResourceTags: !FindInMap [StackMap, ProxyMap, ResourceTags]
        EnableFlowLogs: !Ref EnableFlowLogs
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, ProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment

  NoProxyVPCStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: vpc.template
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        VPCCidr: !FindInMap [StackMap, NoProxyMap, VPCCidr]
        PublicSubnet1Cidr: !FindInMap [StackMap, NoProxyMap, PublicSubnet1Cidr]
        PublicSubnet2Cidr: !FindInMap [StackMap, NoProxyMap, PublicSubnet2Cidr]
        PrivateSubnet1Cidr: !FindInMap [StackMap, NoProxyMap, PrivateSubnet1Cidr]
        PrivateSubnet2Cidr: !FindInMap [StackMap, NoProxyMap, PrivateSubnet2Cidr]
        ResourceTags: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        EnableFlowLogs: !Ref EnableFlowLogs
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  LoadTestVPCStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: vpc.template
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        VPCCidr: !FindInMap [StackMap, LoadTestMap, VPCCidr]
        PublicSubnet1Cidr: !FindInMap [StackMap, LoadTestMap, PublicSubnet1Cidr]
        PublicSubnet2Cidr: !FindInMap [StackMap, LoadTestMap, PublicSubnet2Cidr]
        PrivateSubnet1Cidr: !FindInMap [StackMap, LoadTestMap, PrivateSubnet1Cidr]
        PrivateSubnet2Cidr: !FindInMap [StackMap, LoadTestMap, PrivateSubnet2Cidr]
        ResourceTags: !FindInMap [StackMap, LoadTestMap, ResourceTags]
        EnableFlowLogs: !Ref EnableFlowLogs
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, LoadTestMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  ProxyRDSStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: rds.template
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        VpcID: !GetAtt ProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet2
        DBReaderInstanceClass: !Ref DBReaderInstanceClass
        DBWriterInstanceClass: !Ref DBWriterInstanceClass
        PerformanceInsightsRetentionPeriod: !Ref PerformanceInsightsRetentionPeriod
        CreateRDSProxy: !FindInMap [StackMap, ProxyMap, CreateRDSProxy]
        LayerVersionArn: !GetAtt ProxyLayerVersionStack.Outputs.PythonLambdaLayer
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, ProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment

  NoProxyRDSStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: rds.template
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        VpcID: !GetAtt NoProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet2
        DBReaderInstanceClass: !Ref DBReaderInstanceClass
        DBWriterInstanceClass: !Ref DBWriterInstanceClass
        PerformanceInsightsRetentionPeriod: !Ref PerformanceInsightsRetentionPeriod
        CreateRDSProxy: !FindInMap [StackMap, NoProxyMap, CreateRDSProxy]
        LayerVersionArn: !GetAtt ProxyLayerVersionStack.Outputs.PythonLambdaLayer
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  ProxyLayerVersionStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: lambda-layer.template
      Parameters:
        LambdaRuntimeEnv: !Ref LambdaRuntimeEnv
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, ProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment

  NoProxyLayerVersionStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: lambda-layer.template
      Parameters:
        LambdaRuntimeEnv: !Ref LambdaRuntimeEnv
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  ProxyAccessStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: access-function.template
      Parameters:
        VpcID: !GetAtt ProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet2
        LambdaRuntimeEnv: !Ref LambdaRuntimeEnv
        LayerVersionArn: !If
          - IsPython
          - !GetAtt ProxyLayerVersionStack.Outputs.PythonLambdaLayer
          - !GetAtt ProxyLayerVersionStack.Outputs.NodeJsLambdaLayer
        Endpoint: !GetAtt ProxyRDSStack.Outputs.ProxyEndpoint
        RDSSecurityGroup: !GetAtt ProxyRDSStack.Outputs.RDSSecurityGroup
        ProxySecurityGroup: !GetAtt ProxyRDSStack.Outputs.ProxySecurityGroup
        CreateRDSProxy: !FindInMap [StackMap, ProxyMap, CreateRDSProxy]
        ClusterEndpointResourceId: !GetAtt ProxyRDSStack.Outputs.ClusterEndpointResourceId
        SSLCertURL: https://www.amazontrust.com/repository/AmazonRootCA1.pem
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, ProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment

  NoProxyAccessStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: access-function.template
      Parameters:
        VpcID: !GetAtt NoProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet2
        LambdaRuntimeEnv: !Ref LambdaRuntimeEnv
        LayerVersionArn: !If
          - IsPython
          - !GetAtt NoProxyLayerVersionStack.Outputs.PythonLambdaLayer
          - !GetAtt NoProxyLayerVersionStack.Outputs.NodeJsLambdaLayer
        Endpoint: !GetAtt NoProxyRDSStack.Outputs.ClusterReaderEndpoint
        RDSSecurityGroup: !GetAtt NoProxyRDSStack.Outputs.RDSSecurityGroup
        ProxySecurityGroup: NA
        CreateRDSProxy: !FindInMap [StackMap, NoProxyMap, CreateRDSProxy]
        ClusterEndpointResourceId: !GetAtt NoProxyRDSStack.Outputs.ClusterEndpointResourceId
        SSLCertURL: !Sub https://truststore.pki.rds.amazonaws.com/${AWS::Region}/${AWS::Region}-bundle.pem
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  ProxyAddUsersStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: add-users.template
      Parameters:
        VpcID: !GetAtt ProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt ProxyVPCStack.Outputs.PrivateSubnet2
        LayerVersionArn: !GetAtt ProxyLayerVersionStack.Outputs.PythonLambdaLayer
        Endpoint: !GetAtt ProxyRDSStack.Outputs.ClusterEndpoint
        RDSSecurityGroup: !GetAtt ProxyRDSStack.Outputs.RDSSecurityGroup
        CreateRDSProxy: !FindInMap [StackMap, ProxyMap, CreateRDSProxy]
        ProxySecurityGroup: !GetAtt ProxyRDSStack.Outputs.ProxySecurityGroup
        DBSecretArn: !GetAtt ProxyRDSStack.Outputs.DBSecret
        DBProxyName: !GetAtt ProxyRDSStack.Outputs.DBProxyName
        DBProxyArn: !GetAtt ProxyRDSStack.Outputs.DBProxyArn
        UsersToCreate: !Ref UsersToCreate
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, ProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  NoProxyAddUsersStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: add-users.template
      Parameters:
        VpcID: !GetAtt NoProxyVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt NoProxyVPCStack.Outputs.PrivateSubnet2
        LayerVersionArn: !GetAtt NoProxyLayerVersionStack.Outputs.PythonLambdaLayer
        Endpoint: !GetAtt NoProxyRDSStack.Outputs.ClusterEndpoint
        RDSSecurityGroup: !GetAtt NoProxyRDSStack.Outputs.RDSSecurityGroup
        ProxySecurityGroup: NA
        CreateRDSProxy: !FindInMap [StackMap, NoProxyMap, CreateRDSProxy]
        DBSecretArn: !GetAtt NoProxyRDSStack.Outputs.DBSecret
        DBProxyName: NA
        DBProxyArn: NA
        UsersToCreate: !Ref UsersToCreate
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, NoProxyMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  DashboardStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: dashboard.template
      Parameters:
        ProxyAccessLambda: !If
          - IsPython
          - !GetAtt ProxyAccessStack.Outputs.PythonFunction
          - !GetAtt ProxyAccessStack.Outputs.NodeJsFunction
        NoProxyAccessLambda: !If
          - IsPython
          - !GetAtt NoProxyAccessStack.Outputs.PythonFunction
          - !GetAtt NoProxyAccessStack.Outputs.NodeJsFunction
        ProxyClusterName: !GetAtt ProxyRDSStack.Outputs.DBClusterName
        NoProxyClusterName: !GetAtt NoProxyRDSStack.Outputs.DBClusterName
        DBProxyName: !GetAtt ProxyRDSStack.Outputs.DBProxyName
        ApiGatewayName: !GetAtt ApiStack.Outputs.ApiGatewayName
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, LoadTestMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  LocustStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: ec2.template
      Parameters:
        VpcCidrBlock: !GetAtt LoadTestVPCStack.Outputs.VpcCidrBlock
        VpcID: !GetAtt LoadTestVPCStack.Outputs.VpcID
        SubnetID: !GetAtt LoadTestVPCStack.Outputs.PublicSubnet1
        InstanceAMI: !Ref LocustAmiId
        InstanceType: !Ref LocustInstanceType
        LocustVersion: !Ref LocustVersion
        SecondaryInstanceCapacity: !Ref LocustSecondaryInstanceCapacity
        CIDRRange: !Ref CIDRRange
        UsersToCreate: !Ref UsersToCreate
        VPCEndpointSecurityGroup: !GetAtt ApiStack.Outputs.VPCEndpointSecurityGroup
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, LoadTestMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

  ApiStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: api.template
      Parameters:
        VpcCidrBlock: !GetAtt LoadTestVPCStack.Outputs.VpcCidrBlock
        VpcID: !GetAtt LoadTestVPCStack.Outputs.VpcID
        PrivateSubnet1: !GetAtt LoadTestVPCStack.Outputs.PrivateSubnet1
        PrivateSubnet2: !GetAtt LoadTestVPCStack.Outputs.PrivateSubnet2
        ProxyAccessLambda: !If
          - IsPython
          - !GetAtt ProxyAccessStack.Outputs.PythonFunction
          - !GetAtt ProxyAccessStack.Outputs.NodeJsFunction
        NoProxyAccessLambda: !If
          - IsPython
          - !GetAtt NoProxyAccessStack.Outputs.PythonFunction
          - !GetAtt NoProxyAccessStack.Outputs.NodeJsFunction
        ApiEndpointType: !Ref ApiEndpointType
      Tags:
        - Key: Project
          Value: !FindInMap [StackMap, LoadTestMap, ResourceTags]
        - Key: Environment
          Value: !Ref Environment
    Condition: IsLoadTest

Outputs:
  LocustAddress:
    Description: The address of the Locust primary instance.
    Value: !GetAtt LocustStack.Outputs.LocustAddress
    Condition: IsLoadTest

  APIGatewayURL:
    Description: URL of the API Gateway.
    Value: !GetAtt ApiStack.Outputs.ApiGatewayURL
    Condition: IsLoadTest

  ProxyLambdaName:
    Description: Proxy tenant data access lambda function.
    Value: !If
      - IsPython
      - !GetAtt ProxyAccessStack.Outputs.PythonFunction
      - !GetAtt ProxyAccessStack.Outputs.NodeJsFunction

  NoProxyLambdaName:
    Description: NoProxy tenant data access lambda function.
    Value: !If
      - IsPython
      - !GetAtt NoProxyAccessStack.Outputs.PythonFunction
      - !GetAtt NoProxyAccessStack.Outputs.NodeJsFunction
    Condition: IsLoadTest

  ProxyAuroraReplica1:
    Description: Proxy Aurora replica 1.
    Value: !GetAtt ProxyRDSStack.Outputs.AuroraReplicaName1

  NoProxyAuroraReplica1:
    Description: NoProxy Aurora replica 1.
    Value: !GetAtt NoProxyRDSStack.Outputs.AuroraReplicaName1
    Condition: IsLoadTest

  ProxyAuroraReplica2:
    Description: Proxy Aurora replica 2.
    Value: !GetAtt ProxyRDSStack.Outputs.AuroraReplicaName2

  NoProxyAuroraReplica2:
    Description: NoProxy Aurora replica 2.
    Value: !GetAtt NoProxyRDSStack.Outputs.AuroraReplicaName2
    Condition: IsLoadTest

  DashboardName:
    Description: CLoudWatch dashboard.
    Value: !GetAtt DashboardStack.Outputs.LoadTestDashboard
    Condition: IsLoadTest

  APIGatewayLogGroupName:
    Description: The CloudWatch Group for load test API Gateway.
    Value: !GetAtt ApiStack.Outputs.APIGatewayLogGroupName
    Condition: IsLoadTest