Unresolved Dependencies error when creating Beanstalk Env with shared load balancer in CloudFormation

0

I'm trying to create a Beanstalk Environment in CloudFormation that will use an existing shared application load balancer, rather than one created by Beanstalk.

Unfortunately I get an error in Beanstalk suggesting that I'm not referencing the load balancer correctly.

Service:AmazonCloudFormation, Message:Template format error: Unresolved resource dependencies [AWSEBV2LoadBalancer] in the Resources block of the template

ElasticBeanstalk events

In my CloudFormation template I have the following:

Resources:
  ConfigurationTemplate:
  Type: AWS::ElasticBeanstalk::ConfigurationTemplate
  Properties:
    ApplicationName: !ImportValue
      Fn::Sub: "${ApplicationStackName}-ApplicationName"
    SolutionStackName: !Ref StackType
    OptionSettings:
        - Namespace: aws:elasticbeanstalk:environment
           OptionName: EnvironmentType
           Value: LoadBalanced
        - Namespace: aws:elasticbeanstalk:environment
           OptionName: LoadBalancerIsShared
           Value: true
        - Namespace: aws:elasticbeanstalk:environment
          OptionName: LoadBalancerType
          Value: application
        - Namespace: aws:elbv2:loadbalancer
          OptionName: SharedLoadBalancer
          Value:
            Fn::ImportValue: !Sub "${SharedLoadBalancerStackName}-LoadBalancer-Arn"

I have double-checked and the export is available where we're importing it from. Any idea why I would be getting the load balancer-related error in Beanstalk?

For completeness, and in case I'm misunderstanding, I'm using instructions from [1], and [2] to try add a listener to the load balancer from the Beanstalk CloudFormation template but the Lambda doesn't get executed so I guess we don't make it this far.

  LambdaBasicExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess
        - arn:aws:iam::aws:policy/AWSElasticBeanstalkReadOnly
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  GetEBLBTargetGroupResource:
    Type: Custom::GetEBLoadBalancerArn
    Properties:
      ServiceToken: !GetAtt GetEBLBTargetGroupLambda.Arn
      EBEnvName: !Ref Environment

  # Query EB for its first load balancer's ARN
  GetEBLBTargetGroupLambda:
    Type: AWS::Lambda::Function
    Properties:
      Description: Get ARN of ElasticBeanstalk load balancer
      Handler: index.handler
      Timeout: 30
      Role: !GetAtt 'LambdaBasicExecutionRole.Arn'
      Runtime: nodejs12.x
      Code:
        ZipFile: |
          const AWS = require('aws-sdk');
          const cfnResponse = require('cfn-response');
          const eb = new AWS.ElasticBeanstalk();
          const cfn = new AWS.CloudFormation();
          
          exports.handler = (event, context) => {
            if (event['RequestType'] !== 'Create') {
              console.log(event['RequestType'], 'is not Create');
              return cfnResponse.send(event, context, cfnResponse.SUCCESS, {
                Message: `${event['RequestType']} completed.`,
              });
            }
          
            eb.describeEnvironmentResources(
              { EnvironmentName: event['ResourceProperties']['EBEnvName'] },
              function (err, { EnvironmentResources }) {
                if (err) {
                  console.log('Exception', err);
                  return cfnResponse.send(event, context, cfnResponse.FAILED, {});
                }
          
                const PhysicalResourceId = EnvironmentResources['AutoScalingGroups'].find(
                  (group) => group.Name
                )['Name'];
          
                const { StackResources } = cfn.describeStackResources(
                  { PhysicalResourceId },
                  function (err, { StackResources }) {
                    if (err) {
                      console.log('Exception', err);
                      return cfnResponse.send(event, context, cfnResponse.FAILED, {});
                    }
                    const TargetGroup = StackResources.find(
                      (resource) => resource.LogicalResourceId === 'AWSEBV2LoadBalancerTargetGroup'
                    );
          
                    cfnResponse.send(event, context, cfnResponse.SUCCESS, {
                      TargetGroupArn: TargetGroup.PhysicalResourceId,
                    });
                  }
                );
              }
            );
          }

  ListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Priority: 1
      ListenerArn:
        Fn::ImportValue: !Sub '${SharedLoadBalancerStackName}-Listener-Arn'
      Actions:
        - Type: forward
          TargetGroupArn:
            Fn::GetAtt: [ 'GetEBLBTargetGroupResource', 'TargetGroupArn' ]
      Conditions:
        - Field: path-pattern
          PathPatternConfig:
            Values: [ '/*' ]

[1] https://stackoverflow.com/questions/67322501/cloudformation-elasticbeanstalk-specify-target-group-for-shared-load-balancer

[2] https://stackoverflow.com/questions/65677754/awswafv2webaclassociation-resourcearn-for-application-load-balancer-in-cloud/65729457#65729457

1 Answer
0
Accepted Answer

It's because I had an ebextension that referenced AWSEBV2LoadBalancer.

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions