Home > Software engineering >  CodeDeploy::DeploymentGroup Error: The list of target group pairs must have exactly one pair
CodeDeploy::DeploymentGroup Error: The list of target group pairs must have exactly one pair

Time:01-21

I am creating a cloudformation nestedDeployment(CodeBuild Project and CodeDeploy Application) with a Blue/Green Deployment, for an ECS (Fargate Managed) Deployment. The Deployment fails in the creation of the CodeDeployment Group with this error:

"The list of target group pairs must have exactly one pair (Service: AmazonCodeDeploy; Status Code: 400; Error Code: InvalidTargetGroupPairException; Request ID: xxxxxx)"

My nested Deployment has an alb and the ouputs are seen in this deployment as importvalues, the output values are - ECSTargetGroup1Name, ECSTargetGroup1Name (With the export from the alb as - Value: !GetAtt ECSTargetGroup1.TargetGroupName and Value: !GetAtt ECSTargetGroup2.TargetGroupName). Same applies for the ECS ClusterName with its output-export in it's yaml file.

My two cents in understanding this error is suggesting i may have declared wrongly the target groups in the TargetGroupPairInfoList.

Any help with this will be appreciated.

ALB Code is as follows:

# 4. ECS Target Group

  ECSTargetGroup1:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 20
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      Name: !Sub ${EnvironmentName}-${ServiceName1}-1
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-${ServiceName1}-1
      TargetType: ip
      UnhealthyThresholdCount: 4
      VpcId: !ImportValue VpcId

  ECSTargetGroup2:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 20
      HealthCheckPath: /healtchcheck
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 4
      Name: !Sub ${EnvironmentName}-${ServiceName1}-2
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-${ServiceName1}-2
      TargetType: ip
      UnhealthyThresholdCount: 4
      VpcId: !ImportValue VpcId

  # 1. Load Balancer

  PublicLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub ${EnvironmentName}
      Scheme: internet-facing
      SecurityGroups: [!ImportValue PublicLoadBalancerSG]
      Subnets:
        # The load balancer is placed into the public subnets, so that traffic
        # from the internet can reach the load balancer directly via the internet gateway
        - !ImportValue PublicSubnet1a
        - !ImportValue PublicSubnet1b
        - !ImportValue PublicSubnet1c
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} PublicLoadBalancer


  # 3. Load Balancer Listener

  80Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions: # Required
        - Type: redirect 
          RedirectConfig:
            Host: "#{host}"
            Path: "/#{path}"
            Port: "443"
            Protocol: HTTPS
            Query: "#{query}"
            StatusCode: HTTP_301
      LoadBalancerArn: !Ref PublicLoadBalancer # Required
      Port: 80
      Protocol: HTTP

  ProductionListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      # Certificates:
      #   - CertificateArn: !Ref Certificate
      DefaultActions: # Required
        - TargetGroupArn: !Ref ECSTargetGroup2
          Type: forward
      LoadBalancerArn: !Ref PublicLoadBalancer # Required
      Port: 443
      Protocol: HTTP

  TestListener: 
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      # Certificates:
      #   - CertificateArn: !Ref Certificate
      DefaultActions: # Required
        - TargetGroupArn: !Ref ECSTargetGroup1
          Type: forward
      LoadBalancerArn: !Ref PublicLoadBalancer # Required
      Port: 8443
      Protocol: HTTP

  # 5. Load Balancer Listener Rule

  80ListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions: # Required
        - Type: redirect 
          RedirectConfig:
            Host: "#{host}"
            Path: "/#{path}"
            Port: "443"
            Protocol: HTTPS
            Query: "#{query}"
            StatusCode: HTTP_301
      Conditions: # Required
        - Field: path-pattern
          Values: [!Ref 'Path']
      ListenerArn: !Ref 80Listener # Required
      Priority: 1 # Required

  ProductionListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions: # Required
        - TargetGroupArn: !Ref ECSTargetGroup2
          Type: forward
      Conditions: # Required
        - Field: path-pattern
          Values: [!Ref 'Path']
      ListenerArn: !Ref ProductionListener # Required
      Priority: 1 # Required

  TestListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions: # Required
        - TargetGroupArn: !Ref ECSTargetGroup1
          Type: forward
      Conditions: # Required
        - Field: path-pattern
          Values: [!Ref 'Path']
      ListenerArn: !Ref TestListener # Required
      Priority: 1 # Required

