Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elastic Beanstalk environment forces update on each apply #1471

Open
stuffandthings opened this issue Aug 22, 2017 · 60 comments
Open

Elastic Beanstalk environment forces update on each apply #1471

stuffandthings opened this issue Aug 22, 2017 · 60 comments
Labels
bug Addresses a defect in current functionality. service/elasticbeanstalk Issues and PRs that pertain to the elasticbeanstalk service.

Comments

@stuffandthings
Copy link

stuffandthings commented Aug 22, 2017

Hello,

Every time I run terraform apply my elastic beanstalk environment is marked for update, which in turn re-creates my environment. This is clearly undesirable behavior.

Terraform Version

Terraform v0.10.2

Affected Resource(s)

  • aws_elastic_beanstalk_environment

Terraform Configuration Files

resource "aws_elastic_beanstalk_environment" "backend" {
  name                = "backend-${var.environment}"
  application         = "backend"
  solution_stack_name = "64bit Amazon Linux 2017.03 v2.4.3 running PHP 5.6"
  tier                = "WebServer"

  setting {
  ...
  }
}

Output

  ~ module.ums.aws_elastic_beanstalk_environment.backend
      setting.#:                    "19" => "20"
      setting.1224657411.name:      "SSHSourceRestriction" => ""
      setting.1224657411.namespace: "aws:autoscaling:launchconfiguration" => ""
      setting.1224657411.resource:  "" => ""
      setting.1224657411.value:     "tcp,22,22,null" => ""
      setting.1311926541.name:      "RollingUpdateEnabled" => "RollingUpdateEnabled"
      setting.1311926541.namespace: "aws:autoscaling:updatepolicy:rollingupdate" => "aws:autoscaling:updatepolicy:rollingupdate"
      setting.1311926541.resource:  "" => ""
      setting.1311926541.value:     "true" => "true"
      setting.1531156480.name:      "Application Healthcheck URL" => ""
      setting.1531156480.namespace: "aws:elasticbeanstalk:application" => ""
      setting.1531156480.resource:  "" => ""
      setting.1531156480.value:     "/elb-status" => ""
      setting.1636165274.name:      "EC2KeyName" => "EC2KeyName"
      setting.1636165274.namespace: "aws:autoscaling:launchconfiguration" => "aws:autoscaling:launchconfiguration"
      setting.1636165274.resource:  "" => ""
      setting.1636165274.value:     "key" => "key"
      setting.2276893638.name:      "RollingUpdateType" => "RollingUpdateType"
      setting.2276893638.namespace: "aws:autoscaling:updatepolicy:rollingupdate" => "aws:autoscaling:updatepolicy:rollingupdate"
      setting.2276893638.resource:  "" => ""
      setting.2276893638.value:     "Health" => "Health"
      setting.2396587397.name:      "MinSize" => "MinSize"
      setting.2396587397.namespace: "aws:autoscaling:asg" => "aws:autoscaling:asg"
      setting.2396587397.resource:  "" => ""
      setting.2396587397.value:     "1" => "1"
      setting.2420299722.name:      "SystemType" => "SystemType"
      setting.2420299722.namespace: "aws:elasticbeanstalk:healthreporting:system" => "aws:elasticbeanstalk:healthreporting:system"
      setting.2420299722.resource:  "" => ""
      setting.2420299722.value:     "enhanced" => "enhanced"
      setting.2558992023.name:      "ManagedActionsEnabled" => "ManagedActionsEnabled"
      setting.2558992023.namespace: "aws:elasticbeanstalk:managedactions" => "aws:elasticbeanstalk:managedactions"
      setting.2558992023.resource:  "" => ""
      setting.2558992023.value:     "true" => "true"
      setting.2671587030.name:      "Subnets" => "Subnets"
      setting.2671587030.namespace: "aws:ec2:vpc" => "aws:ec2:vpc"
      setting.2671587030.resource:  "" => ""
      setting.2671587030.value:     "subnet-3630230b,subnet-6a798c23,subnet-6d116547,subnet-8ea1a4d6" => "subnet-3630230b,subnet-6a798c23,subnet-6d116547,subnet-8ea1a4d6"
      setting.2808638165.name:      "PreferredStartTime" => "PreferredStartTime"
      setting.2808638165.namespace: "aws:elasticbeanstalk:managedactions" => "aws:elasticbeanstalk:managedactions"
      setting.2808638165.resource:  "" => ""
      setting.2808638165.value:     "Sun:02:00" => "Sun:02:00"
      setting.2983186660.name:      "UpdateLevel" => "UpdateLevel"
      setting.2983186660.namespace: "aws:elasticbeanstalk:managedactions:platformupdate" => "aws:elasticbeanstalk:managedactions:platformupdate"
      setting.2983186660.resource:  "" => ""
      setting.2983186660.value:     "minor" => "minor"
      setting.3007260544.name:      "AssociatePublicIpAddress" => "AssociatePublicIpAddress"
      setting.3007260544.namespace: "aws:ec2:vpc" => "aws:ec2:vpc"
      setting.3007260544.resource:  "" => ""
      setting.3007260544.value:     "true" => "true"
      setting.3172159480.name:      "ELBSubnets" => "ELBSubnets"
      setting.3172159480.namespace: "aws:ec2:vpc" => "aws:ec2:vpc"
      setting.3172159480.resource:  "" => ""
      setting.3172159480.value:     "subnet-3630230b,subnet-6a798c23,subnet-6d116547,subnet-8ea1a4d6" => "subnet-3630230b,subnet-6a798c23,subnet-6d116547,subnet-8ea1a4d6"
      setting.3225151102.name:      "MaxSize" => "MaxSize"
      setting.3225151102.namespace: "aws:autoscaling:asg" => "aws:autoscaling:asg"
      setting.3225151102.resource:  "" => ""
      setting.3225151102.value:     "2" => "2"
      setting.3276487710.name:      "" => "Application Healthcheck URL"
      setting.3276487710.namespace: "" => "aws:elasticbeanstalk:application"
      setting.3276487710.resource:  "" => ""
      setting.3276487710.value:     "" => "HTTP:80/elb-status"
      setting.335963092.name:       "" => "DBSubnets"
      setting.335963092.namespace:  "" => "aws:ec2:vpc"
      setting.335963092.resource:   "" => ""
      setting.335963092.value:      "" => "subnet-3630230b,subnet-6a798c23,subnet-6d116547,subnet-8ea1a4d6"
      setting.337125008.name:       "" => "SSHSourceRestriction"
      setting.337125008.namespace:  "" => "aws:autoscaling:launchconfiguration"
      setting.337125008.resource:   "" => ""
      setting.337125008.value:      "" => "tcp, 22, 22, sg-9f9946e4"
      setting.37040285.name:        "ServiceRole" => "ServiceRole"
      setting.37040285.namespace:   "aws:elasticbeanstalk:environment" => "aws:elasticbeanstalk:environment"
      setting.37040285.resource:    "" => ""
      setting.37040285.value:       "aws-elasticbeanstalk-service-role" => "aws-elasticbeanstalk-service-role"
      setting.3909253589.name:      "VPCId" => "VPCId"
      setting.3909253589.namespace: "aws:ec2:vpc" => "aws:ec2:vpc"
      setting.3909253589.resource:  "" => ""
      setting.3909253589.value:     "vpc-581ad93f" => "vpc-581ad93f"
      setting.417274623.name:       "InstanceType" => "InstanceType"
      setting.417274623.namespace:  "aws:autoscaling:launchconfiguration" => "aws:autoscaling:launchconfiguration"
      setting.417274623.resource:   "" => ""
      setting.417274623.value:      "m3.medium" => "m3.medium"
      setting.43215759.name:        "SecurityGroups" => "SecurityGroups"
      setting.43215759.namespace:   "aws:autoscaling:launchconfiguration" => "aws:autoscaling:launchconfiguration"
      setting.43215759.resource:    "" => ""
      setting.43215759.value:       "sg-b445c3c4" => "sg-b445c3c4"
      setting.733236782.name:       "IamInstanceProfile" => "IamInstanceProfile"
      setting.733236782.namespace:  "aws:autoscaling:launchconfiguration" => "aws:autoscaling:launchconfiguration"
      setting.733236782.resource:   "" => ""
      setting.733236782.value:      "profile" => "profile"

