Skip to content

Instantly share code, notes, and snippets.

@monfresh
Created March 21, 2014 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monfresh/9678741 to your computer and use it in GitHub Desktop.
Save monfresh/9678741 to your computer and use it in GitHub Desktop.
while getopts ":a:o:" opt; do
case $opt in
a)
echo "Getting ready to set environment variables for $2"
echo "Setting CANONICAL_URL"
heroku config:set CANONICAL_URL=$2.herokuapp.com --app $2
echo "Setting DOMAIN_NAME"
heroku config:set DOMAIN_NAME=herokuapp.com --app $2
echo "Setting SECRET_TOKEN"
token2=$(cat /dev/random | LC_CTYPE=C tr -dc "[:alnum:]" | head -c 128)
heroku config:set SECRET_TOKEN=$token2 --app $2
echo "Getting ready to install add-ons for $2"
echo "Installing Mandrill by MailChimp"
heroku addons:add mandrill --app $2
echo "Installing Memcachier"
heroku addons:add memcachier --app $2
echo "Installing New Relic"
heroku addons:add newrelic --app $2
;;
o)
echo "Setting OHANA_API_ENDPOINT"
heroku config:set OHANA_API_ENDPOINT=$4 --app $2
;;
\?)
echo "Invalid option: -$OPTARG" >&2
echo "Usage: setup_heroku -a your_app_name -o your_api_endpoint" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument" >&2
echo "Usage: setup_heroku -a your_app_name -o your_api_endpoint" >&2
exit 1
;;
esac
done
@monfresh
Copy link
Author

I want both the -a and -o options to be required, so that if someone runs the script like this:

setup_heroku -a app_name

It should echo "Please provide an API endpoint".

And vice versa if endpoint is present but not app name

@monfresh
Copy link
Author

I tried adding this to the bottom, but it didn't work:

shift $((OPTIND-1))

if [ -z "${a}" ] || [ -z "${o}" ]; then
  echo "No arguments supplied" >&2;
  exit 1;
fi

@monfresh
Copy link
Author

I also tried adding this at the top and it didn't work either:

if ( ! getopts ":a:o:" opt); then
  echo "Please provide both an app name and an API endpoint";
  echo "Usage: setup_heroku -a your_app_name -o your_api_endpoint";
  exit $E_OPTERROR;
fi

@ycombinator
Copy link

To be honest, if you want both parameters to be always supplied when this command is invoked, consider making them positional parameters instead of options (since they aren't really optional, are they?).

Still, if you want to preserve them as options, here's one way to do this:

#!/bin/bash

# Parse options
while getopts ":a:o:" opt; do
  case $opt in
    a)
      APP_NAME=$OPTARG
      ;;
    o)
      OHANA_API_ENDPOINT=$OPTARG
      ;;
    *)
      # Invalid option stuff...
  esac
done

# Guard clause for APP_NAME option
if [ -z "$APP_NAME" ]; then
    echo "Please provide application name using the -a option." >&2
    exit 201
fi

# Guard clause for OHANA_API_ENDPOINT option
if [ -z "$OHANA_API_ENDPOINT" ]; then
    echo "Please provide an Ohana API endpoint using the -o option." >&2
    exit 202
fi

# Heroku processing stuff...

@monfresh
Copy link
Author

@ycombinator, good point about the positional parameters, but how would I deal with the possibility that they supplied the parameters in the wrong order? I guess Heroku would throw an error because it wouldn't find an app by the name of the endpoint.

@ycombinator
Copy link

Exactly, your script is a client-side interface. You could keep it relatively dumb and let the server-side (in this case, Heroku) handle validation. Or you could be nicer to your users and keep the validation closer to them, in the script itself. The other benefit of the latter approach (client-side validation) is that it is better for transactional operations - that is, you don't want to do partial work on the server, then run into a validation error from the server and have to undo a bunch of work.

So, for instance, you could check that the API endpoint parameter value matched the regex /^https?:/// before passing it off to Heroku.

Also, if you think about it, all this validation logic has nothing to do with whether the parameters are positional or optional. Either way, you could run into the same problems with a user specifying the wrong one in the wrong place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment