AWSTemplateFormatVersion: 2010-09-09
Description: 'Master manifest with cases for ADP Platform'
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: General configuration
        Parameters:
          - ADPS3BucketName
          - ADPS3BucketRegion
          - BasePlatformVersion
          - UseCaseVersion
          - DnsZoneType
          - EnableExternalAccess
      - Label:
          default: Use cases configuration
        Parameters:
          - BatchProcessing
          - DataQuality
          - DataGovernance
          - Streaming
          - Dashboard
          - MlObservability
          - PromotionPlanning
          - VisualAttributes
          - MlOps
          - SemanticLayer
      - Label:
          default: Batch configuration
        Parameters:
          - BatchInputPath
          - ItemPropertiesInputPath
      - Label:
          default: Streaming configuration
        Parameters:
          - InputFilePath
      - Label:
          default: General configurations for cases Promotion Planning, Visual Attributes, MlOps
        Parameters:
          - NotebookInstanceType
          - MlModelDockerImage
          - MlflowServiceDockerImage
          - MlflowExperimentDockerImage
          - CleanupEpLambdaDockerImage
      - Label:
          default: Ml Observability configuration
        Parameters:
          - NannymlDockerImage
          - EventBridgeState
          - EventBridgeScheduleExpression
          - DeltaMinutes
          - EstimatorKey
      - Label:
          default: Promotion Planning configuration
        Parameters:
          - DatasetBucket
          - PPUseKubernetesModel
          - PPUseSagemakerModel
          - GitHubRepositoryPP
          - PPUIDockerImage
          - MlflowLambdaDockerImage
      - Label:
          default: Visual Attributes configuration
        Parameters:
          - PytorchModelsBucket
          - GitHubRepositoryVA
          - VADockerImage
          - VAInitLambdaDockerImage
      - Label:
          default: MlOps configuration
        Parameters:
          - MlOpsUseKubernetesModel
          - MlOpsUseSagemakerModel
          - DeployUsingCodeBuild
          - DeployUsingLambda
          - GitHubRepositoryMlOps
          - CPDockerImage
          - MlLambdaDockerImage
          - RepositoryID
          - BranchName
          - GitConnectionName
      - Label:
          default: Semantic Layer configuration
        Parameters:
          - SLDashboardDockerImage
          - CacheBucketName
          - ExportBucketName
          - CubeSchemasBucketName
          - SqlApiUser
          - CubeNamespace

Parameters:
#  General Configuration
  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: '1.3.1-marketplace'
  UseCaseVersion:
    Type: String
    Description: 'UseCase build version.'
    Default: '1.3.1-marketplace'
  DnsZoneType:
    Type: String
    Description:
      '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 to be created in Route 53.'
    AllowedValues: [ "public", "private" ]
    Default: 'private'
  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'

#    Use cases configuration
  BatchProcessing:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  DataQuality:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  DataGovernance:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  Streaming:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  Dashboard:
    Type: String
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Disabled'
  MlObservability:
    Type: String
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Disabled'
  PromotionPlanning:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  VisualAttributes:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  MlOps:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'
  SemanticLayer:
    Type: String
    AllowedValues: ['Enabled', 'Disabled']
    Default: 'Disabled'

# Batch configuration
  BatchInputPath:
    Type: String
    Description: 'Input file for aws_analytical_batch_process dag.'
    Default: 'griddynamics-analytical-data-platform-releases/input/batch/transaction-events.csv'
  ItemPropertiesInputPath:
    Type: String
    Description: 'Input file for aws_item_properties_batch_process dag.'
    Default: 'griddynamics-analytical-data-platform-releases/input/batch/item_properties/*'

# Streaming configuratuin
  InputFilePath:
    Type: String
    Description: 'Input file for Batch pipeline use case.'
    Default: 's3://griddynamics-analytical-data-platform-releases/input/stream/part-of-transaction-events.csv'

