Reputation: 508
I'll be running a Rails application on Elastic Beanstalk and I'll have both Web and Worker environments. The problem is that, since they both share the same code, I need to run some specific ebextensions on the worker environment (to initialize the worker process) and some specific scripts on the web (to initialize the app server). How can I separate the two scripts on different folders inside .ebextensions folder and tell Elastic Beanstalk to run then according to an environment variable?
Thanks,
Upvotes: 3
Views: 2119
Reputation: 1118
Here's an approach that is not ideal but that works. Always run the same steps in all environments. Write a shell script to encapsulate the commands you want to conditionally run. Have the shell script test for the existence of an environment variable and run the commands if that environment variable is set. Here's an illustration on how to implement this:
.ebextensions/worker_job.config
files:
"/home/webapp/worker_job.sh" :
mode: "000755"
owner: webapp
group: webapp
content: |
#!/bin/sh
if [ -z "$RUN_WORKER_JOB" ]; then
echo 'RUN_WORKER_JOB is not set, skipping RUN_WORKER_JOB';
else
echo 'RUN_WORKER_JOB is set, running RUN_WORKER_JOB'
# run useful worker commands
fi
container_commands:
00_worker_job:
command: /home/webapp/worker_job.sh
RUN_WORKER_JOB
on selected environmentsUsing the AWS console, select the environment you want the commands to run in. Open the Software Configuration
tool and set an environment variable called RUN_WORKER_JOB
. Make sure that environment variable is not set in the environments you don't want your commands to run in.
Set a convention and call the scripts, variables and files in a consistent way: worker_job.sh
, worker_job.config
, RUN_WORKER_JOB
, etc...
Upvotes: 3
Reputation: 6632
Altogether I think this is a missing feature that AWS ought to offer first-class support for in the future, or more obvious and coherent first-class support—saved configurations help for EB option settings and resources (extra custom infrastructure), but I don't believe they can include on-instance commands, and their distinction and precedence from .ebextensions
is messy and confusing for a team to have to understand (you can define resources and settings in either .ebextensions
files or saved configurations…). EB is clearly designed for one application to have multiple environments, so .ebextensions
unawareness of that seems conspicuous.
Solutions like @yacc's are workable for situations that boil down to minor differences in scripts between environments, which might suffice for the OP's question. It gets messy though, and doesn't help at all for EB configuration and custom resources instead of on-instance commands, such as if I want to enable a bunch of custom CloudWatch metrics or a multi-instance ElastiCache cluster only for production and/or worker environments, but not staging.
For that, saved configurations can help:
$ eb config save staging
$ cp .elasticbeanstalk/saved_configs/{staging,production}-sc.cfg.yml
# Add production-specific option settings, resources, etc.:
$ $EDITOR .elasticbeanstalk/saved_configs/production-sc.cfg.yml
# Save the config to S3:
$ eb config put production --cfg production-sc
# Apply the config to the environment:
$ eb config production --cfg production-sc
I remove any secrets from the saved configs like sensitive environment variable values and then check .elasticbeanstalk/saved_configs
into source control for repeatable environment recreation in the future. (This [useful] article suggests that moving the files into the root of .elasticbeanstalk/
may be preferable for the CLI's .gitignore
conventions). Of course you could do first-time production env setup in the web console and then save and modify that, instead of starting from a copy of staging.
It might also be possible to achieve some of this within .ebextensions
files using CloudFormation condition functions for resources—I haven't tried this yet but I'll update my answer if I have the chance to find what input parameters EB gives to CloudFormation (it looks like AWSEBEnvironmentName
will work).
Upvotes: 2