aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 56 forks source link

AWS::ElasticBeanstalk::Environment - SolutionStackName change without replacement #226

Open candrews opened 5 years ago

candrews commented 5 years ago

AWS::ElasticBeanstalk::Environment-SolutionStackName change without replacement

Elastic Beanstalk supports changing the solution stack name without replacement. For example, you can do so using the CLI with this command:

aws elasticbeanstalk update-environment --solution-stack-name "64bit Amazon Linux 2018.03 v2.7.6 running Python 3.6" --environment-name "Environment1"

That will update the solution stack in place.

Managed platform updates also perform in place updates without environment replacement.

Using the console web UI to change the solution stack also performs an in place update.

However, CloudFormation always replaces the Beanstalk Environment when the SolutionStackName changes; this is documented at https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-beanstalk-environment.html where it says "Update requires: Replacement"

This restriction is very troublesome since environments that have a "CNAMEPrefix" specified cannot be replaced.

Can you please implement updating of SolutionStackName without replacement in CloudFormation?

6. Category (required) - Will help with tagging and be easier to find by other users to +1

Use the categories as displayed in the AWS Management Console (simplified):

  1. Compute (Elastic Beanstalk)
candrews commented 5 years ago

Also reported on the forums at https://forums.aws.amazon.com/message.jspa?messageID=919696

thibaut-pro commented 4 years ago

This is obviously also a blocker for AWS CDK deployments. I was trying to upgrade to the latest recommended platform version and was also blocked by this:

[~] AWS::ElasticBeanstalk::Environment Environment Environment replace
 └─ [~] SolutionStackName (requires replacement)
     ├─ [-] 64bit Amazon Linux 2018.03 v2.9.6 running Python 3.6
     └─ [+] 64bit Amazon Linux 2018.03 v2.9.7 running Python 3.6
thibaut-pro commented 4 years ago

Note that this is still a major blocker for us. We have a compliance requirement to upgrade our platform versions within 30 days of their general availability which currently requires us to spend about 2 hours creating a duplicate environment with a new name, flipping our Cloudfront distribution to point to it, and then deleting the old environment. This operation is 1-click in the console and it would be amazing for it to be the same with Cloudformation and CDK.

jusrob commented 4 years ago

Hope this helps someone. I fought this for some time and was able to work around it by defining a custom configuration template that is based on my solution stack name of choose via a configuration template resource.

I then was able to reference that resource as a template name instead of providing the solution stack name in my Environment resource definition.

I was then able to successfully change solution stacks without replacement as i was actually modifying the underlying custom configuration template. As a nice side effect i was able to collapse a lot of my CFN down by using the configuration template resource since i used a single CFN stack to build different beanstalk environments that all had 90% overlap in the options i provided via CFN.

laymonk commented 3 years ago

@jusrob, your solution is interesting.

The challenges I faced previously when I tried to do this include:

  1. Deciding what option settings to keep with Environment and what to move to ConfigurationTemplate
  2. I also encountered challenges with dependency ordering

I didn't have a great deal of time to give it, and just got rid of the ConfigurationTemplate.

Please, can you share your template structure, perhaps as a gist?

jusrob commented 3 years ago

@laymonk I don't put any option in my Environment resource and do it all in the ConfigurationTemplate. I keep a mapping of ami id, solutionstackname i can reference with a !FindInMap based on the platform type i pass in.

Mappings:
  java8:
    us-west-2:
      ImageId: ami-0c76396db552ede19 # aws-elasticbeanstalk-amzn-2.0.20210326.64bit-eb_corretto8_amazon_linux_2-hvm-2021-03-30T16-29
      SolutionStackName: 64bit Amazon Linux 2 v3.1.7 running Corretto 8

I then build conditions around the platform type (Java8, Java11, DotNet, etc). Then in my configuration template resource I wrap the options I want to be conditional on platform type like this

      - Fn::If:
        - JavaBased
        - Namespace: aws:elasticbeanstalk:application:environment # Java specific option
          OptionName: networkaddress.cache.ttl
          Value: 30
        - !Ref AWS::NoValue

So now i have a single configuration template resource I keep updated with conditionals wrapped around the option settings that are platform specific. I went from almost 4000 lines of yaml to under 1000.