# ML observability configuration
  NannymlDockerImage:
    Type: String
    Description: 'Container path in the registry. ECR must have been created before. Default values provided as example.'
    Default: "grid-dynamics/adp-nannyml"
  EventBridgeState:
    Type: String
    Description: 'Defines whether EventBridge is enabled or not'
    Default: 'ENABLED'
    AllowedValues: ['ENABLED', 'DISABLED']
  EventBridgeScheduleExpression:
    Type: String
    Description: 'Defines schedule for EventBridge'
    Default: "rate(5 minutes)"
  DeltaMinutes:
    Type: String
    Description: 'Period for which requests will be analysed'
    Default: '5'
  EstimatorKey:
    Type: String
    Description: 'File path for estimator in the bucket'
    Default: 'nannyml/estimators/new_dle.pkl'

# General configurations for cases Promotion Planning, Visual Attributes, MlOps
  NotebookInstanceType:
    Type: String
    Description: 'The EC2 instance type for the Amazon SageMaker Notebook instance (Promotion Planning, Visual Attributes, MlOps, Ml Observability).'
    ConstraintDescription: 'Must select a valid Notebook instance type'
    AllowedValues:
      - ml.t2.medium
      - ml.t2.large
      - ml.t2.xlarge
      - ml.t3.medium
      - ml.t3.large
    Default: 'ml.t3.large'
  MlModelDockerImage:
    Type: String
    Description: 'Docker image name for Ml Model service'
    Default: 'grid-dynamics/adp-deployment-model'
  MlflowServiceDockerImage:
    Type: String
    Description: 'Enter your path of image. Repository should be created before starting this cases'
    Default: 'griddynamics/adp-mlflow-churn-predictions'
  MlflowExperimentDockerImage:
    Type: String
    Description: 'Docker image name for MlflowExperiment lambda'
    Default: 'grid-dynamics/adp-mlflowexperiment'
  CleanupEpLambdaDockerImage:
    Type: String
    Description: 'Docker image name for Cleanup Sagemaker Endpoint Lambda'
    Default: 'grid-dynamics/adp-cleanup-ep-lambda'

# Promotion Planning configuration
  GitHubRepositoryPP:
    Type: String
    Description: '[OPTIONAL] The Git repository associated with the notebook instance as its default code repository'
    Default: ''
  PPUseKubernetesModel:
    Type: String
    Description: 'If this item is enabled, then PPUseSagemakerModel must be disabled'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Disabled'
  PPUseSagemakerModel:
    Type: String
    Description: 'If this item is enabled, then PPUseKubernetesModel must be disabled'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Enabled'
  DatasetBucket:
    Type: String
    Description: 'An existing S3 bucket where Promotion planning dataset is located.'
    Default: ''
  PPUIDockerImage:
    Type: String
    Description: 'Docker image name for Promotion Planning UI service'
    Default: 'grid-dynamics/adp-ui-promotion-planning'
  MlflowLambdaDockerImage:
    Type: String
    Description: 'Docker image name for Promotion Planning Mlflow lambda'
    Default: 'grid-dynamics/adp-ppmlflowlambda'

# Visual Attributes configuration
  PytorchModelsBucket:
    Type: String
    Description: 'Path to Visual Attributes PyTorch Models bucket'
    Default: 'adp-rnd-ml-models/visual-attribution/pytorch-models-casted'
  GitHubRepositoryVA:
    Type: String
    Description: '[OPTIONAL] The Git repository associated with the notebook instance as its default code repository'
    Default: ''
  VADockerImage:
    Type: String
    Description: 'Docker image name for Visual Attributes service'
    Default: 'grid-dynamics/adp-visual-attributes'
  VAInitLambdaDockerImage:
    Type: String
    Description: 'Docker image name for Visual Attributes lambda'
    Default: 'grid-dynamics/adp-vainit-lambda'

# MlOps configuration
  MlOpsUseKubernetesModel:
    Type: String
    Description: '[WARNING] If this item is enabled, then MlOpsUseSagemakerModel must be disabled'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Disabled'
  MlOpsUseSagemakerModel:
    Type: String
    Description: '[WARNING] If this item is enabled, then MlOpsUseKubernetesModel must be disabled'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Enabled'
  DeployUsingCodeBuild:
    Type: String
    Description: '[WARNING] Should match with DeployUsingLambda parameter. If parameter DeployUsingLambda was enabled, then this parameter must be disabled!'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Disabled'
  DeployUsingLambda:
    Type: String
    Description: '[WARNING] Should match with DeployUsingCodeBuild parameter. If parameter DeployUsingCodeBuild was enabled, then this parameter must be disabled!'
    AllowedValues: [ 'Enabled', 'Disabled' ]
    Default: 'Enabled'
  BranchName:
    Type: String
    Description: '[If DeployUsingCodeBuild enabled] The name of the branch for the repository where the source change was made'
    Default: 'main'
  RepositoryID:
    Type: String
    Description: '[If DeployUsingCodeBuild enabled] The owner and name of the repository where source changes are to be detected. For example, griddynamics/test'
    Default: ''
  GitConnectionName:
    Type: String
    Description: '[If DeployUsingCodeBuild enabled] The name of the connection. Connection names must be unique in an AWS user account. MaxLength of name - 32.'
    Default: 'MlflowGHConnection'
    MaxLength: '32'
  GitHubRepositoryMlOps:
    Type: String
    Description: '[OPTIONAL] The Git repository associated with the notebook instance as its default code repository'
    Default: ''
  CPDockerImage:
    Type: String
    Description: 'Docker image name for Churn Prediction service'
    Default: 'grid-dynamics/adp-ui-churn-predictions'
  MlLambdaDockerImage:
    Type: String
    Description: 'Docker image name for Ml lambda'
    Default: 'grid-dynamics/adp-mllambda'

# Semantic Layer configuration
  SLDashboardDockerImage:
    Type: String
    Description: 'Docker image name for Semantic Layer dashboard'
    Default: 'griddynamics/semantic-dashboard'
  CacheBucketName: 
    Type: String
    Description: ''
    Default: 'caching'
  ExportBucketName: 
    Type: String
    Description: ''
    Default: 'exporting'
  CubeSchemasBucketName: 
    Type: String
    Description: ''
    Default: 'schemas'
  SqlApiUser: 
    Type: String
    Description: ''
    Default: 'sqlapiuser'
  CubeNamespace:
    Type: String
    Description: ''
    Default: 'cube'

Conditions:
#  Use cases conditions
  EnableBatch: !Equals [ !Ref BatchProcessing, 'Enabled' ]
  EnableDataQuality: !Equals [ !Ref DataQuality, 'Enabled' ]
  EnableDataGovernance: !Equals [ !Ref DataGovernance, 'Enabled' ]
  EnableStreaming: !Equals [ !Ref Streaming, 'Enabled' ]
  EnableDashboard: !Equals [ !Ref Dashboard, 'Enabled' ]
  EnableMlObservability: !Equals [ !Ref MlObservability, 'Enabled' ]
  EnablePromotionPlanning: !Equals [ !Ref PromotionPlanning, 'Enabled' ]
  EnableVisualAttributes: !Equals [ !Ref VisualAttributes, 'Enabled' ]
  EnableMlOps: !Equals [ !Ref MlOps, 'Enabled' ]
  EnableSemanticLayer: !Equals [ !Ref SemanticLayer, 'Enabled' ]

# Access conditions
  EnableExternalAccessCondition: !And
    - !Equals [!Ref DnsZoneType, 'private']
    - !Equals [!Ref EnableExternalAccess, 'Enabled']

