Need help with an example of an optional bind


#1

Cross posted from a github request from @gustovd https://github.com/habitat-sh/habitat/issues/4855

Found in the documentation (https://www.habitat.sh/docs/developing-packages/#pkg-binds)

“”"
Service group A can optionally bind to “X” or “Y”. If “X” is present, we operate this way, if “Y” is present, we operate this way. The service will start and may fail because “X” and/or “Y” my not be present at start, but it will eventually start. Real world example: An application service group that could use a Redis backend or a PostgreSQL backend, depending on how you are deploying it in different scenarios.
“”"

Could you show an example of how this works?


#2

Continuing with the example of an application that can either use a Redis or PostgreSQL backend, you could have a plan.sh that includes something like this:

pkg_binds_optional=(
    [redis]="...",
    [database]="..."
)

(The "..." serve as placeholders for whatever exported data you would need for those binds… they could be as simple as "port", but it depends on the specific things you’re wanting to bind to.)

If you want to start your application with the Redis backend, you would just bind that to a service group, like so:

hab svc load my/awesome-app --bind=redis:redis.default

(assuming you have a redis.default service group in your environment)

This will ensure that my/awesome-app will not start until members of the redis.default group are present; once they are, their exported data are available to use in the templates of the application, which would be written such that they would “do the right thing”, depending on which bind was present. That might look something like this:

{{ #if bind.redis }}
... do redis stuff
{{ /if }}

{{ #if bind.database }}
... do database stuff instead
{{ /if }}

In another deployment scenario, you could deploy your service using the database backend instead. That would look like this:

hab svc load my/awesome-app --bind=database:postgresql.default

Similarly, this will block startup of my/awesome-app until members of the postgresql.default group are present.

It should be noted that the use of “optional” here means that you can choose to bind to something or not, but your application will henceforth require them to be present in order to start. I’m currently working on a refinement to our binding logic that will make it so binds can be present or not, and your application will still be able to run… this is how properly designed distributed services should behave anyway. This will allow your application to degrade gracefully if one of its dependencies goes away.


Binds, exports, and gossip, oh my!
#3

Thank you for the clarification!