Bonsai! scripting with heroku-cli
18 Mar 2022 . ElasticSearch . Comments #
While upgrading to Elastic Search 7 we needed to upgrade our heroku environments. We manage multiple heroku environments for each of our teams, and manually updating each environment is prone to errors and can be tedious. We deploy and set environment variables is this scripting exercise.
Uses awk
, grep
, ruby
and compares some of the string manipulation of each
heroku addons --all | awk ' /bonsai:standard-sm/ {print $1}' | while read line
heroku addons:create bonsai:standard-sm --app=$line --version=7.10
Wherever we were paying for Elastic create an addon of the modern version.
After the addons are deployed, they report as environment variables to the app.
All of our BONSAI_URL
values were set to Elastic version 6.8 and our app is currently
dual writing on 6 and 7. We need all the BONSAI_CREEPY_COLOR_CHOICES values to tell
our app where to start duplicate writing.
During this process I created some scripts mixing shell scripting and interweaving
ruby using -e
heroku config --app=my-app |
ruby -e "puts ARGF.map { |line| @app=(match = line.match(/([a-z0-9-]+) Config Vars/)) ? match[1] : @app; line.match(/BONSAI_([^U]+)_URL/) ? \"#{@app} #{line.match(/https:.*/)[0]}\" : nil}.reject(&:nil?).sort.uniq" |
awk {'printf "heroku config:set ELASTICSEARCH_URL7=%s --app=%s", $2, $1'} | sh
I need to set an ENV for each one, so I’m extracting the new Bonsai environments I created and setting an app environment variable. The nice thing about heroku is you can set your variable to the value of another variable
ARGF.map do |line|
@app=
(match = line.match(/([a-z0-9-]+) Config Vars/))
? match[1]
: @app
line.match(/BONSAI_([^U]+)_URL/)
? \"#{@app} #{line.match(/https:.*/)[0]}\"
: nil
.reject(&:nil?)
.sort
.uniq
In this block we are going through the lines of greped output of heroku config
scoped to a single app
The first line we parse is a comment that we pull the app name out of. Interesting feature of ruby here
is the instance variable usage for @app
. Without the @
app is scoped to the block (a single line of
the config
output. We set @app using these comments to heroku config:set
.
On lines that are comments, we set @app and on lines which contain our ENV connection string we return a space
separated app connection_string
.
awk {'printf "heroku config:set ELASTICSEARCH_URL7=%s --app=%s", $2, $1'}
converts each of those pairs into a command that will be passed to sh
heroku config:set ELASTICSEARCH_URL7=connection_string --app=app
Now if we only all of the deployed instances shared a color maybe this could be easier? It sure was convenient that it restarted all the existing apps as it went, reporting status of each on output.