Last active
March 21, 2024 05:49
-
-
Save AndreSteenveld/c8e6409b4dd79f1b7abd479c3c0065be to your computer and use it in GitHub Desktop.
Helper script to gather docker-compose files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
cf__help(){ | |
printf '%s\n' \ | |
'compose-files - Helper script to gather docker-compose files ' \ | |
' ' \ | |
'Usage: ' \ | |
' compose-files [options --] [presets] ' \ | |
' ' \ | |
'Options: ' \ | |
' -?, -h, --help Show this help message ' \ | |
' -v, --verbose List found docker-compose files to stderr ' \ | |
' -l, --list List found docker-compose files to stdout (this omits the ' \ | |
' `--file` prefix) ' \ | |
' -p, --path <p> Root paths from which to look for docker-compose files, ' \ | |
' multiple roots can be provided. These are searched in order. ' \ | |
' If no paths are provided this defaults to `$PWD`. ' \ | |
' ' \ | |
'Presets: ' \ | |
' Presets can be the one of two things; An infix for a docker compose file or a ' \ | |
' path to a file. When preset is supplied the script checks if it is a file ' \ | |
' first. For example `Makefile` would be a poor infix, most likley the script ' \ | |
' will pass your `Makefile`-file to docker compose which will then throw an ' \ | |
' error. If the supplied preset is not a file it will look for all files in all ' \ | |
' supplied paths that look like `docker-compose.<infix>.{yml,yaml,json}. ' \ | |
' ' \ | |
' If options are supplied everything after `--` is treated as a preset. If no ' \ | |
' options are provided (or none can be parsed) all argumnets will be treated as ' \ | |
' presets. `--he1p` is bad taste, but otherwise a perfectly valid infix. ' \ | |
' ' \ | |
'Example: ' \ | |
' compose-files ' \ | |
' compose-files first-preset second-preset ./docker-compose.other.yaml ' \ | |
' compose-files --list --path . --path ../first --path ../second -- preset ' \ | |
' docker compose --project-name example $(compose-files development) up ' \ | |
' ' | |
exit 0 | |
} | |
cf__gather(){ | |
# | |
# So we're passing basically two arrays to this function which we'll need to parse out. The strategy to do this has | |
# been taken from/inspired by the following SO posts: | |
# | |
# https://stackoverflow.com/a/70855715/95019 -- Passing arrays as seperate values | |
# https://stackoverflow.com/a/71060036/95019 -- Passing arrays _by reference_, requires bash v4 | |
# | |
# We're going with the _old_ way of doing this, the reasoning here is that is has to work out of the box on OSX | |
# which comes with bash v3 by default. | |
# | |
local arguments=("$@") | |
local number_of_paths=${arguments[0]} | |
local number_of_presets=${arguments[$((number_of_paths + 1))]} | |
local paths=() | |
local presets=() | |
# | |
# So this array parsing could be done in a single loop, but that seems more confusing than just using | |
# all the offsets. I'm sure there is a way to make this work with slices but can't really be botherd. | |
# | |
for (( i = 1 ; i <= number_of_paths ; i++ )) ; do | |
paths+=("${arguments[$i]}") | |
done | |
for (( i = ( number_of_paths + 1 + 1) ; i <= ( number_of_paths + number_of_presets + 1); i++ )) ; do | |
presets+=("${arguments[$i]}") | |
done | |
local compose_files=(); | |
# | |
# Compose the list of compose files, first we're going to look for all regular compose files and load these | |
# regardless. Then go through the presets and add these to the list as well. | |
# | |
# As it turns out `globstar` is a feature introduced in bash v4, making it unusable for OSX. Luckikly we can | |
# fall back on good old `find`. | |
# shopt -s globstar nullglob extglob | |
for path in "${paths[@]}"; do | |
#for compose_file in "${path}"/**/docker-compose.{yml,yaml,json}; do | |
for compose_file in $(find "${path}" -name 'docker-compose.yml' -or -name 'docker-compose.yaml' -or -name 'docker-compose.json') ; do | |
compose_files+=( "$(realpath "${compose_file}")" ) | |
done | |
done | |
for path in "${paths[@]}"; do | |
for preset in "${presets[@]}"; do | |
if [[ -f "${preset}" ]]; then | |
compose_files+=( "$(realpath "${preset}")" ) | |
continue | |
fi | |
#for compose_file in "${path}"/**/docker-compose."${preset}".{yml,yaml,json}; do | |
for compose_file in $(find "${path}" -name "docker-compose.${preset}.yml" -or -name "docker-compose.${preset}.yaml" -or -name "docker-compose.${preset}.json") ; do | |
compose_files+=( "$(realpath "${compose_file}")" ) | |
done | |
done | |
done | |
printf '%s\n' "${compose_files[@]}" | |
} | |
cf__main(){ | |
local verbose=0; | |
local list=0 | |
local paths=(); | |
local presets=(); | |
while (( $# )) ; do | |
case $1 in | |
"-h" | "-?" | --help ) cf__help ;; | |
"-v" | --verbose ) verbose=1 ; shift ; continue ;; | |
"-l" | --list ) list=1 ; shift ; continue ;; | |
"-p" | --path ) paths+=( "$2" ) ; shift 2 ; continue ;; | |
-- ) shift ;; | |
esac | |
presets=( "$@" ) | |
break | |
done | |
if [[ "${#paths[@]}" == 0 ]]; then | |
paths+=( "$PWD" ) | |
fi | |
cf__gather "${#paths[@]}" "${paths[@]}" "${#presets[@]}" "${presets[@]}" | ( | |
if [[ "$verbose" == 0 ]] && [[ "$list" == 0 ]]; then | |
sed -e 's/^/ --file /' | tr -d '\n' | |
elif [[ "$verbose" == 1 ]] && [[ "$list" == 0 ]]; then | |
tee >(sed 's/^/[compose-files] /' >&2) | sed -e 's/^/ --file /' | tr -d '\n' | |
elif [[ "$verbose" == 1 ]] && [[ "$list" == 1 ]]; then | |
tee >(sed 's/^/[compose-files] /' >&2) | |
elif [[ "$verbose" == 0 ]] && [[ "$list" == 1 ]]; then | |
cat | |
fi | |
) | |
} | |
(return 0 2> /dev/null) || cf__main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment