diff --git a/client/src/docker/docker.bash b/client/src/docker/docker.bash index f55eb04..0d49e56 100755 --- a/client/src/docker/docker.bash +++ b/client/src/docker/docker.bash @@ -92,8 +92,8 @@ function main() \e[37;2m# Setup an alias for latest \e[0m $ alias docker-finance=\"$0 archlinux${global_arg_delim_1}${USER}:latest\" - \e[37;2m# Generate environment and build image\e[0m - $ docker-finance gen && docker-finance build + \e[37;2m# Generate environment and build default image\e[0m + $ docker-finance gen && docker-finance build type=default \e[37;2m# Bring up container, open shell (type 'exit' to leave)\e[0m $ docker-finance up @@ -124,8 +124,8 @@ function main() \e[37;2m# Setup an alias for dev-tools\e[0m $ alias docker-finance_dev-tools=\"$0 dev-tools${global_arg_delim_1}${USER}:latest\" - \e[37;2m# Generate environment and build image\e[0m - $ docker-finance_dev-tools gen && docker-finance_dev-tools build + \e[37;2m# Generate environment and build default image\e[0m + $ docker-finance_dev-tools gen && docker-finance_dev-tools build type=default \e[37;2m# Spawn a container with given command (removed after command finishes)\e[0m $ docker-finance_dev-tools run 'shellcheck --version' diff --git a/client/src/docker/lib/internal/lib_docker.bash b/client/src/docker/lib/internal/lib_docker.bash index 683ed42..d232150 100644 --- a/client/src/docker/lib/internal/lib_docker.bash +++ b/client/src/docker/lib/internal/lib_docker.bash @@ -46,10 +46,44 @@ if [ -z "$EDITOR" ]; then fi fi -# -# `docker compose` -# +# Remaining "constructor" implementation +function lib_docker::__docker() +{ + # Docker-related files + [ -z "$DOCKER_FINANCE_CLIENT_REPO" ] && lib_utils::die_fatal + declare -g global_repo_dockerfiles="${DOCKER_FINANCE_CLIENT_REPO}/client/Dockerfiles/" + case "$global_platform" in + archlinux | ubuntu) + global_repo_dockerfiles+="finance" + ;; + dev-tools) + global_repo_dockerfiles+="dev-tools" + ;; + *) + lib_utils::die_fatal "platform was not previously checked" + ;; + esac + + # + # Generate docker-compose.yml + # + + [ -z "$global_env_file" ] && lib_utils::die_fatal + [ -z "$global_shell_file" ] && lib_utils::die_fatal + [ -z "$global_repo_dockerfiles" ] && lib_utils::die_fatal + + local _path="${global_repo_dockerfiles}/docker-compose.yml" + lib_utils::print_debug "Generating '${_path}'" + + sed \ + -e "s|@DOCKER_FINANCE_IMAGE@|${global_image}:${global_tag}|g" \ + -e "s|@DOCKER_FINANCE_CONTAINER@|${global_container}|g" \ + -e "s|@DOCKER_FINANCE_NETWORK@|${global_network}|g" \ + "${_path}.${global_platform}.in" >"$_path" || return $? +} + +# `docker compose` wrapper function lib_docker::__docker_compose() { [ -z "$global_env_file" ] && lib_utils::die_fatal @@ -66,7 +100,199 @@ function lib_docker::__docker_compose() function lib_docker::__build() { - time lib_docker::__docker_compose build --pull docker-finance "$@" + [ -z "$global_usage" ] && lib_utils::die_fatal + [ -z "$global_arg_delim_1" ] && lib_utils::die_fatal + [ -z "$global_arg_delim_2" ] && lib_utils::die_fatal + [ -z "$global_arg_delim_3" ] && lib_utils::die_fatal + + [ -z "$global_platform" ] && lib_utils::die_fatal + + case "$global_platform" in + archlinux | ubuntu) + local -r _usage=" +\e[32mDescription:\e[0m + + Build 'finance' image of given type + +\e[32mUsage:\e[0m + + $ $global_usage type${global_arg_delim_2} + +\e[32mArguments:\e[0m + + Build type: + + type${global_arg_delim_2} + +\e[32mNotes:\e[0m + + - All builds will continue to incorporate custom Dockerfile (see \`edit help\`) + - WARNING: for 'tiny' and 'micro'; use only if you trust pre-compiled assets hosted on GitHub (Microsoft) + +\e[32mExamples:\e[0m + + \e[37;2m# Build normal (default) image\e[0m + $ $global_usage type${global_arg_delim_2}default + + \e[37;2m# Build a smaller default image but *without* ROOT.cern (meta-analysis) support\e[0m + $ $global_usage type${global_arg_delim_2}slim + + \e[37;2m# Build an even smaller default image with *pre-built* hledger-flow binary (but *with* ROOT.cern support)\e[0m + $ $global_usage type${global_arg_delim_2}tiny + + \e[37;2m# Build the smallest image possible: the 'tiny' image *without* ROOT.cern support\e[0m + $ $global_usage type${global_arg_delim_2}micro +" + ;; + dev-tools) + local -r _usage=" +\e[32mDescription:\e[0m + + Build 'dev-tools' image of given type + +\e[32mUsage:\e[0m + + $ $global_usage type${global_arg_delim_2} + +\e[32mArguments:\e[0m + + Build type: + + type${global_arg_delim_2} + +\e[32mNotes:\e[0m + + - All builds will continue to incorporate custom Dockerfile (see \`edit help\`) + +\e[32mExamples:\e[0m + + \e[37;2m# Build normal (default) image\e[0m + $ $global_usage type${global_arg_delim_2}default +" + ;; + *) + lib_utils::die_fatal "unsupported platform" + ;; + esac + + # + # Ensure supported arguments + # + + [ $# -eq 0 ] && lib_utils::die_usage "$_usage" + + for _arg in "$@"; do + [[ ! "$_arg" =~ ^type[s]?${global_arg_delim_2} ]] \ + && lib_utils::die_usage "$_usage" + done + + # + # Parse arguments before testing + # + + # Parse key for value + for _arg in "$@"; do + + local _key="${_arg%${global_arg_delim_2}*}" + local _len="$((${#_key} + 1))" + + if [[ "$_key" =~ ^type[s]?$ ]]; then + local _arg_type="${_arg:${_len}}" + [ -z "$_arg_type" ] && lib_utils::die_usage "$_usage" + fi + done + + # + # Test argument values, set globals + # + + IFS="$global_arg_delim_3" + + # Arg: type + if [ ! -z "$_arg_type" ]; then + [[ ! "$_arg_type" =~ ^default$|^slim$|^tiny$|^micro$ ]] \ + && lib_utils::die_usage "$_usage" + fi + + # TODO: factor out parser + + # + # Generate Dockerfile + # + + [ -z "$DOCKER_FINANCE_UID" ] && lib_utils::die_fatal + [ -z "$DOCKER_FINANCE_GID" ] && lib_utils::die_fatal + [ -z "$DOCKER_FINANCE_USER" ] && lib_utils::die_fatal + + [ -z "$global_repo_dockerfiles" ] && lib_utils::die_fatal + + local _final="${global_repo_dockerfiles}/Dockerfile" + local _in_file="${global_repo_dockerfiles}/Dockerfile.${global_platform}.in" + + lib_utils::print_debug "Generating '${_final}' from '${_in_file}" + + sed \ + -e "s:@DOCKER_FINANCE_UID@:${DOCKER_FINANCE_UID}:g" \ + -e "s:@DOCKER_FINANCE_GID@:${DOCKER_FINANCE_GID}:g" \ + -e "s:@DOCKER_FINANCE_USER@:${DOCKER_FINANCE_USER}:g" \ + "$_in_file" >"$_final" || return $? + + # + # Append to Dockerfile according to type + # + + if [[ "$global_platform" == "dev-tools" && "$_arg_type" != "default" ]]; then + lib_utils::print_warning "'${_arg_type}' is not supported for 'dev-tools', using 'default'" + fi + + if [[ "$global_platform" != "dev-tools" ]]; then + + local _in_files=() + + case "$_arg_type" in + default | slim) + _in_files+=("hledger-flow.src") + [[ "$_arg_type" == "default" ]] && _in_files+=("root") + ;; + tiny | micro) + _in_files+=("hledger-flow.bin") + [[ "$_arg_type" == "tiny" ]] && _in_files+=("root") + ;; + *) + lib_utils::die_fatal "unsupported build" + ;; + esac + + for _file in "${_in_files[@]}"; do + local _path="${global_repo_dockerfiles}/${global_platform}/Dockerfile.${_file}.in" + lib_utils::print_debug "Appending '${_path}' to '${_final}'" + sed \ + -e "s:@DOCKER_FINANCE_USER@:${DOCKER_FINANCE_USER}:g" \ + "$_path" >>"$_final" || return $? + done + + fi + + # + # Append to Dockerfile end-user's custom Dockerfile + # + + [ -z "$global_custom_dockerfile" ] && lib_utils::die_fatal + + if [[ ! -f "$global_custom_dockerfile" ]]; then + lib_utils::print_debug "'${global_custom_dockerfile}' not found, skipping" + else + lib_utils::print_debug "Appending '${global_custom_dockerfile}' to '${_final}'" + sed \ + -e "s:@DOCKER_FINANCE_USER@:${DOCKER_FINANCE_USER}:g" \ + "$global_custom_dockerfile" >>"$_final" || return $? + fi + + # + # Execute + # + + time lib_docker::__docker_compose build --pull docker-finance } function lib_docker::__up() diff --git a/client/src/docker/lib/lib_docker.bash b/client/src/docker/lib/lib_docker.bash index 52616bd..ad91bd7 100644 --- a/client/src/docker/lib/lib_docker.bash +++ b/client/src/docker/lib/lib_docker.bash @@ -109,69 +109,8 @@ function lib_docker::docker() # Setup remaining client/container globals lib_gen::gen || return $? - # TODO: all following docker related should be internal - - # Docker-related files - [ -z "$global_repo_client" ] && lib_utils::die_fatal - declare -g global_repo_dockerfiles="${global_repo_client}/Dockerfiles/" - - case "$global_platform" in - archlinux | ubuntu) - global_repo_dockerfiles+="finance" - ;; - dev-tools) - global_repo_dockerfiles+="dev-tools" - ;; - *) - lib_utils::die_fatal "platform was not previously checked" - ;; - esac - - # - # docker-compose - # - - [ -z "$global_env_file" ] && lib_utils::die_fatal - [ -z "$global_shell_file" ] && lib_utils::die_fatal - - local _path="${global_repo_dockerfiles}/docker-compose.yml" - lib_utils::print_debug "Generating '${_path}'" - - sed \ - -e "s|@DOCKER_FINANCE_IMAGE@|${global_image}:${global_tag}|g" \ - -e "s|@DOCKER_FINANCE_CONTAINER@|${global_container}|g" \ - -e "s|@DOCKER_FINANCE_NETWORK@|${global_network}|g" \ - "${_path}.${global_platform}.in" >"$_path" || return $? - - # - # Dockerfile - # - - [ -z "$DOCKER_FINANCE_UID" ] && lib_utils::die_fatal - [ -z "$DOCKER_FINANCE_GID" ] && lib_utils::die_fatal - [ -z "$DOCKER_FINANCE_USER" ] && lib_utils::die_fatal - - local _path="${global_repo_dockerfiles}/Dockerfile" - lib_utils::print_debug "Generating '${_path}'" - - sed \ - -e "s:@DOCKER_FINANCE_UID@:${DOCKER_FINANCE_UID}:g" \ - -e "s:@DOCKER_FINANCE_GID@:${DOCKER_FINANCE_GID}:g" \ - -e "s:@DOCKER_FINANCE_USER@:${DOCKER_FINANCE_USER}:g" \ - "${_path}.${global_platform}.in" >"$_path" || return $? - - # Append end-user's custom Dockerfile to final Dockerfile - [ -z "$global_custom_dockerfile" ] && lib_utils::die_fatal - - if [[ ! -f "$global_custom_dockerfile" ]]; then - lib_utils::print_debug "'${global_custom_dockerfile}' not found, skipping" - return 0 - fi - - lib_utils::print_debug "Appending '${global_custom_dockerfile}' to '${_path}'" - sed \ - -e "s:@DOCKER_FINANCE_USER@:${DOCKER_FINANCE_USER}:g" \ - "$global_custom_dockerfile" >>"$_path" || return $? + # Remaining "constructor" implementation + lib_docker::__docker || return $? return 0 }