Expected Behavior

No change should be detected

Actual Behavior

Terraform thinks I've made a change

Steps to Reproduce

  1. Run terraform apply
  2. Run terraform apply again with no changes
@stuffandthings
Copy link
Author

I narrowed it down to an issue with these two setting options. My current workaround is to just comment them out:

  setting {
    namespace = "aws:elasticbeanstalk:application"
    name      = "Application Healthcheck URL"
    value     = "HTTP:80/elb-status"
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SSHSourceRestriction"
    value     = "tcp, 22, 22, ${var.bastion_security_group}"
  }

@Ninir Ninir added the bug Addresses a defect in current functionality. label Aug 23, 2017
@stuffandthings
Copy link
Author

One of the side effects of this ends up being a security critical issue. Not being able to configure SSHSourceRestriction to avoid the constant refreshes by default will keep port 22 open to the world.

@mbklein
Copy link

mbklein commented May 11, 2018

I'm having this issue as well. I can't not use the Application Healthcheck URL without compromising my deployment, so I'm stuck letting it update every environment on each apply.

@DanielSchaffer
Copy link

DanielSchaffer commented Jun 14, 2018

This also happens with the aws:autoscaling:launchconfiguration IamInstanceProfile setting. Looks like the setting ID changes every time.

@ppemmaraju-ellevest
Copy link

ppemmaraju-ellevest commented Jun 14, 2018

Terraform v0.11.7

  • provider.aws v1.13.0
    aws:autoscaling:launchconfiguration
    IamInstanceProfile has no issues.
    SSHSourceRestriction - issues if you use a resource reference. no issues if a cidr is directly provided.

But running into issues with:
setting {
name = "SSLReferencePolicy"
namespace = "aws:elb:policies:TLSHighPolicy"
value = "ELBSecurityPolicy-TLS-1-2-2017-01"
}

@hshafy
Copy link
Contributor

hshafy commented Jun 21, 2018

I'm also facing the same issue, any update or work around?

@arturstorm
Copy link

It's annoying to wait 10 min for beanstalk update even there no changes

@chucknelson
Copy link

+1 - Also facing this issue which causes unnecessary deployment time.

@mattboston
Copy link

mattboston commented Sep 11, 2018

+1 I'm having this issue as well

<> terraform version
Terraform v0.11.8

  • provider.aws v1.33.0

@sertaco
Copy link

sertaco commented Sep 20, 2018

Any update on this? Having the same issue when using aws:autoscaling:launchconfiguration IamInstanceProfile setting. I have to give an instance profile. Is there any workaround to suppress updates?

@RobertPaulson90
Copy link

Same problems... Really a PITA

@mbklein
Copy link

mbklein commented Oct 1, 2018

@mitchellh Any chance of getting some official word on this? It's a pretty big usability issue.

@caJaeger
Copy link

caJaeger commented Feb 27, 2019

I have to agree that this is pretty serious, it's completely crippling my IaC, not only does this apply every time for no reason, it also prevents other resources from being updated because it fails to update constantly with:

aws_elastic_beanstalk_environment.default: Error waiting for Elastic Beanstalk Environment (e-nwn8rhh3xs) to become ready: 2 errors occurred:
	* 2019-02-27 19:33:27.54 +0000 UTC (e-nwn8rhh3xs) : Service:AmazonCloudFormation, Message:No updates are to be performed.
	* 2019-02-27 19:33:28.574 +0000 UTC (e-nwn8rhh3xs) : Environment tag update failed.

This is pretty much unusable for my purposes.

@GarlicDipping
Copy link

GarlicDipping commented Apr 2, 2019

Any updates??? Seems like IamInstanceProfile and SecurityGroups settings force this change...

*Edit
So, after searching a bit, I found out that

  1. For IamInstanceProfile setting, Use name instead of id. Using id field will make terraform think your beanstalk environment changed.
  2. Don't use 'awseb' name prefix with security group. AWS Provider will ignore if security group's name starts with it. Here is the code reference.

@rpadovani
Copy link

Another important point for the SSHSourceRestriction setting: do NOT put spaces after commas.

This will trigger an update, so do not use it:

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SSHSourceRestriction"
    value     = "tcp, 22, 22, ${var.bastion_security_group}"
  }

while this WILL NOT:

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SSHSourceRestriction"
    value     = "tcp,22,22,${var.bastion_security_group}"
  }

@andrewjeffree
Copy link

So I found a bug in the beanstalk API almost a year ago that essentially meant they were returning null values in certain situations with SSHSourceRestriction. They emailed me this morning say it should be fixed now, perhaps it'll solve this problem.

@krunalsabnis
Copy link

krunalsabnis commented Jul 25, 2019

I have this issues with many other elements. see below (- & +) removing and adding.
Terraform v0.12.3

  • provider.archive v1.2.2

  • provider.aws v2.20.0

    /+ setting {
    + name = "Subnets"
    + namespace = "aws:ec2:vpc"
    + value = "subnet-0533bc84xxxxx, subnet-0849547f75xxxx"
    }
    - setting {
    - name = "Subnets" -> null
    - namespace = "aws:ec2:vpc" -> null
    - value = "subnet-0533bc84xxxxx,subnet-0849547f75xxxx" -> null
    }
    - setting {
    - name = "Unit" -> null
    - namespace = "aws:autoscaling:trigger" -> null
    - value = "Percent" -> null
    }
    + setting {
    + name = "Unit"
    + namespace = "aws:autoscaling:trigger"
    + value = "Percent"
    }
    - setting {
    - name = "UpperThreshold" -> null
    - namespace = "aws:autoscaling:trigger" -> null
    - value = "70" -> null
    }
    + setting {
    + name = "UpperThreshold"
    + namespace = "aws:autoscaling:trigger"
    + value = "70"
    }
    - setting {
    - name = "VPCId" -> null
    - namespace = "aws:ec2:vpc" -> null
    - value = "vpc-095dee784a4382c63" -> null
    }
    + setting {
    + name = "VPCId"
    + namespace = "aws:ec2:vpc"
    + value = "vpc-095dee784a4382c63"
    }

@rpadovani
Copy link

* /+ setting {
  + name      = "Subnets"
  + namespace = "aws:ec2:vpc"
  + value     = "subnet-0533bc84xxxxx, subnet-0849547f75xxxx"
  }
  - setting {
  - name      = "Subnets" -> null
  - namespace = "aws:ec2:vpc" -> null
  - value     = "subnet-0533bc84xxxxx,subnet-0849547f75xxxx" -> null
  }

@krunalsabnis this is because you have a space between the first and the second subnet, after the comma.
Try removing the space in the value, and it should stop this behavior

@jborrey
Copy link

jborrey commented Aug 4, 2019

I observed ultra strange behavior - the post by @GarlicDipping prompted me to try this, so thanks!

My EB deployment had a bunch of custom settings, and each Terraform apply would re-apply these settings as a no-op. These were settings like subnets, sgs, load balancer settings, service role, instance profile, etc.

I changed only the IamInstanceProfile from a full ARN to just the name, and instantly the entire problem went away for all settings.

Previous: arn:aws:iam::xxx:instance-profile/eb-ec2-role
After: eb-ec2-role

Update: In a different EB app, this trick didn't resolve the problem.

@Rmannn
Copy link

Rmannn commented Aug 20, 2019

Adding resource = "" to setting section fixes my issue.

@mmulligan03
Copy link

mmulligan03 commented Aug 21, 2019

  • setting {
    - name = "UpperThreshold" -> null
    - namespace = "aws:autoscaling:trigger" -> null
    - value = "60" -> null
    }
  • setting {
    + name = "UpperThreshold"
    + namespace = "aws:autoscaling:trigger"
    + value = "60"
    }

Similar to @krunalsabnis I get this for every setting when applying terraform to Beanstalk environment Using terraform v 0.12.6.

@mleonhard
Copy link

Bug is present in provider "aws" { version = "~> 2.30" } released 2019-09-26.

Two changes work around it for me:

  1. Add resource="" to each setting section. (Thanks @Rmannn ! 👍)
  2. Stop including settings which Elastic Beanstalk will ignore and not return in queries.

Working version:

resource "aws_elastic_beanstalk_environment" "api_service" {
  name = "${var.instance_name}-api-service"
  application = aws_elastic_beanstalk_application.api_service.name
  cname_prefix = "com-company-${var.instance_name}-api"
  version_label = aws_elastic_beanstalk_application_version.api_service.name
  # https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html
  solution_stack_name = "64bit Amazon Linux 2018.03 v2.9.2 running Java 8"

  # https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-elasticbeanstalkenvironment
  # Prod & Staging get expensive Load Balancers.  Other deployments get cheap Elastic IPs.
  setting {
    namespace = "aws:elasticbeanstalk:environment"
    name = "EnvironmentType"
    value = var.is_prod_or_staging ? "LoadBalanced" : "SingleInstance"
    // These empty 'resource' values prevent updating the environment on every apply.
    // See https://github.com/terraform-providers/terraform-provider-aws/issues/1471#issuecomment-522977469
    resource = ""
  }

  // Include the 'LoadBalancerType' setting only in Prod/Staging deployments.
  // The Beanstalk API ignores the LoadBalancerType setting when EnvironmentType=SingleInstance.
  // When Terraform queries the application's settings, the Beanstalk API does not return the
  // LoadBalancerType entry, so Terraform tries to add it.  This makes Terraform update the
  // application on *every* apply.
  // See https://github.com/terraform-providers/terraform-provider-aws/issues/1471#issuecomment-522977469
  // This 'dynamic' ugly hack is required because Terraform has no conditionals.
  // See https://github.com/hashicorp/terraform/issues/19853
  // TODO(dev1) Switch to Pulumi once it's mature enough and get away from this nonsense.
  dynamic "setting" {
    for_each = var.is_prod_or_staging ? [
      1] : []
    content {
      namespace = "aws:elasticbeanstalk:environment"
      name = "LoadBalancerType"
      # classic, application, or network
      value = "application"
      resource = ""
    }
  }
...

@UdhavPawar
Copy link

Faced exact same issue. What solved the issue for me (these are not my solutions, found them from reading this and other posts):

  1. Add resource = "" in every environment setting
  2. Remove space between subnets that you are passing to the VPC setting of environment
  3. Remove the environment setting for BeanStalk to send default GET requests to custom healthcheck path, instead update load-balancer healthcheck path with custom path
  4. update the gateway_id to nat_gateway_id if you are attaching NAT GW to a private subnet's route table

Hope these help :)

@ghost
Copy link

ghost commented Feb 13, 2020

Same issue here when trying to use aws:elb:policies:backendkey PublicKey, Terraform force the update with exactly the same certificate PEM content.

  setting {
    namespace = "aws:elb:policies:backendencryption"
    name      = "PublicKeyPolicyNames"
    value     = "backendkey"
    resource  = ""
  }

  setting {
    namespace = "aws:elb:policies:backendencryption"
    name      = "InstancePorts"
    value     = "443"
    resource  = ""
  }

  setting {
    namespace = "aws:elb:policies:backendkey"
    name      = "PublicKey"
    value     = tls_self_signed_cert.backend.cert_pem
    resource  = ""
  }

EDIT: To fix this issue, the public key must be passed instead of the certificate and it must be formatted to contain only the raw key:

  setting {
    namespace = "aws:elb:policies:backendencryption"
    name      = "PublicKeyPolicyNames"
    value     = "backendkey"
    resource  = ""
  }

  setting {
    namespace = "aws:elb:policies:backendencryption"
    name      = "InstancePorts"
    value     = "443"
    resource  = ""
  }

  setting {
    namespace = "aws:elb:policies:backendkey"
    name      = "PublicKey"
    value     = replace(replace(tls_private_key.backend.public_key_pem, "/-----[A-Z ]+-----/", ""), "/\\s/", "")
    resource  = ""
  }

@montross50
Copy link

montross50 commented Apr 10, 2020

As others have mentioned, you need to watch out for spaces in your subnets. In addition the subnets appear to be sorted alphabetically.

setting {
    namespace = "aws:ec2:vpc"
    name      = "Subnets"
    value     = join(",", sort(var.private_subnets))
    resource  = ""
  }

where var.private_subnets is a list(string) of subnets fixed my issue.

@DanielSchaffer
Copy link

One other thing I just noticed was that when you have lists of things (subnets, security groups), sometimes they come back in a different order than your TF config specifies, so it detects a diff every time. Reorder the entries in the value to match what's coming back, and it should be set. That, plus the resource = "" hack is what fixed it all for me.

@oirtemed
Copy link

