Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Environment specific ebextensions Beanstalk commands

I have a spring-boot application for which I need to specify graphite server and port (to send metrics). For that to work, I have to install and configure statsd. I do that using the ebextensions file.

commands:
  01_nodejs_install:
    command: sudo yum -y install nodejs npm --enablerepo=epel
    ignoreErrors: true

  02_mkdir_statsd:
    command: mkdir /home/ec2-user/statsd
    ignoreErrors: true

  03_fetch_statsd:
    command: git clone https://github.com/etsy/statsd.git /home/ec2-user/statsd
    ignoreErrors: true

  04_change_example_config:
    command: "cat exampleConfig.js | sed 's/2003/<graphite-port>/g' | sed 's/graphite.example.com/<my-graphite-server>/g' > config.js"
    cwd: /home/ec2-user/statsd

  05_run_statsd:
    command: setsid node stats.js config.js >/dev/null 2>&1 < /dev/null &
    cwd: /home/ec2-user/statsd

The problem with this configuration is that I can specify only 1 graphite server here for all environments.

So I decided to move commands 04 and 05 into container_commands. I am thinking of defining an environment variable called ENV_NAME using the beanstalk console/UI, and set it to dev, qa, or prod according to the environment. Then I can use test option of container_commands to run 04 and 05 commands only for specific environment based on this ENV_NAME.

So my problem is - how can I use AWS console to define environment variable? I tried using Beanstalk console to define my variable as explained in the documentation here but it did not work. I also found (see the answer with 5 upvotes) that this method sets only JVM properties and not ENV variables.

I cannot define environment variable using ebextensions because then I'll have the same problem - can't define different env vars for different envs :)

So I need help with either:

  • Set the ENV_NAME environment variable using beanstalk UI.

Or

  • Suggest a way to use ENV_NAME system property in container_commands to condition whether or not to run the command based on the value of ENV_NAME.

And in case you know a simpler/better way to specify different Graphite servers for different environments, please feel free to pitch in.

like image 568
Nik Avatar asked Jun 08 '16 03:06

Nik


People also ask

How do you use Ebextensions in Elastic Beanstalk?

You can add AWS Elastic Beanstalk configuration files ( . ebextensions ) to your web application's source code to configure your environment and customize the AWS resources that it contains. Configuration files are YAML- or JSON-formatted documents with a . config file extension that you place in a folder named .

How do I view environment variables in Elastic Beanstalk?

On AWS, open Elastic Beanstalk. Go to your Application > Environment > Configuration > Software Configuration . Under Environment Properties you will find a list of properties you can configure. These variables will be attached to the process.


2 Answers

The way I resolved this was to define ENV_NAME as dev and prod in dev and prod environments respectively and use the following ebextensions configuration.

commands:
  01_nodejs_install:
    command: sudo yum -y install nodejs npm --enablerepo=epel
    ignoreErrors: true

  02_mkdir_statsd:
    command: mkdir /home/ec2-user/statsd
    ignoreErrors: true

  03_fetch_statsd:
    command: git clone https://github.com/etsy/statsd.git /home/ec2-user/statsd
    ignoreErrors: true

container_commands:
  04a_container_change_example_config:
    command: "cat exampleConfig.js | sed 's/2003/<graphite-dev-port>/g' | sed 's/graphite.example.com/<graphite-dev-host>/g' > config.js"
    cwd: /home/ec2-user/statsd
    test: '[ "${ENV_NAME}" == "dev" ]'

  04b_container_change_example_config:
    command: "cat exampleConfig.js | sed 's/2003/<graphite-prod-port>/g' | sed 's/graphite.example.com/<graphite-prod-host>/g' > config.js"
    cwd: /home/ec2-user/statsd
    test: '[ "${ENV_NAME}" == "prod" ]'

  05_run_statsd:
    command: setsid node stats.js config.js >/dev/null 2>&1 < /dev/null &
    cwd: /home/ec2-user/statsd

Using test I can condition the execution of the container command on the ENV_NAME property which I have already defined in the beanstalk environment.

like image 105
Nik Avatar answered Nov 02 '22 20:11

Nik


In addition to the answer by @Nik:

Instead of manually adding an environment variable ENV_NAME, you could also obtain the actual environment name and store that in ENV_NAME automatically. This is achieved using option_settings in your ebextensions config file.

For example:

option_settings:
  aws:elasticbeanstalk:application:environment:
    ENV_NAME: '`{ "Ref" : "AWSEBEnvironmentName" }`'  # assign the actual env name to ENV_NAME

container_commands:
  0100_execute_only_in_dev:
    command: echo "this is the development environment"  # this will turn up in ebactivity.log
    test: '[[ $ENV_NAME = "dev" ]]'

A side note, for those who are not so familiar with shell scripting, like me: the spaces in the test expression are important (example).

Update: Amazon Linux 2

As of 2021, Amazon Linux 2 is the new standard. Amazon Linux 2 uses platform hooks instead of the container_commands in .ebextensions.

Here's a bash script equivalent to the 0100_execute_only_in_dev container command defined above, that can be used as a platform hook on Amazon Linux 2:

0100_execute_only_in_dev.sh

#!/bin/bash
if [ $ENV_NAME = "dev" ]
# the following output will end up in "/var/log/eb-hooks.log"
then echo "this is the development environment" 
fi

The shell script requires execution permission, as described here, and can be placed in any of the subdirectories of .platform/hooks and/or .platform/confighooks, in your source bundle, depending on the applicable deployment phase (prebuild, predeploy, or postdeploy). See the deployment workflow for more information. It also helps to inspect /var/log/eb-engine.log, to see what exactly happens during the deployment.

Note that platform hooks also have access to the EB environment properties.

like image 27
djvg Avatar answered Nov 02 '22 21:11

djvg