From 894119b31ae93c97f5e4841f30305d26342616df Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Sat, 21 Aug 2021 22:12:15 -0700 Subject: feat: holy bash spaghetti --- dactyl.sh | 576 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 576 insertions(+) create mode 100755 dactyl.sh (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh new file mode 100755 index 0000000..88e294f --- /dev/null +++ b/dactyl.sh @@ -0,0 +1,576 @@ +#!/bin/bash + +# ******************* # +# ******************* setup ******************* # +# ******************* # + +# exit if any errors are thrown +set -e + +container="" +shellContainer=DM-shell +configContainer=DM-config +modelContainer=DM-model +imageName=dactyl-keyboard +srcBind="$(pwd)/src:/app/src" +thingsBind="$(pwd)/things:/app/things" + +# force exit on interrupt in case we are in a menu +function catch_interrupt() { exit 1; } +trap catch_interrupt SIGINT +trap catch_interrupt SIGTSTP + +# ******************* # +# ******************* functions ******************* # +# ******************* # + +################################ +# General Helpers +################################ + +function inform() { + echo -e "\n[INFO] $@\n" +} + +function warn() { + echo -e "\n[WARN] $@\n" +} + +function error() { + echo -e "\n[ERROR] $@\n" +} + +function exitUnexpectedPositionalArgs() { + error "Unexpected positionnal argument.\n\n\tAlready had: $positional\n\n\tAnd then got: $1" + exit 1 +} + +function exitUnexpectedFlags() { + error "One or more flags are invalid:\n\n\tPositional: $positional\n\n\tFlags: $flags" + exit 1 +} + +################################ +# Interactive Menu +################################ + +# https://unix.stackexchange.com/questions/146570/arrow-key-enter-menu +# Arguments: +# array of options +# +# Return value: +# selected index (0 for opt1, 1 for opt2 ...) + +function menu { + printf "\n[Dactyl Manuform] Please choose an option:\n\n" + options=("$@") + + # helpers for terminal print control and key input + ESC=$(printf "\033") + cursor_blink_on() { printf "$ESC[?25h"; } + cursor_blink_off() { printf "$ESC[?25l"; } + cursor_to() { printf "$ESC[$1;${2:-1}H"; } + print_option() { printf "\t $1 "; } + print_selected() { printf "\t${COLOR_GREEN} $ESC[7m $1 $ESC[27m${NC}"; } + get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } + key_input() { + local key + ESC=$(printf "\033") + + # read 3 characters, 1 at a time + for (( i=0; i < 3; ++i)); do + read -s -n1 input 2>/dev/null >&2 + # concatenate chars together + key+="$input" + # if a number is encountered, echo it back + if [[ $input =~ ^[1-9]$ ]]; then + echo $input; return; + # if enter, early return + elif [[ $input = "" ]]; then + echo enter; return; + # if we encounter something other than [1-9] or "" or the escape sequence + # then consider it an invalid input and exit without echoing back + elif [[ ! $input = $ESC && i -eq 0 ]]; then + return + fi + done + + if [[ $key = $ESC[A ]]; then echo up; fi; + if [[ $key = $ESC[B ]]; then echo down; fi; + } + + # initially print empty new lines (scroll down if at bottom of screen) + for opt in "${options[@]}"; do printf "\n"; done + + # determine current screen position for overwriting the options + local lastrow=`get_cursor_row` + local startrow=$(($lastrow - $#)) + + # ensure cursor and input echoing back on upon a ctrl+c during read -s + trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 + cursor_blink_off + + local selected=0 + + # print options by overwriting the last lines + function drawOptions() { + local idx=0 + for opt in "${options[@]}"; do + cursor_to $(($startrow + $idx)) + # add an index to the option + local label="$(($idx + 1)). $opt" + if [ $idx -eq $selected ]; then + print_selected "$label" + else + print_option "$label" + fi + ((idx++)) + done + } + + while true; do + drawOptions + + # user key control + input=$(key_input) + + case $input in + enter) break;; + [1-9]) + # If a digit is encountered, consider it a selection (if within range) + if [ $input -lt $(($# + 1)) ]; then + selected=$(($input - 1)) + drawOptions + break + fi + ;; + up) ((selected--)); + if [ $selected -lt 0 ]; then selected=$(($# - 1)); fi;; + down) ((selected++)); + if [ $selected -ge $# ]; then selected=0; fi;; + esac + done + + # cursor position back to normal + cursor_to $lastrow + cursor_blink_on + echo + + return $selected +} + + +################################ +# Setup helpers +################################ + +function showHelpAndExit() { + echo "TODO: Help Menu" + exit +} + +# error on any unexpected flags or more than one positional argument +function processArgs() { + while [[ $# -gt 0 ]] + do + key="$1" + + case $key in + --build|-rm|--remove|--inspect|--run|--start|--stop) + if [[ $flags ]]; then + flags+=" $key" + else + flags=$key + fi + shift;; + -h|--help) + showHelpAndExit + ;; + *) + # all valid flags should have already been captured above + if [[ $key == -* ]]; then + error "Unknwon flag: $key" + exit 1 + # if we already have a positional argument we shouldn't get another + elif [[ "$positional" ]]; then + exitUnexpectedPositionalArgs $key + exit 1 + # the totality of accepted positional arguments + elif [[ "$key" =~ ^(image|shell|config|model)$ ]]; then + positional="$key" + if [[ ! $key = image ]]; then + key+="Container" + container=$(echo "${!key}") + fi + shift + else + error "Unknown positional arg: \"$key\"" + exit 1 + fi + ;; + esac + done +} + +# installing docker is out of scope +# so if it isn't found, inform user and exit +function checkDocker() { + if ! which docker &> /dev/null; then + error "Docker is not installed.\n\n\tPlease visit https://www.docker.com/products/docker-desktop for more information." + exit 1 + fi +} + +# exit unless user responds with yes +function confirmContinue() { + while true; do + read -p "$@ [y/n]" yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit 0;; + * ) error "Please answer yes or no.";; + esac + done +} + +################################ +# Image Logic +################################ + +function imageExists() { + docker image list | grep "$imageName" &> /dev/null +} + +function buildImage() { + inform "Building docker image: $imageName..." + docker build -t dactyl-keyboard -f docker/Dockerfile . +} + +function promptBuildImageIfNotExists() { + if ! imageExists; then + inform "Docker image not found: $imageName" + confirmContinue "Would you like to build it now?" + buildImage + fi +} + +# image will always exist if we are here +function handleRebuildImage() { + warn "Docker image already exists: $imageName" + confirmContinue "Would you like to overwrite it?" + buildImage +} + +function handleRemoveImage() { + warn "This will remove docker image: $imageName" + confirmContinue "Would you like to continue?" + inform "Removing docker image: $imageName..." + docker image rm $imageName +} + +function handleInspectImage() { + inform "Checking status of image: $imageName" + docker image inspect $imageName +} + +function handleImageMenu() { + local check="Check Image Status" + local build="Reuild Image" + local remove="Remove Image" + local end="Exit" + options=("$check" "$build" "$remove" "$end") + # execute in subshell so exit code doesn't exit the script + (menu "${options[@]}") && true + result="${options[$?]}" + + case $result in + $check) handleInspectImage;; + $build) handleRebuildImage;; + $remove) handleRemoveImage;; + *) exit;; + esac +} + +# if we made it this far, image is confirmed to exist +function handleImageCLI() { + if [[ ! "$flags" ]]; then + handleImageMenu + elif [[ "$flags" =~ ^.*(--inspect).*$ ]]; then + handleInspectImage + elif [[ "$flags" =~ ^.*(--build).*$ ]]; then + handleRebuildImage + elif [[ "$flags" =~ ^.*(--remove|-rm).*$ ]]; then + handleRemoveImage + else + exitUnexpectedFlags + fi +} + +################################ +# Container Helpers +################################ + +function containerExists() { + docker container list -a | grep "$container" &> /dev/null +} + +function containerIsRunning() { + if ! containerExists "$container"; then + return 1 + fi + + docker container inspect $container | grep '"Status": "running",' &> /dev/null +} + +function isShell() { + test $container = $shellContainer +} + +function promptIfShell() { + if isShell; then + promptStartShellSession + fi +} + +function buildContainerAndExecutePythonScript() { + docker run --name $container -d -v "$srcBind" -v "$thingsBind" $imageName python3 -i $1 +} + +function buildContainer() { + inform "Building docker container: $container..." + case $container in + $shellContainer) + docker run --name $shellContainer -d -p 8000:8000 -it -v "$srcBind" -v "$thingsBind" $imageName + ;; + $modelContainer) + buildContainerAndExecutePythonScript dactyl_manuform.py + ;; + $configContainer) + buildContainerAndExecutePythonScript generate_configuration.py + ;; + *) + error "Unexpected exception. Containier: $container" + exit 1;; + esac + echo +} + +function buildContainerIfNotExists() { + if ! containerExists; then + warn "Container not found: $container" + confirmContinue "Would you like to build it now?" + buildContainer + fi +} + +function startContainer() { + docker container start $container &> /dev/null +} + +function promptStartContainerIfNotRunning() { + buildContainerIfNotExists + if ! containerIsRunning; then + warn "Container is not running: $container" + confirmContinue "Would you like to start it now?" + startContainer + fi +} + +function startContainerIfNotRunning() { + buildContainerIfNotExists + if ! containerIsRunning; then + inform "Starting docker container: $container" + startContainer + fi +} + +function startContainerOrAlert() { + if containerIsRunning; then + inform "Container is already running: $shellContainer" + else + startContainerIfNotRunning + fi + + if isShell; then + promptStartShellSession + fi +} + +function stopContainer() { + if containerIsRunning; then + inform "Stopping docker container: $container..." + docker container stop $container &> /dev/null + docker container wait $container &> /dev/null + fi +} + +function handleStopContainer() { + if ! containerExists; then + warn "Docker container does not exist: $container" + elif ! containerIsRunning; then + inform "Container is already stopped: $container" + else + stopContainer + fi +} + +function removeContainer() { + if containerExists; then + stopContainer + inform "Removing docker container: $container..." + docker container rm $container &> /dev/null + fi +} + +function inspectContainer() { + if ! containerExists; then + inform "Container \"$container\" does not exist." + confirmContinue "Would you like to build it?" + buildContainer + fi + + docker container inspect $container +} + +function handleBuildContainer() { + if containerExists; then + warn "Container already exists: $container" + confirmContinue "Would you like to overwrite it?" + removeContainer + fi + + buildContainer + promptIfShell +} + +function handleContainerMenu() { + local build="Rebuild $container Container" + local start="Start $container Container" + local stop="Stop $container Container" + local remove="Remove $container Container" + local inspect="Inspect $container Container" + local run="Start $container Session" + local main="Main Menu" + local end="Exit" + + if ! containerExists; then + build="Build $container Container" + options=("$build" "$main" "$end") + elif containerIsRunning; then + options=("$run" "$inspect" "$build" "$stop" "$remove" "$main" "$end") + if ! isShell; then + unset options[0] + fi + else + options=("$inspect" "$build" "$start" "$remove" "$main" "$end") + fi + + # execute in subshell so exit code doesn't exit the script + (menu "${options[@]}") && true + result="${options[$?]}" + + case $result in + $build) handleBuildContainer;; + $start) startContainerOrAlert;; + $stop) handleStopContainer;; + $remove) removeContainer;; + $inspect) inspectContainer;; + $main) handleMainMenu;; + *) + if isShell && [[ $run = $result ]]; then + startShellSession + fi + exit + ;; + esac +} + +function handleContainerCLI() { + if [[ ! "$flags" ]]; then + handleContainerMenu + elif [[ "$flags" =~ ^.*(--inspect).*$ ]]; then + inspectContainer + elif [[ "$flags" =~ ^.*(--build).*$ ]]; then + handleBuildContainer + elif [[ "$flags" =~ ^.*(--run).*$ ]] && isShell; then + startShellSession + elif [[ "$flags" =~ ^.*(--start).*$ ]]; then + startContainerOrAlert + elif [[ "$flags" =~ ^.*(--stop).*$ ]]; then + handleStopContainer + elif [[ "$flags" =~ ^.*(--remove|-rm).*$ ]]; then + removeContainer + else + exitUnexpectedFlags + fi +} + +################################ +# Shell Specific Logic +################################ + +function startShellSession() { + promptStartContainerIfNotRunning + inform "Starting session in container: $shellContainer\n\n\tType \"exit\" to terminate the session." + docker exec -it $shellContainer /bin/bash +} + +function promptStartShellSession() { + confirmContinue "Would you like to start a shell session?" + startShellSession +} + +################################ +# Main Menu Logic +################################ + +function handleMainMenu() { + container="" + + local imageOpt="Manage Docker Image" + local shellOpt="$shellContainer Options" + local configOpt="$configContainer Options" + local modelOpt="$modelContainer Options" + local end="Exit" + + options=("$imageOpt" "$shellOpt" "$configOpt" "$modelOpt" "$end") + + # execute in subshell so exit code doesn't exit the script + (menu "${options[@]}") && true + result="${options[$?]}" + + case $result in + $imageOpt ) handleImageMenu;; + $shellOpt|$configOpt|$modelOpt) + # remove " Options" and set as currentn container + container=$(echo "${result/ Options/}") + handleContainerMenu + ;; + * ) exit;; + esac +} + +# ******************* # +# ******************* main ******************* # +# ******************* # + +# figure out why we're running the script +processArgs $@ + +# exit if `docker` command not available +checkDocker + +# make sure the base image has been built +promptBuildImageIfNotExists + +# main switchboard to act depending on which positionl arg was passed + +if [[ "$positional" ]]; then + case $positional in + image ) handleImageCLI;; + shell|config|model ) handleContainerCLI;; + * ) exitUnexpectedPositionalArgs;; + esac +else + handleMainMenu +fi -- cgit v1.2.3 From 0719f34f77f377647b3c975f01a8a7ae6ff88f59 Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Sun, 22 Aug 2021 11:56:43 -0700 Subject: chore: on screen help * feat: menu improvements --- dactyl.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 17 deletions(-) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index 88e294f..bf6259c 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -62,7 +62,12 @@ function exitUnexpectedFlags() { # selected index (0 for opt1, 1 for opt2 ...) function menu { - printf "\n[Dactyl Manuform] Please choose an option:\n\n" + local header="\n[Dactyl Manuform]" + if [ $container ]; then + header+=" -- $container" + fi + header+="\n\nPlease choose an option:\n\n" + printf "$header" options=("$@") # helpers for terminal print control and key input @@ -165,8 +170,32 @@ function menu { ################################ function showHelpAndExit() { - echo "TODO: Help Menu" - exit +cat << _end_of_text +[Dactyl Manuform] + +A bash CLI to manage Docker artifacts for the Dactyl Keyboard project. + +Run script without any options to use in interactive mode. + +Usage: + ./dactyl.sh + ./dactyl.sh [-h | --help | --uninstall] + ./dactyl.sh image [--build | --inspect | --remove] + ./dactyl.sh (config|model) [--build | --inspect | --start | --stop | --remove] + ./dactyl.sh shell [--build | --inspect | --session | --start | --stop | --remove] + +Options: + positional Target the image or a particular container (shell | config | model) + -h --help Show this screen. + --uninstall Remove all Docker artifacts. + --build Build or rebuild the target container. + --inspect Show "docker inspect" results for the target container. + --start Start or restart the target container. + --stop Stop the target container. + --remove Remove the target container. + --session Start a shell session in the shell container. +_end_of_text +exit } # error on any unexpected flags or more than one positional argument @@ -176,16 +205,15 @@ function processArgs() { key="$1" case $key in - --build|-rm|--remove|--inspect|--run|--start|--stop) + --build|--remove|--inspect|--session|--start|--stop) if [[ $flags ]]; then flags+=" $key" else flags=$key fi shift;; - -h|--help) - showHelpAndExit - ;; + -h|--help) showHelpAndExit;; + --uninstall) handleUninstall;; *) # all valid flags should have already been captured above if [[ $key == -* ]]; then @@ -275,10 +303,11 @@ function handleInspectImage() { function handleImageMenu() { local check="Check Image Status" - local build="Reuild Image" + local build="Rebuild Image" local remove="Remove Image" + local mainMenu="Main Menu" local end="Exit" - options=("$check" "$build" "$remove" "$end") + options=("$check" "$build" "$remove" "$mainMenu" "$end") # execute in subshell so exit code doesn't exit the script (menu "${options[@]}") && true result="${options[$?]}" @@ -287,6 +316,7 @@ function handleImageMenu() { $check) handleInspectImage;; $build) handleRebuildImage;; $remove) handleRemoveImage;; + $mainMenu) handleMainMenu;; *) exit;; esac } @@ -299,7 +329,7 @@ function handleImageCLI() { handleInspectImage elif [[ "$flags" =~ ^.*(--build).*$ ]]; then handleRebuildImage - elif [[ "$flags" =~ ^.*(--remove|-rm).*$ ]]; then + elif [[ "$flags" =~ ^.*(--remove).*$ ]]; then handleRemoveImage else exitUnexpectedFlags @@ -449,7 +479,7 @@ function handleContainerMenu() { local stop="Stop $container Container" local remove="Remove $container Container" local inspect="Inspect $container Container" - local run="Start $container Session" + local session="Start $container Session" local main="Main Menu" local end="Exit" @@ -457,7 +487,7 @@ function handleContainerMenu() { build="Build $container Container" options=("$build" "$main" "$end") elif containerIsRunning; then - options=("$run" "$inspect" "$build" "$stop" "$remove" "$main" "$end") + options=("$session" "$inspect" "$build" "$stop" "$remove" "$main" "$end") if ! isShell; then unset options[0] fi @@ -477,7 +507,7 @@ function handleContainerMenu() { $inspect) inspectContainer;; $main) handleMainMenu;; *) - if isShell && [[ $run = $result ]]; then + if isShell && [[ $session = $result ]]; then startShellSession fi exit @@ -492,13 +522,13 @@ function handleContainerCLI() { inspectContainer elif [[ "$flags" =~ ^.*(--build).*$ ]]; then handleBuildContainer - elif [[ "$flags" =~ ^.*(--run).*$ ]] && isShell; then + elif [[ "$flags" =~ ^.*(--session).*$ ]] && isShell; then startShellSession elif [[ "$flags" =~ ^.*(--start).*$ ]]; then startContainerOrAlert elif [[ "$flags" =~ ^.*(--stop).*$ ]]; then handleStopContainer - elif [[ "$flags" =~ ^.*(--remove|-rm).*$ ]]; then + elif [[ "$flags" =~ ^.*(--remove).*$ ]]; then removeContainer else exitUnexpectedFlags @@ -531,16 +561,20 @@ function handleMainMenu() { local shellOpt="$shellContainer Options" local configOpt="$configContainer Options" local modelOpt="$modelContainer Options" + local uninstallOpt="Uninstall" + local help="Show Help" local end="Exit" - options=("$imageOpt" "$shellOpt" "$configOpt" "$modelOpt" "$end") + options=("$imageOpt" "$shellOpt" "$configOpt" "$modelOpt" "$help" "$uninstallOpt" "$end") # execute in subshell so exit code doesn't exit the script (menu "${options[@]}") && true result="${options[$?]}" case $result in - $imageOpt ) handleImageMenu;; + $help) showHelpAndExit;; + $imageOpt) handleImageMenu;; + $uninstallOpt) handleUninstall;; $shellOpt|$configOpt|$modelOpt) # remove " Options" and set as currentn container container=$(echo "${result/ Options/}") -- cgit v1.2.3 From e45f1cff76ae5b6000c4efd35d6dc759359c4b3f Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Sun, 22 Aug 2021 17:22:30 -0700 Subject: feat: uninstall all docker artifacts --- dactyl.sh | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index bf6259c..c0bc41e 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -9,8 +9,10 @@ set -e container="" shellContainer=DM-shell -configContainer=DM-config modelContainer=DM-model +configContainer=DM-config +containers=("$shellContainer" "$configContainer" "$modelContainer") + imageName=dactyl-keyboard srcBind="$(pwd)/src:/app/src" thingsBind="$(pwd)/things:/app/things" @@ -289,11 +291,15 @@ function handleRebuildImage() { buildImage } +function removeImage() { + inform "Removing docker image: $imageName..." + docker image rm $imageName +} + function handleRemoveImage() { warn "This will remove docker image: $imageName" confirmContinue "Would you like to continue?" - inform "Removing docker image: $imageName..." - docker image rm $imageName + removeImage } function handleInspectImage() { @@ -550,6 +556,20 @@ function promptStartShellSession() { startShellSession } +################################ +# Uninstaller +################################ + +function handleUninstall() { + for currentContainer in "${containers[@]}"; do + container="$currentContainer" + removeContainer + done + + removeImage + exit +} + ################################ # Main Menu Logic ################################ -- cgit v1.2.3 From f0cc5f2df7f169f9634d2704d3a5fd704fb4c0e8 Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Sun, 22 Aug 2021 17:26:59 -0700 Subject: feat: prompt before uninstall --- dactyl.sh | 2 ++ 1 file changed, 2 insertions(+) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index c0bc41e..1cad28f 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -561,6 +561,8 @@ function promptStartShellSession() { ################################ function handleUninstall() { + warn "This will remove all containers and images." + confirmContinue "Are you sure you want to continue?" for currentContainer in "${containers[@]}"; do container="$currentContainer" removeContainer -- cgit v1.2.3 From 78be9475566ee1ee797589bf2c7139e603c70a8b Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Sun, 22 Aug 2021 20:09:14 -0700 Subject: feat: menu is ephemeral --- dactyl.sh | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index 1cad28f..8440bab 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -82,8 +82,6 @@ function menu { get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } key_input() { local key - ESC=$(printf "\033") - # read 3 characters, 1 at a time for (( i=0; i < 3; ++i)); do read -s -n1 input 2>/dev/null >&2 @@ -105,6 +103,18 @@ function menu { if [[ $key = $ESC[A ]]; then echo up; fi; if [[ $key = $ESC[B ]]; then echo down; fi; } + function cursorUp() { printf "$ESC[A"; } + function clearRow() { printf "$ESC[2K\r"; } + function eraseMenu() { + cursor_to $lastrow + clearRow + numHeaderRows=$(printf "$header" | wc -l) + numOptions=${#options[@]} + numRows=$(($numHeaderRows + $numOptions)) + for ((i=0; i<$numRows; ++i)); do + cursorUp; clearRow; + done + } # initially print empty new lines (scroll down if at bottom of screen) for opt in "${options[@]}"; do printf "\n"; done @@ -112,16 +122,15 @@ function menu { # determine current screen position for overwriting the options local lastrow=`get_cursor_row` local startrow=$(($lastrow - $#)) + local selected=0 # ensure cursor and input echoing back on upon a ctrl+c during read -s trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 cursor_blink_off - local selected=0 - - # print options by overwriting the last lines - function drawOptions() { - local idx=0 + while true; do + # print options by overwriting the last lines + local idx=0 for opt in "${options[@]}"; do cursor_to $(($startrow + $idx)) # add an index to the option @@ -133,10 +142,6 @@ function menu { fi ((idx++)) done - } - - while true; do - drawOptions # user key control input=$(key_input) @@ -147,7 +152,6 @@ function menu { # If a digit is encountered, consider it a selection (if within range) if [ $input -lt $(($# + 1)) ]; then selected=$(($input - 1)) - drawOptions break fi ;; @@ -158,10 +162,8 @@ function menu { esac done - # cursor position back to normal - cursor_to $lastrow + eraseMenu cursor_blink_on - echo return $selected } -- cgit v1.2.3 From 10c1f95b4b41f9c0ce876be5e02e7c6bf8a9f8d2 Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Wed, 25 Aug 2021 21:29:32 -0700 Subject: feat: remove port bind * chore: match container names to other implementations * feat: add release build --- dactyl.sh | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index 8440bab..7ccc387 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -8,10 +8,14 @@ set -e container="" +# bad practice: + # container variable names MUST match + # the positional name {positional}Container shellContainer=DM-shell -modelContainer=DM-model +runContainer=DM-run configContainer=DM-config -containers=("$shellContainer" "$configContainer" "$modelContainer") +releaseBuildContainer=DM-release-build +containers=("$shellContainer" "$configContainer" "$runContainer" "$releaseBuildContainer") imageName=dactyl-keyboard srcBind="$(pwd)/src:/app/src" @@ -179,20 +183,20 @@ cat << _end_of_text A bash CLI to manage Docker artifacts for the Dactyl Keyboard project. -Run script without any options to use in interactive mode. +Run the script without any flags to use the interactive menu. Usage: ./dactyl.sh ./dactyl.sh [-h | --help | --uninstall] ./dactyl.sh image [--build | --inspect | --remove] - ./dactyl.sh (config|model) [--build | --inspect | --start | --stop | --remove] + ./dactyl.sh (config|run|releaseBuild) [--build | --inspect | --start | --stop | --remove] ./dactyl.sh shell [--build | --inspect | --session | --start | --stop | --remove] Options: - positional Target the image or a particular container (shell | config | model) + positional Target the image or a particular container (shell | config | run | releaseBuild) -h --help Show this screen. --uninstall Remove all Docker artifacts. - --build Build or rebuild the target container. + --build Build (or rebuild) and run the target container. --inspect Show "docker inspect" results for the target container. --start Start or restart the target container. --stop Stop the target container. @@ -228,7 +232,7 @@ function processArgs() { exitUnexpectedPositionalArgs $key exit 1 # the totality of accepted positional arguments - elif [[ "$key" =~ ^(image|shell|config|model)$ ]]; then + elif [[ "$key" =~ ^(image|shell|config|run|releaseBuild)$ ]]; then positional="$key" if [[ ! $key = image ]]; then key+="Container" @@ -378,14 +382,17 @@ function buildContainer() { inform "Building docker container: $container..." case $container in $shellContainer) - docker run --name $shellContainer -d -p 8000:8000 -it -v "$srcBind" -v "$thingsBind" $imageName + docker run --name $shellContainer -d -it -v "$srcBind" -v "$thingsBind" $imageName ;; - $modelContainer) + $runContainer) buildContainerAndExecutePythonScript dactyl_manuform.py ;; $configContainer) buildContainerAndExecutePythonScript generate_configuration.py ;; + $releaseBuildContainer) + buildContainerAndExecutePythonScript model_builder.py + ;; *) error "Unexpected exception. Containier: $container" exit 1;; @@ -492,7 +499,7 @@ function handleContainerMenu() { local end="Exit" if ! containerExists; then - build="Build $container Container" + build="Build and run $container Container" options=("$build" "$main" "$end") elif containerIsRunning; then options=("$session" "$inspect" "$build" "$stop" "$remove" "$main" "$end") @@ -582,14 +589,15 @@ function handleMainMenu() { container="" local imageOpt="Manage Docker Image" - local shellOpt="$shellContainer Options" - local configOpt="$configContainer Options" - local modelOpt="$modelContainer Options" + local shellOpt="$shellContainer Container" + local configOpt="$configContainer Container" + local releaseOpt="$releaseBuildContainer Container" + local runOpt="$runContainer Container" local uninstallOpt="Uninstall" local help="Show Help" local end="Exit" - options=("$imageOpt" "$shellOpt" "$configOpt" "$modelOpt" "$help" "$uninstallOpt" "$end") + options=("$imageOpt" "$shellOpt" "$configOpt" "$runOpt" "$releaseOpt" "$help" "$uninstallOpt" "$end") # execute in subshell so exit code doesn't exit the script (menu "${options[@]}") && true @@ -599,9 +607,9 @@ function handleMainMenu() { $help) showHelpAndExit;; $imageOpt) handleImageMenu;; $uninstallOpt) handleUninstall;; - $shellOpt|$configOpt|$modelOpt) - # remove " Options" and set as currentn container - container=$(echo "${result/ Options/}") + $shellOpt|$configOpt|$runOpt|$releaseOpt) + # remove " Container" and set as currentn container + container=$(echo "${result/ Container/}") handleContainerMenu ;; * ) exit;; @@ -625,9 +633,9 @@ promptBuildImageIfNotExists if [[ "$positional" ]]; then case $positional in - image ) handleImageCLI;; - shell|config|model ) handleContainerCLI;; - * ) exitUnexpectedPositionalArgs;; + image) handleImageCLI;; + shell|config|run|releaseBuild) handleContainerCLI;; + *) exitUnexpectedPositionalArgs;; esac else handleMainMenu -- cgit v1.2.3 From 46a63d47c23da94723f0750836f5db921cb26dc9 Mon Sep 17 00:00:00 2001 From: Robert Reed Date: Tue, 31 Aug 2021 22:05:44 -0700 Subject: fix: add check to ensure docker daemon is running --- dactyl.sh | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'dactyl.sh') diff --git a/dactyl.sh b/dactyl.sh index 7ccc387..43bb553 100755 --- a/dactyl.sh +++ b/dactyl.sh @@ -255,6 +255,11 @@ function checkDocker() { error "Docker is not installed.\n\n\tPlease visit https://www.docker.com/products/docker-desktop for more information." exit 1 fi + + if ! docker image list &> /dev/null; then + error "Docker is not running. Please start docker and try again." + exit 1; + fi } # exit unless user responds with yes -- cgit v1.2.3