Description: >
  This template deploys the mesh and all of its components.

Parameters:

  MeshName:
    Description: The name of the mesh to create
    Type: String

  ServicesDomain:
    Description: The DNS suffice applied to virtual service names (e.g. default.svc.cluster.local)
    Type: String

Resources:

  Mesh:
    Type: AWS::AppMesh::Mesh
    Properties:
      MeshName: !Ref MeshName
      Spec:
        EgressFilter:
          Type: DROP_ALL


  ColorGatewayVirtualGateway:
    Type: AWS::AppMesh::VirtualGateway
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualGatewayName: ColorGateway
      Spec:
        BackendDefaults:
          ClientPolicy: {}
        Listeners:
          - PortMapping:
              Port: 80
              Protocol: http

  ColorGatewayRoute:
    DependsOn:
      - ColorGatewayVirtualGateway
      - ColorTellerVirtualService
    Type: AWS::AppMesh::GatewayRoute
    Properties: 
      GatewayRouteName: ColorGatewayRoute
      MeshName: !GetAtt Mesh.MeshName
      Spec: 
        HttpRoute:
          Action: 
            Target:
              VirtualService:
                VirtualServiceName: !Sub "colorteller.${ServicesDomain}"
          Match: 
            Prefix: /
      VirtualGatewayName: ColorGateway

  ExternalServiceVirtualNode:
    Type: AWS::AppMesh::VirtualNode
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualNodeName: ExternalService
      Spec:
        Listeners:
          - PortMapping:
              Port: 443
              Protocol: tcp
        ServiceDiscovery:
          DNS:
            Hostname: github.com
            IpPreference: IPv4_ONLY

  ExternalServiceVirtualNode2:
    Type: AWS::AppMesh::VirtualNode
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualNodeName: ExternalService2
      Spec:
        Listeners:
          - PortMapping:
              Port: 443
              Protocol: tcp
        Logging: {}
        ServiceDiscovery:
          DNS:
            Hostname: go.dev
            IpPreference: IPv4_ONLY
  
  ExternalVirtualRouter:
    Type: AWS::AppMesh::VirtualRouter
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualRouterName: external
      Spec:
        Listeners:
          - PortMapping:
              Port: 444
              Protocol: tcp

  ExternalRouterRoute:
    Type: AWS::AppMesh::Route
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      RouteName: go
      VirtualRouterName: !GetAtt ExternalVirtualRouter.VirtualRouterName
      Spec:
        TcpRoute:
          Action:
            WeightedTargets:
              - Port: 443
                VirtualNode: !GetAtt ExternalServiceVirtualNode2.VirtualNodeName
                Weight: 1

  ExternalServiceVirtualService:
    Type: AWS::AppMesh::VirtualService
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualServiceName: github.com
      Spec:
        Provider:
          VirtualNode:
            VirtualNodeName: !GetAtt ExternalServiceVirtualNode.VirtualNodeName

  ExternalServiceVirtualService2:
    Type: AWS::AppMesh::VirtualService
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualServiceName: go.dev
      Spec:
        Provider:
          VirtualRouter:
            VirtualRouterName: !GetAtt ExternalVirtualRouter.VirtualRouterName

  ColorTellerVirtualNode:
    Type: AWS::AppMesh::VirtualNode
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualNodeName: ColorTellerWhite
      Spec:
        Listeners:
          - PortMapping:
              Port: 80
              Protocol: http
            HealthCheck:
              Protocol: http
              Path: /ping
              HealthyThreshold: 2
              UnhealthyThreshold: 3
              TimeoutMillis: 2000
              IntervalMillis: 5000
        Backends:
          - VirtualService:
              VirtualServiceName: !GetAtt ExternalServiceVirtualService.VirtualServiceName
          - VirtualService:
              VirtualServiceName: !GetAtt ExternalServiceVirtualService2.VirtualServiceName
        ServiceDiscovery:
          DNS:
            Hostname: !Sub "colorteller.${ServicesDomain}"

  ColorTellerVirtualService:
    Type: AWS::AppMesh::VirtualService
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualServiceName: !Sub "colorteller.${ServicesDomain}"
      Spec:
        Provider:
          VirtualNode:
            VirtualNodeName: !GetAtt ColorTellerVirtualNode.VirtualNodeName