#  Output conditions
  EnabledKubernetes: !Or
    - !Condition EnableBatch
    - !Condition EnableDataQuality
    - !Condition EnableDataGovernance
    - !Condition EnableStreaming
    - !Condition EnableDashboard
    - !Condition EnablePromotionPlanning
    - !Condition EnableVisualAttributes
    - !Condition EnableMlOps
  EnabledAirflow: !Or
    - !Condition EnableBatch
    - !Condition EnableDataQuality
    - !Condition EnableDataGovernance
    - !Condition EnableStreaming
  AirflowELB: !And
    - !Condition EnabledAirflow
    - !Condition EnableExternalAccessCondition
  EnabledAtlas: !Or
    - !Condition EnableDataGovernance
    - !Condition EnableDataQuality
  AtlasELB: !And
    - !Condition EnabledAtlas
    - !Condition EnableExternalAccessCondition
  EnabledElasticSearch: !Or
    - !Condition EnableDashboard
    - !Condition EnableDataGovernance
    - !Condition EnableDataQuality
  ElasticSearchELB: !And
    - !Condition EnabledElasticSearch
    - !Condition EnableExternalAccessCondition
  EnabledKibana: !Or
    - !Condition EnableDashboard
    - !Condition EnableDataQuality
  KibanaELB: !And
    - !Condition EnabledKibana
    - !Condition EnableExternalAccessCondition
  PromotionPlanningELB: !And
    - !Condition EnablePromotionPlanning
    - !Condition EnableExternalAccessCondition
  VisualAttributesELB: !And
    - !Condition EnableVisualAttributes
    - !Condition EnableExternalAccessCondition
  EnabledMlflow: !Or
    - !Condition EnableVisualAttributes
    - !Condition EnablePromotionPlanning
    - !Condition EnableMlOps
  MlflowELB: !And
    - !Condition EnabledMlflow
    - !Condition EnableExternalAccessCondition
  MlopsELB: !And
    - !Condition EnableMlOps
    - !Condition EnableExternalAccessCondition
  SemanticLayerELB: !And
    - !Condition EnableSemanticLayer
    - !Condition EnableExternalAccessCondition
  UsingCodeBuild: !Equals [ !Ref DeployUsingCodeBuild, 'Enabled' ]

