Skip to content

hashmap-kz/go-genopts

Repository files navigation

Generate bash getopt boilerplate.

This tool is designed to simplify the creation of boilerplate code for Bash scripts, enabling quick and consistent setup.

It automates the generation of essential script components, including:

  • Main Function: Provides a structured entry point for your script.
  • Usage Function: Displays help information and usage instructions.
  • Argument Parsing: Handles command-line arguments and options.
  • Input Validation and Checks: Ensures robust error handling and parameter validation.

Most parameters are pre-configured, allowing you to quickly create robust and reusable Bash scripts with minimal effort.

Implementation details

  • --help option is added by default, you don't need to specify it (and it's added as a long option only, this prevents collisions)
  • you don't need to specify short options, unless the short option is different that the first letter of the long one
  • by default all options are required, but you may add 'optional: true' setting
  • descriptions are used to generate helpful usage
  • in a field 'type' you may use "list, bool" values

Input config example

opts:
  # required args
  - name: dbname
    desc: "database to dump"
  - name: host
    desc: "database server host or socket directory"
  - name: port
    desc: "database server port number"
  - name: username
    short: U
    desc: "connect as specified database user"
  - name: output
    short: O
    desc: "output path"
  # optional args
  - name: schema
    type: list
    short: "n"
    desc: "dump only schemas matching pattern"
    optional: true
  - name: exclude-schema
    type: list
    short: "N"
    desc: "do not dump any schemas matching pattern"
    optional: true
  - name: verbose
    defaultValue: "true"
    type: bool
    optional: true
  - name: jobs
    defaultValue: "2"
    optional: true

Generated code

#!/bin/bash
set -euo pipefail

usage() {
  cat <<EOF
Usage: $(basename "$0") [OPTIONS]

OPTION                DESCRIPTION                               REQUIRED
--help
-d, --dbname          database to dump                          V
-h, --host            database server host or socket directory  V
-p, --port            database server port number               V
-U, --username        connect as specified database user        V
-O, --output          output path                               V
-n, --schema          dump only schemas matching pattern
-N, --exclude-schema  do not dump any schemas matching pattern
-v, --verbose
-j, --jobs

EOF
}

main() {
  local dbname=''
  local host=''
  local port=''
  local username=''
  local output=''
  local schema=()
  local exclude_schema=()
  local verbose="true"
  local jobs="2"

  getopt_short_opts='d:h:p:U:O:n:N:vj:'
  getopt_long_opts='dbname:,host:,port:,username:,output:,schema:,exclude-schema:,verbose,jobs:,help'
  VALID_ARGS=$(getopt -o "${getopt_short_opts}" --long "${getopt_long_opts}" -- "$@")

  # shellcheck disable=SC2181
  if [ $? != 0 ]; then
    echo "error parsing options"
    usage
    exit 1
  fi

  eval set -- "$VALID_ARGS"
  while true; do
    case "$1" in
    -d | --dbname)
      dbname="${2}"
      shift 2
      ;;
    -h | --host)
      host="${2}"
      shift 2
      ;;
    -p | --port)
      port="${2}"
      shift 2
      ;;
    -U | --username)
      username="${2}"
      shift 2
      ;;
    -O | --output)
      output="${2}"
      shift 2
      ;;
    -n | --schema)
      schema+=("${2}")
      shift 2
      ;;
    -N | --exclude-schema)
      exclude_schema+=("${2}")
      shift 2
      ;;
    -v | --verbose)
      verbose=true
      shift
      ;;
    -j | --jobs)
      jobs="${2}"
      shift 2
      ;;
    --help)
      usage
      exit 0
      ;;
    --)
      shift
      break
      ;;
    *)
      echo "unexpected argument ${1}"
      usage
      exit 1
      ;;
    esac
  done

  # check remaining
  shift $((OPTIND - 1))
  remaining_args="${*}"
  if [ -n "${remaining_args}" ]; then
    printf "\n[error]: remaining args are not allowed: ${remaining_args[*]}\n\n"
    usage
    exit 1
  fi

  # check that required parameters were set
  local req_parameters=('dbname' 'host' 'port' 'username' 'output')
  for req_param in "${req_parameters[@]}"; do
    if [ -z "${!req_param:-}" ]; then
      printf "\n[error]: required parameter is not set: ${req_param}\n\n"
      usage
      exit 1
    fi
  done

  # debug variables
  echo "dbname=${dbname}"
  echo "host=${host}"
  echo "port=${port}"
  echo "username=${username}"
  echo "output=${output}"
  echo "schema=${schema[*]}"
  echo "exclude_schema=${exclude_schema[*]}"
  echo "verbose=${verbose}"
  echo "jobs=${jobs}"

}

main "${@}"

Usage:

go run main.go -c=config.yml > example.sh

Example usage of generated script:

# short form
bash example.sh \
    -d keycloak_base \
    -h 10.40.240.30 \
    -p 5432 \
    -U postgres \
    -v \
    -O "/mnt/backup" \
    -n "public|data_audit"

# long form
bash example.sh \
    --dbname=keycloak_base \
    --host=10.40.240.30 \
    --port=5432 \
    --username=postgres \
    --verbose \
    --output="/mnt/backup" \
    --schema="public|data_audit"

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published