An excerpt of my code is this,

Resources: 

  CodeBuildApplication1:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      BadgeEnabled: false
      Description: !Sub "Build image for ${EnvironmentName} ${ServiceName1}"
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
        ImagePullCredentialsType: CODEBUILD
        PrivilegedMode: true
        Type: LINUX_CONTAINER
      Name: !Sub "${EnvironmentName}-${ServiceName1}-build-image"
      QueuedTimeoutInMinutes: 480
      ServiceRole: !ImportValue CodeBuildService1RoleArn # Required
      Source:
        BuildSpec: codePipeline/ecs-image.yml
        Type: CODEPIPELINE
      TimeoutInMinutes: 60

  CodeDeployApplication1:
    Type: AWS::CodeDeploy::Application
    Properties:
      ApplicationName: !Sub "AppECS-${EnvironmentName}-${ServiceName1}svc"
      ComputePlatform: ECS

  CodeDeployGroup1:
    Type: AWS::CodeDeploy::DeploymentGroup
    Properties:
      ApplicationName: !Ref CodeDeployApplication1  # Required
      AutoRollbackConfiguration:
        Enabled: true
        Events:
          - DEPLOYMENT_FAILURE
          - DEPLOYMENT_STOP_ON_REQUEST
      # AutoScalingGroups:
      #   AutoScalingGroups
      BlueGreenDeploymentConfiguration:
        DeploymentReadyOption:
          ActionOnTimeout: CONTINUE_DEPLOYMENT
          WaitTimeInMinutes: 0
        # GreenFleetProvisioningOption:
        #   Action: DISCOVER_EXISTING
        TerminateBlueInstancesOnDeploymentSuccess:
          Action: TERMINATE
          TerminationWaitTimeInMinutes: 60
      # Deployment:
      #   Description: "String"
      #   IgnoreApplicationStopFailures: false
      DeploymentConfigName: CodeDeployDefault.AllAtOnce
      DeploymentGroupName: !Sub "DgpECS-${EnvironmentName}-${ServiceName1}svc"
      DeploymentStyle:
        DeploymentOption: WITH_TRAFFIC_CONTROL
        DeploymentType: BLUE_GREEN
      ECSServices:
        - ClusterName: !ImportValue ECSCluster1Name
          ServiceName: !ImportValue ECSService1Cluster1Name
      LoadBalancerInfo:
        # ElbInfoList:
        #   - Name: !ImportValue PublicLoadBalancer
        # TargetGroupInfoList:
        TargetGroupPairInfoList:
          - ProdTrafficRoute:
              ListenerArns:
                - !ImportValue ProductionListener
          - TestTrafficRoute:
              ListenerArns:
                - !ImportValue TestListener
          - TargetGroups:
              - Name: !ImportValue ECSTargetGroup1Name
              - Name: !ImportValue ECSTargetGroup2Name
      ServiceRoleArn: !ImportValue CodeDeployServiceRoleArn # Required

I have tried to comment out one target group and use the TargetGroupInfoList, but AWS requires a pair of Target Groups so need to use the TargetGroupPairInfoList.

Checked my alb infrastructure to confirm the targetgroup relationship to the listeners and that section looks good, with my ECS Cluster being created and tasks running.

CodePudding user response:

I think you have too many - characters in the TargetGroupPairInfoList section. You are creating a new list item with each - when you should really only have a single - indicating a single TargetGroupPairInfo item, like this:

        TargetGroupPairInfoList:
          - ProdTrafficRoute:
              ListenerArns:
                - !ImportValue ProductionListener
            TestTrafficRoute:
              ListenerArns:
                - !ImportValue TestListener
            TargetGroups:
              - Name: !ImportValue ECSTargetGroup1Name
              - Name: !ImportValue ECSTargetGroup2Name
  • Related