Resources:
  BatchStack:
    Condition: EnableBatch
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Batch'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-batch-processing.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        BatchInputPath: !Ref BatchInputPath
        ItemPropertiesInputPath: !Ref ItemPropertiesInputPath

  DataQualityStack:
    Condition: EnableDataQuality
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'DataQuality'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-dataquality-2.0.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType

  DataGovernanceStack:
    Condition: EnableDataGovernance
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'DataGovernance'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-datagovernance.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType

  StreamingStack:
    Condition: EnableStreaming
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Streaming'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-streaming.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        InputFilePath: !Ref InputFilePath

  DashboardStack:
    Condition: EnableDashboard
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dashboard'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-analytics-dashboard.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType

  MlObservabilityStack:
    Condition: EnableMlObservability
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'Dashboard'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-observability.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        NotebookInstanceType: !Ref NotebookInstanceType
        NannymlDockerImage: !Ref NannymlDockerImage
        EventBridgeState: !Ref EventBridgeState
        EventBridgeScheduleExpression: !Ref EventBridgeScheduleExpression
        DeltaMinutes: !Ref DeltaMinutes
        EstimatorKey: !Ref EstimatorKey

  PromotionPlanningStack:
    Condition: EnablePromotionPlanning
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'PromotionPlanning'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-promotion-planning.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType
        DatasetBucket: !Ref DatasetBucket
        UseKubernetesModel: !Ref PPUseKubernetesModel
        UseSagemakerModel: !Ref PPUseSagemakerModel
        DockerRegistry: !ImportValue ADPDockerRegistry
        DockerPPUIImage: !Ref PPUIDockerImage
        DockerMlModelImage: !Ref MlModelDockerImage
        MlflowExperimentDockerImage: !Ref MlflowExperimentDockerImage
        MlflowServiceImageRepository: !Ref MlflowServiceDockerImage
        CleanupEpLambdaDockerImage: !Ref CleanupEpLambdaDockerImage
        MlflowLambdaDockerImage: !Ref MlflowLambdaDockerImage
        NotebookInstanceType: !Ref NotebookInstanceType
        GitHubRepository: !Ref GitHubRepositoryPP

  VisualAttributesStack:
    Condition: EnableVisualAttributes
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'VisualAttributes'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-visual-attributes.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType
        PytorchModelsBucket: !Ref PytorchModelsBucket
        DockerVAImage: !Ref VADockerImage
        DockerRegistry: !ImportValue ADPDockerRegistry
        MlflowServiceImageRepository: !Ref MlflowServiceDockerImage
        NotebookInstanceType: !Ref NotebookInstanceType
        GitHubRepository: !Ref GitHubRepositoryVA
        VAInitLambdaDockerImage: !Ref VAInitLambdaDockerImage
        MlflowExperimentDockerImage: !Ref MlflowExperimentDockerImage

  MlOpsStack:
    Condition: EnableMlOps
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'MlOps'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-mlops.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        EnableExternalAccess: !Ref EnableExternalAccess
        DnsZoneType: !Ref DnsZoneType
        UseKubernetesModel: !Ref MlOpsUseKubernetesModel
        UseSagemakerModel: !Ref MlOpsUseSagemakerModel
        DeployUsingLambda: !Ref DeployUsingLambda
        DeployUsingCodeBuild: !Ref DeployUsingCodeBuild
        DockerCPImage: !Ref CPDockerImage
        DockerMlModelImage: !Ref MlModelDockerImage
        DockerRegistry: !ImportValue ADPDockerRegistry
        NotebookInstanceType: !Ref NotebookInstanceType
        GitHubRepository: !Ref GitHubRepositoryMlOps
        MlflowServiceImageRepository: !Ref MlflowServiceDockerImage
        MlflowExperimentDockerImage: !Ref MlflowExperimentDockerImage
        MlLambdaDockerImage: !Ref MlLambdaDockerImage
        CleanupEpLambdaDockerImage: !Ref CleanupEpLambdaDockerImage
        BranchName: !Ref BranchName
        RepositoryID: !Ref RepositoryID
        GitConnectionName: !Ref GitConnectionName

  SemanticLayerStack:
    Condition: EnableSemanticLayer
    Type: AWS::CloudFormation::Stack
    Properties:
      Tags:
        - Key: 'Name'
          Value: 'MlOps'
        - Key: 'Owner'
          Value: !ImportValue ADPPlatformOwner
        - Key: 'Project'
          Value: 'ADP'
      TemplateURL: !Sub 'https://${ADPS3BucketName}.s3.${ADPS3BucketRegion}.${AWS::URLSuffix}/platform/${BasePlatformVersion}/cloudformation/l2/case-semantic-layer.yaml'
      Parameters:
        ADPS3BucketName: !Ref ADPS3BucketName
        ADPS3BucketRegion: !Ref ADPS3BucketRegion
        BasePlatformVersion: !Ref BasePlatformVersion
        UseCaseVersion: !Ref UseCaseVersion
        CacheBucketName: !Ref CacheBucketName
        ExportBucketName: !Ref ExportBucketName
        CubeSchemasBucketName: !Ref CubeSchemasBucketName
        DnsZoneType: !Ref DnsZoneType
        EnableExternalAccess: !Ref EnableExternalAccess
        SqlApiUser: !Ref SqlApiUser
        SLDashboardDockerImage: !Ref SLDashboardDockerImage
        DockerRegistry: !ImportValue ADPDockerRegistry
        CubeNamespace: !Ref CubeNamespace