Still experience this with terraform 0.14.10 and the aws provider 3.22.0 and the resource = "" in the setting.

  # module.eb-name.aws_elastic_beanstalk_environment.default will be updated in-place
  ~ resource "aws_elastic_beanstalk_environment" "default" {
        id                     = "e-xxxxxxxxxx"
        name                   = "eb-name"
        tags                   = {}
        # (15 unchanged attributes hidden)

      + setting {
          + name      = "ConfigDocument"
          + namespace = "aws:elasticbeanstalk:healthreporting:system"
          + value     = jsonencode(
                {
                  + Rules   = {
                      + Environment = {
                          + Application = {
                              + ApplicationRequests4xx = {
                                  + Enabled = false
                                }
                            }
                          + ELB         = {
                              + ELBRequests4xx = {
                                  + Enabled = true
                                }
                            }
                        }
                    }
                  + Version = 1
                }
            )
        }
      - setting {
          - name      = "ConfigDocument" -> null
          - namespace = "aws:elasticbeanstalk:healthreporting:system" -> null
          - value     = jsonencode(
                {
                  - Rules   = {
                      - Environment = {
                          - Application = {
                              - ApplicationRequests4xx = {
                                  - Enabled = false
                                }
                            }
                          - ELB         = {
                              - ELBRequests4xx = {
                                  - Enabled = true
                                }
                            }
                        }
                    }
                  - Version = 1
                }
            ) -> null
        }

I think this happens because jsonencode() orders the document and EB is expecting it in a specific order

related -> hashicorp/terraform#27880

@echoboomer
Copy link

This is still an issue in 3.74.0. How has this not been resolved? This is an absolute show stopper when it comes to creating or managing Elastic Beanstalk applications in Terraform - especially if you're importing an existing one. This creates a giant blindspot in an organization's ability to guarantee that infrastructure can be reliably managed using one tool.

@azban
Copy link

azban commented Feb 3, 2022

seems like the workaround from #1471 (comment) works for almost all cases.

@echoboomer
Copy link

seems like the workaround from #1471 (comment) works for almost all cases.

It does not work in my case whatsoever.

@azban
Copy link

azban commented Feb 3, 2022

does it work after the first apply? have been using it for a few months and not had any of the same issues. there seem to be some underlying implicit configuration setting that happens that will update the state transparently on future plans, but plans have no updates.

@echoboomer
Copy link

does it work after the first apply? have been using it for a few months and not had any of the same issues. there seem to be some underlying implicit configuration setting that happens that will update the state transparently on future plans, but plans have no updates.

Great question. I have an app that was created from the start using Terraform that I'll add resource = "" to each setting and see if that helps. In this case, I'm dealing with an imported environment. It seems risky to do an apply without knowing what it will actually alter, but there may be no choice.

@azban
Copy link

azban commented Feb 3, 2022

yea, not sure there is a good way to automate that process, but there's only so many settings to go through, so it may be bearable for manual review if you only have a few environments. 🤷

@SamuelNorbury
Copy link

SamuelNorbury commented Feb 4, 2022

A workaround that seems to have worked for my team is adding resource = "" to every setting, as well as sorting any interpolated strings, like:

  setting {
    namespace = "aws:autoscaling:asg"
    name      = "Availability Zones"
    value     = "Any"
    resource  = ""                                           # Add an empty resource
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SecurityGroups"
    value     = join(",", sort([data.aws_security_group.this.id, data.aws_security_group.that.id]))     # Use join() and sort()
    resource  = ""
  }

@g4rb1 correct me if I'm wrong.

@snipergotya
Copy link

setting {
    name      = "SSHSourceRestriction"
    namespace = "aws:autoscaling:launchconfiguration"
    value     = "tcp,22,22,192.0.0.34/32"
    resource = ""
  }

Every time I use this option it causes my beanstalk to require an update. if i comment it out it works fine.

I'd like to make sure its included, any way to resolve this?

Also I'm not specifying the keypair setting, i'm wondering does it need to be used in conjunction with the keypair setting to work?

@epomatti
Copy link

Adding resource = "" solved it. Both tf and provider are the latest versions.

@khavishbhundoo
Copy link

khavishbhundoo commented May 26, 2023

Any idea how to fix DBSubnets ?

resource "aws_elastic_beanstalk_environment" "eb_env" {
        id                     = "e-zfvjkxrhap"
        name                   = "api-prod"
        tags                   = {}
        # (17 unchanged attributes hidden)

      + setting {
          + name      = "DBSubnets"
          + namespace = "aws:ec2:vpc"
          + value     = "subnet-071aa19a12d37195e,subnet-083bb9cec8b75cfcc"
        }
        # (27 unchanged blocks hidden)
    }

@snipergotya
Copy link

snipergotya commented May 26, 2023

depending on how you are supplying the subnets you might need to sort them. sorting them fixed my issue with subnets changing.

EG: sort(["subnet-1", "subnet-2"])

@khavishbhundoo
Copy link

@snipergotya I am already sorting the subnets

  setting {
    namespace = "aws:ec2:vpc"
    name      = "DBSubnets"
    value     = join(",", sort(module.vpc.private_subnets))
    resource  = ""
  }

@nueces
Copy link

nueces commented May 26, 2023

@khavishbhundoo try then to do a reverse before the join. You need to preset the string as terraform expect.
You can check try to inspecting the output in json format to get more clues

terraform plan -out plan.out 
terraform show -json plan.out  > plan.json

@khavishbhundoo
Copy link

khavishbhundoo commented May 26, 2023

@nueces

All i can see is the setting with the proper subnet in the json

 {
              "name": "DBSubnets",
              "namespace": "aws:ec2:vpc",
              "resource": "",
              "value": "subnet-071aa19a12d37195e,subnet-083bb9cec8b75cfcc"
},

@nueces
Copy link

nueces commented May 26, 2023

@nueces

All i can see is the setting with the proper subnet in the json

But what about the previous value that was stored? can you found it and paste it here?

@khavishbhundoo
Copy link

@nueces

There is no value for DBSubnets for elastic beanstalk in resource_changes in before section but i see DBSubnets in after section

{
              "name": "DBSubnets",
              "namespace": "aws:ec2:vpc",
              "resource": "",
              "value": "subnet-071aa19a12d37195e,subnet-083bb9cec8b75cfcc"
},

@nueces
Copy link

nueces commented May 26, 2023

Maybe trying hardcoding the values in different order to test and understand what is the expected format? try these values:

 "subnet-071aa19a12d37195e,subnet-083bb9cec8b75cfcc"
 "subnet-083bb9cec8b75cfcc,subnet-071aa19a12d37195e"
 "subnet-071aa19a12d37195e, subnet-083bb9cec8b75cfcc"
 "subnet-083bb9cec8b75cfcc, subnet-071aa19a12d37195e"

Keep in mind that the underlying issue is that the format used to store the values could be different to how terraform is displaying the data. I'm out of ideas, but good luck!

@khavishbhundoo
Copy link

@nueces I found out what the problem was. Actually I don't have an RDS attached to the environment as part of my infra but was setting the DBSubnets and therefore terraform aws provider was trying to add it on every plan. I think that unless have an RDS attached with EB env , you should not add this setting.

Contains the IDs of the database subnets. This is only used if you want to add an Amazon RDS DB Instance as part of your application. If you have multiple subnets, specify the value as a single comma-separated string of subnet IDs (for example, "subnet-11111111,subnet-22222222").
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.managing.db.html?icmpid=docs_elasticbeanstalk_console

@wosiu
Copy link

wosiu commented Aug 9, 2023

Even though I applied all suggestions in this thread, I still had the issue with:

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SecurityGroups"
    value     = aws_security_group.ec2.name
    resource  = ""
  }

