Elastic Beanstalk - deploy from different machines / by different users (or how to get rid of absolute paths in configs)
By default Elastic Beanstalk console tool (eb) adds config files to .gitignore. If there are manual changes to EB configs it can be complex to manually sync these changes between different machines / different users. Of cause it is possible to add config files to git repository but there are also several parameters in the main config which are absolute paths to local files. This way it makes configs not useful for other users (except for the case when different users have exactly the same files layout). Here is how this problem can be fixed:
- Add eb tools under git control
- Add eb configs under git control
- Patch eb tools to accept relative file paths
- Change paths in configs to relative
Below are details for each step.
Add eb tools under git control
This is necessary because we want all users to have the same tools version. Also we are going to make some changes to eb sources to make it understand relative paths.
Just download eb tools and extract somewhere inside your project. Or copy existing version into the project.
Add a wrapper script to run the original eb tool:
#!/bin/sh
# Run the eb tool from the root project directory as
# console/eb {parameters}
# Use linux python2.7 version
SCRIPT_PATH=`dirname $0`
export PATH=$PATH:$SCRIPT_PATH/AWS-ElasticBeanstalk-CLI-2.5.1/eb/linux/python2.7
eb "$@"
Script should be on the same lever as the extracted directory. For example I have:
project_root/
| .ebextensions/
| .elasticbeanstalk/
| .git/
| application/
| console/
| | AWS-ElasticBeanstalk-CLI-2.5.1/
| | eb*
| | ...
| ...
| .gitignore
So I launch the 'eb' as 'console/eb parameters' from the project root directory.
Add eb configs under git control
Add the EB configs under git control:
$ git add -f .elasticbeanstalk
Patch eb tools to accept relative file paths
For the 2.5.1 version I had to make two changes in the config file parser class.
The file path is .../AWS-ElasticBeanstalk-CLI-2.5.1/eb/linux/python2.7/lib/utility/configfile_parser.py.
And the changes are:
[Lines 41 - 47, added lines marked with #1, #2, #3]
def read(self, pathfilename):
#seb: expand path to allow using homedir and relative paths #1
pathfilename = os.path.realpath(os.path.expanduser(pathfilename)) #2
print 'Load sectioned config file: ' + pathfilename #3
with codecs.open(pathfilename, 'r', encoding=ServiceDefault.CHAR_CODEC) as input_file:
_RawConfigParser.readfp(self, input_file)
[Lines 74 - 85, added lines marked with #1, #2, #3]
def read(self, pathfilename):
#seb: expand path to allow using homedir and relative paths #1
pathfilename = os.path.realpath(os.path.expanduser(pathfilename)) #2
print 'Load config file: ' + pathfilename #3
with codecs.open(pathfilename, 'r', encoding=ServiceDefault.CHAR_CODEC) as input_file:
config_pairs = input_file.read()
with _closing(_StringIO(u"[{0}]{1}{2}".format(self._default_section,
os.linesep,
config_pairs))) \
as default_section:
_RawConfigParser.readfp(self, default_section)
Now you can use relative to project root paths in your configs.
Change paths in configs to relative
I had three absolute paths in my ./elasticbeanstalk/config:
[global]
..
AwsCredentialFile=/home/username/.elasticbeanstalk/aws_credential_file
..
[branches]
staging=staging
production=production
[branch:staging]
OptionSettingFile=/path/to/project/.elasticbeanstalk/optionsettings.staging
...
[branch:production]
OptionSettingFile=/path/to/project/.elasticbeanstalk/optionsettings.production
..
Path to aws credential file can be easily fixed by just removing it - eb tools will use config from your home dir by default (~/.elacticbeanstalk/aws_credential_file).
Other two paths (for branch configs) can now be changed to relative:
[global]
# Default credential file path (recognized by both eb tool and git aws.push tool)
# AwsCredentialFile=~/.elasticbeanstalk/aws_credential_file
...
[branches]
staging=staging
production=production
[branch:staging]
OptionSettingFile=./.elasticbeanstalk/optionsettings.staging
...
[branch:production]
OptionSettingFile=./.elasticbeanstalk/optionsettings.production
...
Use it
Make sure you are using the 'eb' wrapper script from the root project directory. For example, for 'eb status':
$ cd project/root/dir
$ ./path/to/eb status
Load sectioned config file: project/root/dir/.elasticbeanstalk/config
Load config file: /home/user/.elasticbeanstalk/aws_credential_file
URL : staging-jp48gay9nx.elasticbeanstalk.com
Status : Ready
Health : Green
Great work! I'll try this =)
ReplyDeleteThanks, this worked like a charm. There are a few lines in the second read() method that need to be included as well:
ReplyDeletewith _closing(_StringIO(u"[{0}]{1}{2}".format(self._default_section,
os.linesep,
config_pairs))) \
as default_section:
_RawConfigParser.readfp(self, default_section)
Thanks, updated the post to make it clearer. I actually didn't mean to replace the methods, just add the new lines, but it was not very explicit.
DeleteThanks!
ReplyDelete