Outputs:
# General tools
  BastionIP:
    Condition: EnabledKubernetes
    Description: 'Bastion host IP address.'
    Value: !If [ EnableBatch, !GetAtt BatchStack.Outputs.BastionIP, !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.BastionIP, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.BastionIP, !If [ EnableStreaming, !GetAtt StreamingStack.Outputs.BastionIP, !If [ EnableVisualAttributes, !GetAtt VisualAttributesStack.Outputs.BastionIP, !If [ EnablePromotionPlanning, !GetAtt PromotionPlanningStack.Outputs.BastionIP, !If [ EnableMlOps, !GetAtt MlOpsStack.Outputs.BastionIP, !If [ EnableDashboard, !GetAtt DashboardStack.Outputs.BastionIP, !If [ EnableSemanticLayer, !GetAtt SemanticLayerStack.Outputs.BastionIP, !Ref 'AWS::NoValue' ] ] ] ] ] ] ] ] ]

  AirflowFQDN:
    Condition: EnabledAirflow
    Description: 'Airflow service DNS address (private zone will not be accessible form outside)'
    Value: !If [ EnableBatch, !GetAtt BatchStack.Outputs.AirflowFQDN, !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AirflowFQDN, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AirflowFQDN, !If [ EnableStreaming, !GetAtt StreamingStack.Outputs.AirflowFQDN, !Ref 'AWS::NoValue'] ] ] ]

  AirflowELB:
    Condition: AirflowELB
    Description: 'Airflow service ELB address (should be enabled in Base Platform first)'
    Value: !If [ EnableBatch, !GetAtt BatchStack.Outputs.AirflowELB, !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AirflowELB, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AirflowELB, !If [ EnableStreaming, !GetAtt StreamingStack.Outputs.AirflowELB, !Ref 'AWS::NoValue'] ] ] ]

  AirflowSecret:
    Condition: EnabledAirflow
    Description: 'Airflow service secret'
    Value: !If [ EnableBatch, !GetAtt BatchStack.Outputs.AirflowSecret, !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AirflowSecret, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AirflowSecret, !If [ EnableStreaming, !GetAtt StreamingStack.Outputs.AirflowSecret, !Ref 'AWS::NoValue'] ] ] ]

  AirflowDagsBucket:
    Condition: EnabledAirflow
    Description: 'Bucket for Airflow Dags'
    Value: !If [ EnableBatch, !GetAtt BatchStack.Outputs.AirflowDagsBucket, !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AirflowDagsBucket, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AirflowDagsBucket, !If [ EnableStreaming, !GetAtt StreamingStack.Outputs.AirflowDagsBucket, !Ref 'AWS::NoValue'] ] ] ]

  AtlasELB:
    Condition: AtlasELB
    Description: 'Atlas service ELB address (will not work if external access is disabled)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AtlasELB, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AtlasELB, !Ref 'AWS::NoValue'] ]

  AtlasFQDN:
    Condition: EnabledAtlas
    Description: 'Atlas service DNS address (private zone will not be accessible form outside)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AtlasFQDN, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AtlasFQDN, !Ref 'AWS::NoValue'] ]

  AtlasSecret:
    Condition: EnabledAtlas
    Description: 'Atlas service secret'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.AtlasSecret, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.AtlasSecret, !Ref 'AWS::NoValue'] ]

  KibanaELB:
    Condition: KibanaELB
    Description: 'Kibana service ELB address (should be enabled in Base Platform first)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.KibanaELB, !If [ EnableDashboard, !GetAtt DashboardStack.Outputs.KibanaELB, !Ref 'AWS::NoValue'] ]

  KibanaFQDN:
    Condition: EnabledKibana
    Description: 'Kibana service DNS address (private zone will not be accessible form outside)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.KibanaFQDN, !If [ EnableDashboard, !GetAtt DashboardStack.Outputs.KibanaFQDN, !Ref 'AWS::NoValue'] ]

  MlflowELB:
    Condition: MlflowELB
    Description: 'Mlflow service ELB address (will not work if external access is disabled)'
    Value: !If [ EnableVisualAttributes, !GetAtt VisualAttributesStack.Outputs.MlflowELB, !If [ EnablePromotionPlanning, !GetAtt PromotionPlanningStack.Outputs.MlflowELB, !If [ EnableMlOps, !GetAtt MlOpsStack.Outputs.MlflowELB, !Ref 'AWS::NoValue'] ] ]

  MlflowFQDN:
    Condition: EnabledMlflow
    Description: 'Mlflow service DNS address (private zone will not be accessible form outside)'
    Value: !If [ EnableVisualAttributes, !GetAtt VisualAttributesStack.Outputs.MlflowFQDN, !If [ EnablePromotionPlanning, !GetAtt PromotionPlanningStack.Outputs.MlflowFQDN, !If [ EnableMlOps, !GetAtt MlOpsStack.Outputs.MlflowFQDN, !Ref 'AWS::NoValue'] ] ]

  ElasticSearchELB:
    Condition: ElasticSearchELB
    Description: 'ElasticSearch service ELB address (should be enabled in Base Platform first)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.ElasticSearchELB, !If [ EnableDashboard, !GetAtt DashboardStack.Outputs.ElasticSearchELB, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.ElasticSearchELB, !Ref 'AWS::NoValue'] ] ]

  ElasticSearchFQDN:
    Condition: EnabledElasticSearch
    Description: 'ElasticSearch service DNS address (private zone will not be accessible form outside)'
    Value: !If [ EnableDataQuality, !GetAtt DataQualityStack.Outputs.ElasticSearchFQDN, !If [ EnableDashboard, !GetAtt DashboardStack.Outputs.ElasticSearchFQDN, !If [ EnableDataGovernance, !GetAtt DataGovernanceStack.Outputs.ElasticSearchFQDN, !Ref 'AWS::NoValue'] ] ]

