walkthroughs/howto-ecs-basics/deploy/2-meshify.yaml [1:495]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameters:
  ProjectName:
    Type: String
    Description: Project name to link stacks

  VpcCIDR:
    Description: Please enter the IP range (CIDR notation) for this VPC
    Type: String
    Default: 10.0.0.0/16

  PublicSubnet1CIDR:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.0.0.0/19

  PublicSubnet2CIDR:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone
    Type: String
    Default: 10.0.32.0/19

  PrivateSubnet1CIDR:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
    Type: String
    Default: 10.0.64.0/19

  PrivateSubnet2CIDR:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
    Type: String
    Default: 10.0.96.0/19

  ColorAppImage:
    Type: String
    Description: Color app container image

  FrontAppImage:
    Type: String
    Description: Front app container image

  EnvoyImage:
    Type: String
    Description: Envoy container image

  CloudWatchAgentImage:
    Type: String
    Description: Cloud Watch agent container image

  ContainerPort:
    Type: Number
    Description: Port number to use for applications
    Default: 8080

Resources:

  # START infra

  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Ref ProjectName

  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref ProjectName

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Ref ProjectName

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: !Ref PublicSubnet1CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Subnet (AZ1)'

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      CidrBlock: !Ref PublicSubnet2CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Subnet (AZ2)'

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: !Ref PrivateSubnet1CIDR
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Subnet (AZ1)'

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      CidrBlock: !Ref PrivateSubnet2CIDR
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Subnet (AZ2)'

  NatGateway1EIP:
    Type: AWS::EC2::EIP
    DependsOn: InternetGatewayAttachment
    Properties:
      Domain: vpc

  NatGateway2EIP:
    Type: AWS::EC2::EIP
    DependsOn: InternetGatewayAttachment
    Properties:
      Domain: vpc

  NatGateway1:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGateway1EIP.AllocationId
      SubnetId: !Ref PublicSubnet1

  NatGateway2:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGateway2EIP.AllocationId
      SubnetId: !Ref PublicSubnet2

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Routes'

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  PrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Routes (AZ1)'

  DefaultPrivateRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway1

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      SubnetId: !Ref PrivateSubnet1

  PrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Routes (AZ2)'

  DefaultPrivateRoute2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway2

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      SubnetId: !Ref PrivateSubnet2

  AppSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Security group for the apps"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - CidrIp: !Ref VpcCIDR
          IpProtocol: -1

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '${ProjectName}-log-group'
      RetentionInDays: 30

  TaskIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchFullAccess
        - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
        - arn:aws:iam::aws:policy/AWSAppMeshEnvoyAccess

  TaskExecutionIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess

  PrivateDnsNamespace:
    Type: AWS::ServiceDiscovery::PrivateDnsNamespace
    Properties:
      Name: !Sub '${ProjectName}.pvtdns'
      Vpc: !Ref VPC

  Mesh:
    Type: AWS::AppMesh::Mesh
    Properties:
      MeshName: !Ref ProjectName

  AppMeshHostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name: !Sub '${ProjectName}.mesh.local'
      HostedZoneConfig:
        Comment: Private hosted zone for resolving virtual-services
      VPCs:
        - VPCId: !Ref VPC
          VPCRegion: !Ref 'AWS::Region'

  AppMeshWildcardRecordSet:
    Type: AWS::Route53::RecordSet
    DependsOn:
      - AppMeshHostedZone
    Properties:
      HostedZoneId: !Ref AppMeshHostedZone
      ResourceRecords:
        - '1.2.3.4'
      TTL: '900'
      Name:
        Fn::Join:
          - '.'
          -
            - '*'
            - !Sub '${ProjectName}.mesh.local'
      Type: A

  # END infra

  # START colorapp

  ColorServiceRegistry:
    Type: AWS::ServiceDiscovery::Service
    Properties:
      Name: 'color'
      DnsConfig:
        NamespaceId: !GetAtt PrivateDnsNamespace.Id
        DnsRecords:
          - Type: A
            TTL: 300
      HealthCheckCustomConfig:
        FailureThreshold: 1

  ColorTaskDef:
    Type: AWS::ECS::TaskDefinition
    Properties:
      RequiresCompatibilities:
        - 'FARGATE'
      Family: !Sub '${ProjectName}-color'
      NetworkMode: 'awsvpc'
      Cpu: 256
      Memory: 512
      TaskRoleArn: !Ref TaskIamRole
      ExecutionRoleArn: !Ref TaskExecutionIamRole
      ProxyConfiguration:
        Type: 'APPMESH'
        ContainerName: 'envoy'
        ProxyConfigurationProperties:
          - Name: 'IgnoredUID'
            Value: '1337'
          - Name: 'ProxyIngressPort'
            Value: '15000'
          - Name: 'ProxyEgressPort'
            Value: '15001'
          - Name: 'AppPorts'
            Value: !Sub '${ContainerPort}'
          - Name: 'EgressIgnoredIPs'
            Value: '169.254.170.2,169.254.169.254'
      ContainerDefinitions:
        - Name: 'app'
          Image: !Ref ColorAppImage
          Essential: true
          DependsOn:
            - ContainerName: 'envoy'
              Condition: 'HEALTHY'
            - ContainerName: 'xray'
              Condition: 'START'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          PortMappings:
            - ContainerPort: !Ref ContainerPort
              HostPort: !Ref ContainerPort
              Protocol: 'tcp'
          Environment:
            - Name: COLOR
              Value: 'green'
            - Name: PORT
              Value: !Sub '${ContainerPort}'
            - Name: XRAY_APP_NAME
              Value: 'color'
        - Name: 'xray'
          Image: "public.ecr.aws/xray/aws-xray-daemon"
          Essential: true
          User: '1337'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          PortMappings:
            - ContainerPort: 2000
              Protocol: 'udp'
        - Name: 'cwagent'
          Image: !Ref CloudWatchAgentImage
          Essential: true
          User: '1337'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'cwagent'
          PortMappings:
            - ContainerPort: 8125
              Protocol: 'udp'
          Environment:
            - Name: 'HOST_NAME'
              Value: !GetAtt ColorVirtualNode.VirtualNodeName
            - Name: CW_CONFIG_CONTENT
              Value:
                Fn::Sub: "{ \"metrics\": { \"namespace\":\"${ProjectName}\", \"metrics_collected\": { \"statsd\": {}}}}"
        - Name: envoy
          Image: !Ref EnvoyImage
          Essential: true
          User: '1337'
          DependsOn:
            - ContainerName: 'xray'
              Condition: 'START'
          Ulimits:
            - Name: "nofile"
              HardLimit: 15000
              SoftLimit: 15000
          PortMappings:
            - ContainerPort: 9901
              Protocol: 'tcp'
            - ContainerPort: 15000
              Protocol: 'tcp'
            - ContainerPort: 15001
              Protocol: 'tcp'
          HealthCheck:
            Command:
              - 'CMD-SHELL'
              - 'curl -s http://localhost:9901/server_info | grep state | grep -q LIVE'
            Interval: 5
            Timeout: 10
            Retries: 10
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          Environment:
            - Name: 'ENVOY_LOG_LEVEL'
              Value: 'debug'
            - Name: 'ENABLE_ENVOY_XRAY_TRACING'
              Value: '1'
            - Name: 'ENABLE_ENVOY_STATS_TAGS'
              Value: '1'
            - Name: 'ENABLE_ENVOY_DOG_STATSD'
              Value: '1'
            - Name: 'APPMESH_RESOURCE_ARN'
              Value:
                Fn::Join:
                  - ''
                  -
                    - 'mesh/'
                    - !GetAtt Mesh.MeshName
                    - '/virtualNode/'
                    - !GetAtt ColorVirtualNode.VirtualNodeName

  ColorECSService:
    Type: AWS::ECS::Service
    DependsOn:
      - ColorServiceRegistry
    Properties:
      Cluster: !Ref ECSCluster
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 100
      DesiredCount: 3
      LaunchType: 'FARGATE'
      ServiceRegistries:
        - RegistryArn: !GetAtt 'ColorServiceRegistry.Arn'
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: DISABLED
          SecurityGroups:
            - !Ref AppSecurityGroup
          Subnets:
            - !Ref PrivateSubnet1
            - !Ref PrivateSubnet2
      TaskDefinition: !Ref ColorTaskDef

  ColorVirtualNode:
    Type: AWS::AppMesh::VirtualNode
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualNodeName: !Sub '${ProjectName}-color-node'
      Spec:
        Listeners:
          - PortMapping:
              Port: !Ref ContainerPort
              Protocol: http
        ServiceDiscovery:
          AWSCloudMap:
            NamespaceName: !Sub '${ProjectName}.pvtdns'
            ServiceName: !GetAtt ColorServiceRegistry.Name
            Attributes:
              - Key: 'ECS_TASK_DEFINITION_FAMILY'
                Value: !Sub '${ProjectName}-color'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



