I use the ruby scaffolding to manage one of my packages, and I have a bunch of scaffolding envvars set to control the config of the running service. So, for example, I have scaffolding_env[FOO]="bar" set.
I’d like to access that var in an init hook to control the behavior of part of the init process, but I haven’t found a way to do that. I’ve tried just accessing the set envvar using $FOO, but it seems unset at the time init runs. I’ve tried explicitly sourcing the app_env.sh as well, but that doesn’t seem to be rendered during init either. Finally, I tried a mustache helper in the init (which the docs indicate should work for “normal” envvars) like {{pkg.env.FOO}}, but that doesn’t work either. They all just render empty, and/or throw an error in the case of sourcing the app_env.sh.
Has anyone done this successfully? Do I need to namespace my mustache-helper differently? Is this even possible?
Relevant snippet of my init hook with my attempt at using the mustache helper:
#!/bin/sh
set -e
# Set envvars based on rendered config.
# This might be redundant, but doing it again doesn't hurt anything
#source {{$svc_config_path}}/app_env.sh
# initialize DB. Normal logic applies here, non-zero means failure.
pg_isready -d {{pkg.env.DATABASE_URL}}
if [ $? -eq 1 ]
then
app-rake db:create
app-rake db:seed
else
echo "Database is ready! Skipping create..."
fi
I see it in app_env.sh once it’s rendered, but that doesn’t seem to have happened at the time that the init hook runs. It is used correctly by the application itself.
Build and run steps are both default provided by the scaffolding.
In order to reproduce the behavior you’re seeing, please show exactly the commands that you’re executing and what output you’re getting. To the extent possible, try including minimal versions of your plan.sh, init hook and any other relevant plan context files.
It may also help to add DEBUG=1 to the command that should trigger the init hook so we can see if app_env.sh is being sourced as it should be.
I don’t have any command that I’ve explicitly written that triggers the init hook. I just created it and let habitat (maybe the ruby scaffolding?) consume and execute it as it normally would.
How would I specify that and add the DEBUG=1 option to it?
After you make changes to your plan.sh or init hook, what commands are you running to reproduce the behavior you’re seeing? Are you building locally in the studio, or pushing to builder and installing from there? What does the build output for your package look like? What command are you using to run your built package?
As for DEBUG=1, if you were running your package like this:
hab svc load /path/to/foo.hart
then you can
env DEBUG=1 hab svc load /path/to/foo.hart
or (assuming bash)
export DEBUG=1
and then all commands you run will generate extra debugging.
Please include the output from your various commands; there may be some hints about any errors that could be occurring.
Also, what does app_env.sh contain? Does it change when you add or remove something like
scaffolding_env[FOO]=bar
to your plan.sh and then re-run the build command? What about when loading the package?
Also, what if you run your app directly in the studio from the built package to rule out the issue being with the docker export? You should be able to run
hab svc load results/latest_thing_I_built.hart
Does that come up correctly? What sort of output do you see when you run
hab sup status
And if your package shows itself as up, what output do you see in the supervisor log at /hab/sup/default/sup.log?
in your plan.sh to be accessible in the context of the init hook. From the second link:
The following environment variables are set by the Ruby scaffolding and placed in a file called app_env.sh, which is created by the scaffolding and located in the /hab/svc/package/config/ directory. When the init hook is executed, the following export commands are run in the context of the hook, which allows it to have access to connection string data and deployment values.
If you’re overriding the default init hook provided by the scaffolding, which means you need to source app_env.sh in your own hook. If you don’t need special init hook behavior, you can get rid of your habitat/hooks/init file and when you rebuild, you should get a scaffolding-generated hook that does the right thing. You can check /hab/pkgs/jbauman/you-app-name/version/buildnumber/hooks/init to confirm what’s getting generated by the build.
Your code had source {{$svc_config_path}}/app_env.sh, but that’s not quite right. It needs to be {{pkg.svc_config_path}}, so the full line would look like:
I just noticed that same error in the init as well after grepping through some core packages for reference. Building an update now to see if it fixes things…
declare -A scaffolding_env
scaffolding_env[FOO]="bar"
In habitat/hooks/init:
#!/bin/bash
source "{{pkg.svc_config_path}}/app_env.sh"
echo "I am the init hook, FOO='$FOO'"
Then
[56][default:/src:0]# build
…
[58][default:/src:1]# hab svc load /src/results/jbauman-sample-node-app-1.0.1-20180417204016-x86_64-linux.hart
hab-sup(MN): The jbauman/sample-node-app/1.0.1/20180417204016 service was successfully loaded
[59][default:/src:0]# sl
…
sample-node-app.default hook[init]:(HK): I am the init hook, FOO='bar'
Testing locally that seems to have fixed the problem. I’m able to access the envvars set by app_env.sh within my init now and I see the {{pkg.svc_config_path}} rendered out as it should be.
Now that I know how this works I’m going to see if I can put together a PR for the docs to make this more clear.
I don’t see the docs anywhere in github so I could do a PR on them. Am I missing something?
In any case, it would be useful if the section https://www.habitat.sh/docs/reference/#template-data made it more explicit how this stuff is namespaced. I was guessing what it should be based on what I saw in another section and clearly guessed wrong.
Could you help me understand what your expectation was based on what you saw elsewhere, and how that differed from what @baumanj directed you to?
If there’s anything misleading or unclear, we definitely want to fix that, but if you could be explicit about the nature of your misunderstanding, and how you were led astray by the docs, that would be super helpful.
In the Template data section, you have the top level namespaces broken out, with their members below them, but it never says “treat these as name spaces and when using them in mustache tags use them like {{pkg.the_thing}}, or {{sys.the_other_thing}}” or similar. Just one or two sentences like that in the intro where readers are pointed to the example would have made all the difference for me.
This is implied in the example, but since the example only dealt with the cfg space it wasn’t clear from that it was how things are broken up, or that it was actually a namespace. It seems like a special case because of how it’s treated in the docs. In the end, it’s one of those things that makes perfect sense once you understand it, but if you don’t know about it already, making it more explicit in the documentation would be very helpful in putting the pieces together.