#  Batch case
  BatchTargetBucket:
    Condition: EnableBatch
    Description: 'Target bucket for Batch usecase.'
    Value: !GetAtt BatchStack.Outputs.BatchTargetBucket

# Streaming case
  StreamingTargetBucket:
    Condition: EnableStreaming
    Description: 'Target bucket for Streaming usecase.'
    Value: !GetAtt StreamingStack.Outputs.StreamingTargetBucket

# Ml observability case
  MlObservabilityNotebookInstanceName:
    Condition: EnableMlObservability
    Description: 'SageMaker notebook instance name for Observability'
    Value: !GetAtt MlObservabilityStack.Outputs.NotebookInstanceName

  MlObservabilityNotebookURL:
    Condition: EnableMlObservability
    Description: 'SageMaker Notebook Instance URL for Promotion Planning case'
    Value: !GetAtt MlObservabilityStack.Outputs.NotebookURL

  DataCaptureBucket:
    Condition: EnableMlObservability
    Description: 'Data capture bucket for ml observability'
    Value: !GetAtt MlObservabilityStack.Outputs.DataCaptureBucket

  EstimatorBucket:
    Condition: EnableMlObservability
    Description: 'Estimator bucket for ml observability'
    Value: !GetAtt MlObservabilityStack.Outputs.EstimatorBucket

  # Promotion Planning case
  PromotionPlanningUIELB:
    Condition: PromotionPlanningELB
    Description: 'Promotion Planning service ELB address (will not work if external access is disabled)'
    Value: !GetAtt PromotionPlanningStack.Outputs.PromotionPlanningUIELB

  PromotionPlanningUIFQDN:
    Condition: EnablePromotionPlanning
    Description: 'Promotion Planning service DNS address (private zone will not be accessible form outside of VPC)'
    Value: !GetAtt PromotionPlanningStack.Outputs.PromotionPlanningUIFQDN

  PromotionPlanningNotebookInstanceName:
    Condition: EnablePromotionPlanning
    Description: 'SageMaker Notebook Instance Name in Promotion Planning case'
    Value: !GetAtt PromotionPlanningStack.Outputs.NotebookInstanceName

  PromotionPlanningNotebookURL:
    Condition: EnablePromotionPlanning
    Description: 'SageMaker Notebook Instance URL for Promotion Planning case'
    Value: !GetAtt PromotionPlanningStack.Outputs.NotebookURL

