Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specific git branches for aws elastic beanstalk environments

Here is my current scenario.

  • I am using AWS Elasticbeanstalk along with the eb cli 3.x tools for deployment.
  • I have created 2 environments (development and production). and one branch in my git repo for each environment (i.e. master , production)
  • I have created .ebextensions and .elasticbeanstalk folders in my git repo
  • the .ebextensions folder has config files that are specific to each environment (e.g. setups, files changes, environment variables . . etc)

I wish to work on each environment in its own git branch.

My difficulty

if i have to deploy to development env, it gets really simple

// make config changes in master branch
// git add, commit
// eb deploy
// thus development environment is updated

But if i have to deploy to production is where the problem begins

git checkout production
git merge master // pulls config that is meant for development environment only
eb deploy 

I want that when i merge changes from the master branch, all my code updates with the latest changes. But the .ebextensions and .elasticbeanstalk directories remain untouched

How do tell git to ignore the whole .ebextensions folder while merging into production branch ?

like image 846
Lloyd Avatar asked Mar 11 '15 12:03

Lloyd


People also ask

What are the two environments available in Elastic Beanstalk?

In AWS Elastic Beanstalk, you can create a load-balanced, scalable environment or a single-instance environment.

What are the three main services that Elastic Beanstalk uses to launch your application?

Elastic Beanstalk is a service for deploying and scaling web applications and services. Upload your code and Elastic Beanstalk automatically handles the deployment—from capacity provisioning, load balancing, and auto scaling to application health monitoring.

How do I link Elastic Beanstalk to GitHub?

On Source page, under Source Provider ,choose GitHub(Version 1). If you have not created GitHub connection , click on “Connect to GitHub” button to grant permission to AWS Code pipeline to access your GitHub repository. This will help AWS Code Pipeline to upload your committed changes from GitHub to AWS Code Pipeline.


2 Answers

Using EB CLI 3.x

For this version it's relatively simple. For example:

mkdir HelloWorld                 # create new directory for project
cd HelloWorld                    # enter the new directory
git init                         # create git repository
eb init -p PHP                   # create new application

echo "<?php echo getenv("ENV_NAME"); ?>" > index.php
git add .gitignore index.php
git commit -m 'Initial commit.'

eb create dev-env                # create environment named dev-env
eb create prod-env               # create environment named prod-env

eb use dev-env                   # associate dev-env to current branch (master)
eb setenv ENV_NAME=DEV           # set env variable specific to dev-env

git checkout -b production       # create production branch and switch to it
eb use prod-env                  # associate prod-env to the current branch (production)
eb setenv ENV_NAME=PROD          # set env variable specific to prod-env

This doesn't save ENV_NAME anywhere in the local filesystem. The EB CLI changes the live EB instance directly. You may use eb config save (as suggested by Nick Humrich) to save the environment configuration settings for the current running environment to .elasticbeanstalk/saved_configs/<env-name>.cfg.yml. Since each environment has its own file, you shouldn't have any conflicts, unless you change one of them in both branches. Another option (see Protecting sensitive informations) would be to add them to .gitignore.

Using EB CLI 2.x

Q: How did you create your environments?

One way is to have distinct optionsettings files for each environment (branch). The EB CLI can help you with that :-)

Run eb init from each branch (see below) and choose a different environment name for each one, so you'll end up with 2 distinct .elasticbeanstalk/optionsettings.<env-name> files. This way you avoid the conflicts on .elasticbeanstalk/.

1. Create the project directory

mkdir MyApp
cd MyApp

2. Initialize Git repository

git init .

3. Setup the development environment (master branch)

eb init

NOTE: When it asks you to provide an environment name, choose a name that identifies whether it's a development or production environment.

Enter your AWS Access Key ID (current value is "<redacted>"): 
Enter your AWS Secret Access Key (current value is "<redacted>"): 
Select an AWS Elastic Beanstalk service region.
Available service regions are:
<redacted>
Select (1 to 8): 1
Enter an AWS Elastic Beanstalk application name
(auto-generated value is "MyApp"): MyApp      
Enter an AWS Elastic Beanstalk environment name
(auto-generated value is "MyApp-env"): MyApp-dev
Select an environment tier.
Available environment tiers are:
1) WebServer::Standard::1.0
2) Worker::SQS/HTTP::1.0
Select (1 to 2): 1
Select a solution stack.
Available solution stacks are:
<redacted>
Select (1 to 59): 32
Select an environment type.
Available environment types are:
1) LoadBalanced
2) SingleInstance
Select (1 to 2): 2
Create an RDS DB Instance? [y/n]: n
Attach an instance profile (current value is "[Create a default instance profile]"):
<redacted>
Select (1 to 5): 4

4. Create a new branch for production

git checkout -b production

5. Setup the production environment

eb init

Repeat step 3 but pick a different environment name. This will create distinct .elasticbeanstalk/optionsettings.<env-name> file.

Q: What about my .ebextensions?

You should use the same app.config for both environments. The only thing that may diverge between environments is the option_settings section. But as far as I know, you can't have different option_settings per environment, so how can we do it?

Well, that's something I don't have an optimal solution yet, but I'll tell you how I do it. I add all option_name's I need and use placeholder values, for example:

option_settings:
  - option_name: MY_CONFIG
    value: CHANGEME

Then later I change their values manually through the AWS Elastic Beanstalk admin panel. Go to Application > Configuration > Software Configuration > Environment Properties.

Another possibility would be to have a custom script which is run by your container_commands. This script could identify the EC2 instance by its hostname (or another unique value) and automatically load the environment variables (e.g. source <hostname>.env).

Protecting sensitive informations

The only rule you need to obey is this: Your repository MUST NOT contain sensitive informations like credentials, unless you don't care.

For example, an application expects to read RDS credentials via environment variables, so you put them in option_settings. But you don't want other contributors to see them, do you? The solution I propose using placeholder is convenient on this aspect.

like image 80
jweyrich Avatar answered Oct 04 '22 13:10

jweyrich


You can merge master to production and production to master. However, after every merge, you have to reset the working tree of the folders in question. Here is how you can do this.

git checkout production
git merge --no-commit --no-ff master
git reset /path/to/[.ebextensions and .elasticbeanstalk]/folders
git commit
git push

Also, you may forget to reset after every merge so I suggest you set up a post-merge hook to do this automatically for the respective branches after every merge.

like image 22
Noman Ur Rehman Avatar answered Oct 04 '22 12:10

Noman Ur Rehman