walkthroughs/howto-ecs-basics/deploy/3-routing.yaml [1:495]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Parameters:
  ProjectName:
    Type: String
    Description: Project name to link stacks

  VpcCIDR:
    Description: Please enter the IP range (CIDR notation) for this VPC
    Type: String
    Default: 10.0.0.0/16

  PublicSubnet1CIDR:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
    Type: String
    Default: 10.0.0.0/19

  PublicSubnet2CIDR:
    Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone
    Type: String
    Default: 10.0.32.0/19

  PrivateSubnet1CIDR:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
    Type: String
    Default: 10.0.64.0/19

  PrivateSubnet2CIDR:
    Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
    Type: String
    Default: 10.0.96.0/19

  ColorAppImage:
    Type: String
    Description: Color app container image

  FrontAppImage:
    Type: String
    Description: Front app container image

  EnvoyImage:
    Type: String
    Description: Envoy container image

  CloudWatchAgentImage:
    Type: String
    Description: Cloud Watch agent container image

  ContainerPort:
    Type: Number
    Description: Port number to use for applications
    Default: 8080

Resources:

  # START infra

  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Ref ProjectName

  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref ProjectName

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Ref ProjectName

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: !Ref PublicSubnet1CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Subnet (AZ1)'

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      CidrBlock: !Ref PublicSubnet2CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Subnet (AZ2)'

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: !Ref PrivateSubnet1CIDR
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Subnet (AZ1)'

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      CidrBlock: !Ref PrivateSubnet2CIDR
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Subnet (AZ2)'

  NatGateway1EIP:
    Type: AWS::EC2::EIP
    DependsOn: InternetGatewayAttachment
    Properties:
      Domain: vpc

  NatGateway2EIP:
    Type: AWS::EC2::EIP
    DependsOn: InternetGatewayAttachment
    Properties:
      Domain: vpc

  NatGateway1:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGateway1EIP.AllocationId
      SubnetId: !Ref PublicSubnet1

  NatGateway2:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGateway2EIP.AllocationId
      SubnetId: !Ref PublicSubnet2

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Public Routes'

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  PrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Routes (AZ1)'

  DefaultPrivateRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway1

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      SubnetId: !Ref PrivateSubnet1

  PrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${ProjectName} Private Routes (AZ2)'

  DefaultPrivateRoute2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway2

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      SubnetId: !Ref PrivateSubnet2

  AppSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Security group for the apps"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - CidrIp: !Ref VpcCIDR
          IpProtocol: -1

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '${ProjectName}-log-group'
      RetentionInDays: 30

  TaskIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchFullAccess
        - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
        - arn:aws:iam::aws:policy/AWSAppMeshEnvoyAccess

  TaskExecutionIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess

  PrivateDnsNamespace:
    Type: AWS::ServiceDiscovery::PrivateDnsNamespace
    Properties:
      Name: !Sub '${ProjectName}.pvtdns'
      Vpc: !Ref VPC

  Mesh:
    Type: AWS::AppMesh::Mesh
    Properties:
      MeshName: !Ref ProjectName

  AppMeshHostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name: !Sub '${ProjectName}.mesh.local'
      HostedZoneConfig:
        Comment: Private hosted zone for resolving virtual-services
      VPCs:
        - VPCId: !Ref VPC
          VPCRegion: !Ref 'AWS::Region'

  AppMeshWildcardRecordSet:
    Type: AWS::Route53::RecordSet
    DependsOn:
      - AppMeshHostedZone
    Properties:
      HostedZoneId: !Ref AppMeshHostedZone
      ResourceRecords:
        - '1.2.3.4'
      TTL: '900'
      Name:
        Fn::Join:
          - '.'
          -
            - '*'
            - !Sub '${ProjectName}.mesh.local'
      Type: A

  # END infra

  # START colorapp

  ColorServiceRegistry:
    Type: AWS::ServiceDiscovery::Service
    Properties:
      Name: 'color'
      DnsConfig:
        NamespaceId: !GetAtt PrivateDnsNamespace.Id
        DnsRecords:
          - Type: A
            TTL: 300
      HealthCheckCustomConfig:
        FailureThreshold: 1

  ColorTaskDef:
    Type: AWS::ECS::TaskDefinition
    Properties:
      RequiresCompatibilities:
        - 'FARGATE'
      Family: !Sub '${ProjectName}-color'
      NetworkMode: 'awsvpc'
      Cpu: 256
      Memory: 512
      TaskRoleArn: !Ref TaskIamRole
      ExecutionRoleArn: !Ref TaskExecutionIamRole
      ProxyConfiguration:
        Type: 'APPMESH'
        ContainerName: 'envoy'
        ProxyConfigurationProperties:
          - Name: 'IgnoredUID'
            Value: '1337'
          - Name: 'ProxyIngressPort'
            Value: '15000'
          - Name: 'ProxyEgressPort'
            Value: '15001'
          - Name: 'AppPorts'
            Value: !Sub '${ContainerPort}'
          - Name: 'EgressIgnoredIPs'
            Value: '169.254.170.2,169.254.169.254'
      ContainerDefinitions:
        - Name: 'app'
          Image: !Ref ColorAppImage
          Essential: true
          DependsOn:
            - ContainerName: 'envoy'
              Condition: 'HEALTHY'
            - ContainerName: 'xray'
              Condition: 'START'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          PortMappings:
            - ContainerPort: !Ref ContainerPort
              HostPort: !Ref ContainerPort
              Protocol: 'tcp'
          Environment:
            - Name: COLOR
              Value: 'green'
            - Name: PORT
              Value: !Sub '${ContainerPort}'
            - Name: XRAY_APP_NAME
              Value: 'color'
        - Name: 'xray'
          Image: "public.ecr.aws/xray/aws-xray-daemon"
          Essential: true
          User: '1337'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          PortMappings:
            - ContainerPort: 2000
              Protocol: 'udp'
        - Name: 'cwagent'
          Image: !Ref CloudWatchAgentImage
          Essential: true
          User: '1337'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'cwagent'
          PortMappings:
            - ContainerPort: 8125
              Protocol: 'udp'
          Environment:
            - Name: 'HOST_NAME'
              Value: !GetAtt ColorVirtualNode.VirtualNodeName
            - Name: CW_CONFIG_CONTENT
              Value:
                Fn::Sub: "{ \"metrics\": { \"namespace\":\"${ProjectName}\", \"metrics_collected\": { \"statsd\": {}}}}"
        - Name: envoy
          Image: !Ref EnvoyImage
          Essential: true
          User: '1337'
          DependsOn:
            - ContainerName: 'xray'
              Condition: 'START'
          Ulimits:
            - Name: "nofile"
              HardLimit: 15000
              SoftLimit: 15000
          PortMappings:
            - ContainerPort: 9901
              Protocol: 'tcp'
            - ContainerPort: 15000
              Protocol: 'tcp'
            - ContainerPort: 15001
              Protocol: 'tcp'
          HealthCheck:
            Command:
              - 'CMD-SHELL'
              - 'curl -s http://localhost:9901/server_info | grep state | grep -q LIVE'
            Interval: 5
            Timeout: 10
            Retries: 10
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'color'
          Environment:
            - Name: 'ENVOY_LOG_LEVEL'
              Value: 'debug'
            - Name: 'ENABLE_ENVOY_XRAY_TRACING'
              Value: '1'
            - Name: 'ENABLE_ENVOY_STATS_TAGS'
              Value: '1'
            - Name: 'ENABLE_ENVOY_DOG_STATSD'
              Value: '1'
            - Name: 'APPMESH_RESOURCE_ARN'
              Value:
                Fn::Join:
                  - ''
                  -
                    - 'mesh/'
                    - !GetAtt Mesh.MeshName
                    - '/virtualNode/'
                    - !GetAtt ColorVirtualNode.VirtualNodeName

  ColorECSService:
    Type: AWS::ECS::Service
    DependsOn:
      - ColorServiceRegistry
    Properties:
      Cluster: !Ref ECSCluster
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 100
      DesiredCount: 3
      LaunchType: 'FARGATE'
      ServiceRegistries:
        - RegistryArn: !GetAtt 'ColorServiceRegistry.Arn'
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: DISABLED
          SecurityGroups:
            - !Ref AppSecurityGroup
          Subnets:
            - !Ref PrivateSubnet1
            - !Ref PrivateSubnet2
      TaskDefinition: !Ref ColorTaskDef

  ColorVirtualNode:
    Type: AWS::AppMesh::VirtualNode
    Properties:
      MeshName: !GetAtt Mesh.MeshName
      VirtualNodeName: !Sub '${ProjectName}-color-node'
      Spec:
        Listeners:
          - PortMapping:
              Port: !Ref ContainerPort
              Protocol: http
        ServiceDiscovery:
          AWSCloudMap:
            NamespaceName: !Sub '${ProjectName}.pvtdns'
            ServiceName: !GetAtt ColorServiceRegistry.Name
            Attributes:
              - Key: 'ECS_TASK_DEFINITION_FAMILY'
                Value: !Sub '${ProjectName}-color'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