# Visual Attributes case
  VisualAttributesELB:
    Condition: VisualAttributesELB
    Description: 'Visual Attributes service ELB address (will not work if external access is disabled)'
    Value: !GetAtt VisualAttributesStack.Outputs.VisualAttributesELB

  VisualAttributesFQDN:
    Condition: EnableVisualAttributes
    Description: 'Visual Attributes service DNS address (private zone will not be accessible form outside)'
    Value: !GetAtt VisualAttributesStack.Outputs.VisualAttributesFQDN

  VisualAttributesNotebookInstanceName:
    Condition: EnableVisualAttributes
    Description: 'SageMaker Notebook Instance Name in Visual Attributes case'
    Value: !GetAtt VisualAttributesStack.Outputs.NotebookInstanceName

  VisualAttributesNotebookURL:
    Condition: EnableVisualAttributes
    Description: 'SageMaker Notebook Instance URL for Visual Attributes case'
    Value: !GetAtt VisualAttributesStack.Outputs.NotebookURL

# MlOps case
  ChurnPredictionsELB:
    Condition: MlopsELB
    Description: 'Churn Predictions service ELB address (will not work if external access is disabled)'
    Value: !GetAtt MlOpsStack.Outputs.ChurnPredictionsELB

  ChurnPredictionsFQDN:
    Condition: EnableMlOps
    Description: 'Churn Predictions service DNS address (private zone will not be accessible form outside)'
    Value: !GetAtt MlOpsStack.Outputs.ChurnPredictionsFQDN

  MlOpsNotebookInstanceName:
    Condition: EnableMlOps
    Description: 'SageMaker Notebook Instance Name in MlOps case'
    Value: !GetAtt MlOpsStack.Outputs.NotebookInstanceName

  MlOpsNotebookURL:
    Condition: EnableMlOps
    Description: 'SageMaker Notebook Instance URL for MLOps case'
    Value: !GetAtt MlOpsStack.Outputs.NotebookURL

  ADPAppPipeline:
    Condition: UsingCodeBuild
    Description: 'Name of the ADP Application Pipeline for MlOps'
    Value: !GetAtt MlOpsStack.Outputs.ADPAppPipeline

# Semantic Layer
  SLCubeFQDN:
    Condition: EnableSemanticLayer
    Description: 'Semantic Layer cube application FQDN'
    Value: !GetAtt SemanticLayerStack.Outputs.CubeFQDN

  SLCubeELB:
    Condition: SemanticLayerELB
    Description: 'Semantic Layer cube application ELB link'
    Value: !GetAtt SemanticLayerStack.Outputs.CubeELB

  SLDashboardFQDN:
    Condition: EnableSemanticLayer
    Description: 'Semantic Layer dashboard application FQDN'
    Value: !GetAtt SemanticLayerStack.Outputs.DashboardFQDN

  SLDashboardELB:
    Condition: SemanticLayerELB
    Description: 'Semantic Layer dashboard application ELB link'
    Value: !GetAtt SemanticLayerStack.Outputs.DashboardELB

  SLCubeSQL:
    Condition: EnableSemanticLayer
    Description: 'Semantic Layer cube application SQL interface'
    Value: !GetAtt SemanticLayerStack.Outputs.CubeSQL

  SLCubeSqlSecretArn:
    Condition: EnableSemanticLayer
    Description: 'Semantic Layer secret contains SQL API password'
    Value: !GetAtt SemanticLayerStack.Outputs.CubeSqlSecretArn