it wants changes all the time.
I'm using latest aws provider 5.11.

I even tried to change name f the security group to start with "aaa" to ensure it is first in order when sorting with default security group, but nope, doesn't help.

@wosiu
Copy link

wosiu commented Aug 11, 2023

Huh, it seems the problem with SecurityGroups is because AWS appends defaults beanstalk SG to the list, after apply.
I know that because when I printed aws_elastic_beanstalk_environment.this.all_settings, I can see one of the fields:

  {
    "name" = "SecurityGroups"
    "namespace" = "aws:autoscaling:launchconfiguration"
    "resource" = ""
    "value" = "my-auxiliary-security-group20230809193328268400000001,awseb-e-sztdahgqve-stack-AWSEBSecurityGroup-RUNCCJX5WPXC"
  },

@avazula
Copy link

avazula commented Jan 30, 2024

The issue is still valid as of Jan 2024, regardless of the workarounds mentioned above. Is there really nothing to be done about it?

@emanuele-scarsella
Copy link

The issue is still valid as of Feb 2024

@peterdudfield
Copy link

I'm still getting this issue

Interestingly I dont get it here, but I do have the issue here
but I dont really understand the differentce

terraform version 1.7.2, aws version ~> 5.0

@peterdudfield
Copy link

peterdudfield commented Apr 30, 2024

I'm still getting this issue

Interestingly I dont get it here, but I do have the issue here but I dont really understand the differentce

terraform version 1.7.2, aws version ~> 5.0

I solved it with

  • adding resource="" to lots of settings
  • fixing namespace = "aws:elb:listener" to namespace = "aws:elb:listener:80"

@kamaradski
Copy link

kamaradski commented Jun 17, 2024

Yup beanstalk is still a pain in terraform (June 2024). I managed to fix all my issues with the above mentioned solutions apart from:

- setting {
          - name      = "HostHeaders" -> null
          - namespace = "aws:elbv2:listenerrule:api" -> null
          - value     = "api.redacted.com,ec1-eb-api-dev.eba-redacted.eu-central-1.elasticbeanstalk.com" -> null
            # (1 unchanged attribute hidden)
        }
      + setting {
          + name      = "HostHeaders"
          + namespace = "aws:elbv2:listenerrule:api"
          + value     = "api.redacted.com"
            # (1 unchanged attribute hidden)
        }
      + setting {
          + name      = "ManagedSecurityGroup"
          + namespace = "aws:elbv2:loadbalancer"
          + value     = "sg-017ce2a9a9f87ced7"
            # (1 unchanged attribute hidden)
        }

resulting from:

variable "eb_dev_api_config" {
  description = "settings for DEV API"

  type = object({
    listenerruleName                               = string
    listenerruleHostHeaders                        = string
    ~
  })
  default = {
    listenerruleName         = "api"                # loadbalancer listener rule name
    listenerruleHostHeaders  = "api.redacted.com" # hostname to match this rule
    ~
  }
}


resource "aws_elastic_beanstalk_environment" "eb_api_dev" {
~
  setting {
    namespace = "aws:elbv2:listenerrule:${var.eb_dev_api_config.listenerruleName}"
    name      = "HostHeaders"
    value     = var.eb_dev_api_config.listenerruleHostHeaders
    resource  = ""
  }
  ~
  setting {
      namespace = "aws:elbv2:loadbalancer"
      name      = "ManagedSecurityGroup"
      value     = aws_security_group.eb_lb_sg_dev.id
      resource  = ""
    }
  ~
}

PS:
for those recommending to remove spaces in lists etc.. please note that these spaces are part of the terraform styleguide and using LINT would always put these spaces back. https://developer.hashicorp.com/terraform/language/functions/formatlist

@hdodov
Copy link

hdodov commented Sep 6, 2024

Like @wosiu, I had the same issue, where the SecurityGroups setting would trigger changes, since Elastic Beanstalk automatically appends its own security group:

- setting {
    - name      = "SecurityGroups" -> null
    - namespace = "aws:autoscaling:launchconfiguration" -> null
    - value     = "my-custom-group,awseb-e-axyhk2fb5a-stack-AWSEBSecurityGroup-EjnP0DRwqyFQ" -> null
      # (1 unchanged attribute hidden)
  }
+ setting {
    + name      = "SecurityGroups"
    + namespace = "aws:autoscaling:launchconfiguration"
    + value     = "my-custom-group"
      # (1 unchanged attribute hidden)
  }

The solution here was to simply add the default security group myself:

data "aws_security_group" "default_eb_group" {
  tags = {
    "aws:cloudformation:logical-id"     = "AWSEBSecurityGroup"
    "elasticbeanstalk:environment-name" = "my-env-name"
  }
}

resource "aws_elastic_beanstalk_environment" "default" {
  name = "my-env-name"
  // ...
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SecurityGroups"
    value     = "my-custom-group,${data.aws_security_group.default_eb_group.name}"
    resource  = ""
  }
}

This works because:

  1. aws:cloudformation:logical-id is a tag that EB always creates and is equal to AWSEBSecurityGroup, so we specifically filter out the auto-generated security group.
  2. elasticbeanstalk:environment-name is a tag that EB always creates and it matches your EB environment name. We need this because there may be multiple EB environments with the AWSEBSecurityGroup tag, so this way we get the one specifically for this environment.

This, combined with the resource = "" trick, and I get the desired outcome when running terraform plan:

No changes. Your infrastructure matches the configuration.

Site note: You currently can't prevent Elastic Beanstalk from creating its default security group: aws/elastic-beanstalk-roadmap#44 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Addresses a defect in current functionality. service/elasticbeanstalk Issues and PRs that pertain to the elasticbeanstalk service.
Projects
None yet
Development

No branches or pull requests