---
AWSTemplateFormatVersion: 2010-09-09
Description: 'Master manifest for ADP Dagster usecase'
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: General configuration
        Parameters:
          - ADPS3BucketName
          - ADPS3BucketRegion
          - BasePlatformVersion
          - UseCaseVersion
          - DnsZoneType
          - EnableExternalAccess
      - Label:
          default: Containers configuration
        Parameters:
          - DagsterNamespace
          - DagsterImage
          - FrontendImage
      - Label:
          default: Snowflake configuration
        Parameters:
          - SnowflakeAccount
          - SnowflakeUser
          - SnowflakePassword

Parameters:
  ADPS3BucketName:
    Type: String
    AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$
    ConstraintDescription:
      'Bucket name can include numbers, lowercase letters, and hyphens (-).
       It cannot start or end with a hyphen (-).'
    Description:
      'ADP bucket name with cloudformation scripts can include numbers,
      lowercase letters, and hyphens (-). It cannot start or end with a hyphen (-).'
    Default: 'griddynamics-analytical-data-platform-releases'
  ADPS3BucketRegion:
    Type: String
    Description: 'The AWS Region where the ADP S3 bucket (ADPS3BucketName) is hosted.'
    Default: 'us-east-1'
  BasePlatformVersion:
    Type: String
    Description: 'BasePlatform build version.'
    Default: 'ReplacementValueForBasePlatformVersion'
  UseCaseVersion:
    Type: String
    Description: 'UseCase build version.'
    Default: 'ReplaceValueForUseCaseVersion'
  EnableExternalAccess:
    Type: String
    Description:
      'Allow or deny access to UIs from outside of VPC (disables ELB for EKS-based applications).
      Disabled by default to minimize unauthorized access.'
    AllowedValues: [ "Enabled", "Disabled" ]
    Default: 'Disabled'
  DnsZoneType:
    Type: String
    Description:
      'Should match with ADP Base Platform settings. Choose public if you already delegated responsibility for the subdomain to Route 53. This subdomain
      should be configured in Route53HostedZoneName. Otherwise choose a private DNS zone.'
    AllowedValues: [ "public", "private" ]
    Default: 'private'


#Images configuration
  DagsterNamespace:
    Type: String
    Description: 'Namespace for dagster in EKS cluster'
    Default: 'dagster'
  DagsterImage:
    Type: String
    Description: 'Dagster image'
    Default: 'griddynamics/example-code-dagster'
  FrontendImage:
    Type: String
    Description: 'Frontend image'
    Default: 'griddynamics/anomaly-dashboard'

# Snowflake configuration
  SnowflakeAccount:
    Type: String
    Description: 'Snowflake account for Dagster integration'
  SnowflakeUser:
    Type: String
    Description: 'Snowflake user for Dagster integration'
  SnowflakePassword:
    Type: String
    Description: "Snowflake user's password for Dagster integration. Use with caution as it will be passed as plaintext!"

Conditions:
  RunningInAnotherRegion: !Not [!Equals [!Ref ADPS3BucketRegion, !Ref "AWS::Region"]]
  EnableExternalAccessCondition: !And
    - !Equals [!Ref DnsZoneType, 'private']
    - !Equals [!Ref EnableExternalAccess, 'Enabled']

Resources:
  BasePlatformUtils:
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'BasePlatformUtils'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l0/base/utils.yaml'
      Parameters:
        ResourcePrefix: !ImportValue ADPResourcePrefix
        ADPS3BucketName: !Sub
          - '${BucketName}'
          - BucketName: !If [RunningInAnotherRegion, !ImportValue ADPS3BucketAnotherRegion, !Ref ADPS3BucketName]
        BasePlatformVersion: !Ref BasePlatformVersion

  BasePlatformVPCOutputs:
    DependsOn: BasePlatformUtils
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformOutputsLambdaArn
      StackName: "VPCStack"
      BpStateBucket: !Sub
        - "${ResourcePrefix}-platform-state-${AWS::AccountId}"
        - ResourcePrefix: !ImportValue ADPResourcePrefix

  BasePlatformInputs:
    DependsOn: BasePlatformUtils
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformInputsLambdaArn
      BpStateBucket: !Sub
        - '${ResourcePrefix}-platform-state-${AWS::AccountId}'
        - ResourcePrefix: !ImportValue ADPResourcePrefix

  BasePlatformOutputs:
    DependsOn: BasePlatformVPCOutputs
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformOutputsLambdaArn
      BpStateBucket: !Sub
        - "${ResourcePrefix}-platform-state-${AWS::AccountId}"
        - ResourcePrefix: !ImportValue ADPResourcePrefix

  BasePlatformCloudMapOutputs:
    DependsOn: BasePlatformOutputs
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformOutputsLambdaArn
      StackName: "CloudMapStack"
      BpStateBucket: !Sub
        - "${ResourcePrefix}-platform-state-${AWS::AccountId}"
        - ResourcePrefix: !ImportValue ADPResourcePrefix

  BasePlatformKubernetes:
    DependsOn: BasePlatformOutputs
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformLambdaOperateArn
      BpStateBucket: !GetAtt BasePlatformUtils.Outputs.BasePlatformStateBucketName
      BpGdComponent: "dagster"
      BpAwsComponent: "Kubernetes"
      BpReferenceComponentName: "KubernetesStack"

  BasePlatformKubernetesExtra:
    DependsOn: BasePlatformKubernetes
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt BasePlatformUtils.Outputs.BasePlatformLambdaOperateArn
      BpStateBucket: !GetAtt BasePlatformUtils.Outputs.BasePlatformStateBucketName
      BpGdComponent: "dagster"
      BpAwsComponent: "KubernetesExtra"
      BpReferenceComponentName: "KubernetesExtraStack"


  BucketStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dagster'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l1/bigdata/apps/dagster/s3.yaml'
      Parameters:
        ResourcePrefix: !ImportValue ADPResourcePrefix
        ADPS3BucketName: !Ref ADPS3BucketName
        BasePlatformVersion: !Ref BasePlatformVersion
        BucketName: "dagster-config"

  DagsterStack:
    DependsOn: BasePlatformKubernetesExtra
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dagster'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l1/bigdata/apps/dagster/dagster.yaml'
      Parameters:
        ResourcePrefix: !ImportValue ADPResourcePrefix
        CloudMapNamespaceId: !GetAtt BasePlatformCloudMapOutputs.CloudMapNamespaceId
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        KubeClusterName: !GetAtt BasePlatformKubernetes.EKSClusterName
        KubeManifestLambdaArn: !GetAtt BasePlatformKubernetes.KubeManifestLambdaArn
        ClusterOID: !GetAtt BasePlatformKubernetes.ClusterOID
        KubeGetLambdaArn: !GetAtt BasePlatformKubernetes.KubeGetLambdaArn
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EKSNodeInstanceRoleArn: !Sub 'arn:aws:iam::${AWS::AccountId}:role/eks-quickstart-ManagedNodeInstance'
        MLEngineerGroupArn: !GetAtt BasePlatformOutputs.MLEngineerGroupArn
        BigDataEngineerGroupArn: !GetAtt BasePlatformOutputs.BigDataEngineerGroupArn
        DevOpsEngineerGroupArn: !GetAtt BasePlatformOutputs.DevOpsEngineerGroupArn
        MLEngineerGroupName: !GetAtt BasePlatformOutputs.MLEngineerGroupName
        BigDataEngineerGroupName: !GetAtt BasePlatformOutputs.BigDataEngineerGroupName
        DevOpsEngineerGroupName: !GetAtt BasePlatformOutputs.DevOpsEngineerGroupName
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType
        Route53HostedZoneName: !GetAtt BasePlatformInputs.Route53HostedZoneName
        DockerRegistry: !ImportValue ADPDockerRegistry
        DagsterImage: !Ref DagsterImage
        DagsterNamespace: !Ref DagsterNamespace
        SnowflakeAccount: !Ref SnowflakeAccount
        SnowflakeUser: !Ref SnowflakeUser
        SnowflakePassword: !Ref SnowflakePassword
        S3BucketName: !GetAtt BucketStack.Outputs.S3BucketName

  InfluxStack:
    DependsOn: BasePlatformKubernetesExtra
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dagster'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l1/bigdata/apps/dagster/influxdb.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        ClusterOID: !GetAtt BasePlatformKubernetes.ClusterOID
        CloudMapNamespaceId: !GetAtt BasePlatformCloudMapOutputs.CloudMapNamespaceId
        DagsterNamespace: !Ref DagsterNamespace
        DnsZoneType: !Ref DnsZoneType
        EnableExternalAccess: !Ref EnableExternalAccess
        KubeClusterName: !GetAtt BasePlatformKubernetes.EKSClusterName
        KubeGetLambdaArn: !GetAtt BasePlatformKubernetes.KubeGetLambdaArn
        KubeManifestLambdaArn: !GetAtt BasePlatformKubernetes.KubeManifestLambdaArn
        ResourcePrefix: !ImportValue ADPResourcePrefix
        Route53HostedZoneName: !GetAtt BasePlatformInputs.Route53HostedZoneName

  FrontendStack:
    DependsOn: BasePlatformKubernetesExtra
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dagster'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l1/bigdata/apps/dagster/frontend.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        ClusterOID: !GetAtt BasePlatformKubernetes.ClusterOID
        CloudMapNamespaceId: !GetAtt BasePlatformCloudMapOutputs.CloudMapNamespaceId
        DagsterNamespace: !Ref DagsterNamespace
        DnsZoneType: !Ref DnsZoneType
        EnableExternalAccess: !Ref EnableExternalAccess
        KubeClusterName: !GetAtt BasePlatformKubernetes.EKSClusterName
        KubeGetLambdaArn: !GetAtt BasePlatformKubernetes.KubeGetLambdaArn
        KubeManifestLambdaArn: !GetAtt BasePlatformKubernetes.KubeManifestLambdaArn
        ResourcePrefix: !ImportValue ADPResourcePrefix
        Route53HostedZoneName: !GetAtt BasePlatformInputs.Route53HostedZoneName
        UseCaseVersion: !Ref UseCaseVersion
        DockerRegistry: !ImportValue ADPDockerRegistry
        DockerImage: !Ref FrontendImage
        InfluxUrl: !GetAtt DagsterStack.Outputs.DagsterELB


Outputs:
  DagsterELB:
    Condition: EnableExternalAccessCondition
    Description: 'Dagster service ELB address'
    Value: !GetAtt DagsterStack.Outputs.DagsterELB

  DagsterFQDN:
    Description: 'Dagster service DNS address'
    Value: !GetAtt DagsterStack.Outputs.DagsterFQDN

  InfluxELB:
    Condition: EnableExternalAccessCondition
    Description: 'Influx service ELB address'
    Value: !GetAtt InfluxStack.Outputs.InfluxELB

  InfluxFQDN:
    Description: 'Influx service DNS address'
    Value: !GetAtt InfluxStack.Outputs.InfluxFQDN

  FrontendELB:
    Condition: EnableExternalAccessCondition
    Description: 'Frontend service ELB address'
    Value: !GetAtt FrontendStack.Outputs.FrontendELB

  FrontendFQDN:
    Description: 'Frontend service DNS address'
    Value: !GetAtt FrontendStack.Outputs.FrontendFQDN
