Skip to content

Instantly share code, notes, and snippets.

@3h4x
Created July 22, 2022 18:36
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 3h4x/883cf3c04d860ff6386b030d82be3d33 to your computer and use it in GitHub Desktop.
Save 3h4x/883cf3c04d860ff6386b030d82be3d33 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Geodesic Wrapper Script
set -o pipefail
# Geodesic Settings
export GEODESIC_PORT=${GEODESIC_PORT:-$((30000 + $$ % 30000))}
readonly OS=$(uname -s)
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
export options=()
export targets=()
function require_installed() {
if ! which $1 >/dev/null; then
echo "Cannot find $1 installed on this system. Please install and try again."
exit 1
fi
}
function options_to_env() {
local kv
local k
local v
for option in ${options[@]}; do
kv=(${option/=/ })
k=${kv[0]} # Take first element as key
k=${k#--} # Strip leading --
k=${k//-/_} # Convert dashes to underscores
k=$(echo $k | tr '[:lower:]' '[:upper:]') # Convert to uppercase (bash3 compat)
v=${kv[1]} # Treat second element as value
v=${v:-true} # Set it to true for boolean flags
export $k="$v"
done
}
function debug() {
if [ "${VERBOSE}" == "true" ]; then
echo "[DEBUG] $*"
fi
}
function run_exit_hooks() {
command -v geodesic_on_exit >/dev/null && geodesic_on_exit
}
function use() {
DOCKER_ARGS=()
if [ -t 1 ]; then
# Running in terminal
DOCKER_ARGS+=(-it --rm --name="${DOCKER_NAME}" --env LS_COLORS --env TERM --env TERM_COLOR --env TERM_PROGRAM)
if [ -n "$SSH_AUTH_SOCK" ]; then
if [ "${OS}" == 'Linux' ]; then
# Bind-mount SSH agent socket into container (linux only)
DOCKER_ARGS+=(--volume "$SSH_AUTH_SOCK:$SSH_AUTH_SOCK"
--env SSH_AUTH_SOCK
--env SSH_CLIENT
--env SSH_CONNECTION
--env SSH_TTY
--env USER
--env USER_ID
--env GROUP_ID)
elif [ "${OS}" == 'Darwin' ] && [ "${GEODESIC_MAC_FORWARD_SOCKET}" == 'true' ]; then
# Bind-mount SSH-agent socket (available in docker-for mac Edge 2.2 release)
# Note that the file/socket /run/host-services/ssh-auth.sock does not exist
# on the host OS, it is in the Moby Linux VM in which the Docker daemon `dockerd` runs.
# See https://github.com/docker/for-mac/issues/410#issuecomment-557613306
# and https://docs.docker.com/docker-for-mac/osxfs/#namespaces
DOCKER_ARGS+=(--volume /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock
-e SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock)
fi
fi
else
DOCKER_ARGS=()
fi
if [ "${WITH_DOCKER}" == "true" ]; then
# Bind-mount docker socket into container
# Should work on Linux and Mac.
# Note that the mounted /var/run/docker.sock is not a file or
# socket in the Mac host OS, it is in the dockerd VM.
# https://docs.docker.com/docker-for-mac/osxfs/#namespaces
echo "# Enabling docker support. Be sure you install a docker CLI binary (apk add docker-cli)."
DOCKER_ARGS+=(--volume "/var/run/docker.sock:/var/run/docker.sock")
# Some reports say this is needed for Windows WSL
if [[ $(uname -r) =~ Microsoft$ ]]; then
DOCKER_ARGS+=(--user root)
fi
# NOTE: bind mounting the docker CLI binary is no longer recommended and usually does not work.
# Use a docker image with a docker CLI binary installed that is appropriate to the image's OS.
fi
if [[ ${GEODESIC_CUSTOMIZATION_DISABLED-false} == false ]]; then
if [ -n "${ENV_FILE}" ]; then
DOCKER_ARGS+=(--env-file ${ENV_FILE})
fi
# allow users to override value of GEODESIC_DEFAULT_ENV_FILE
local geodesic_default_env_file=${GEODESIC_DEFAULT_ENV_FILE:-~/.geodesic/env}
if [ -f "${geodesic_default_env_file}" ]; then
DOCKER_ARGS+=(--env-file=${geodesic_default_env_file})
fi
else
echo "# Disabling user customizations: GEODESIC_CUSTOMIZATION_DISABLED is set and not 'false'"
DOCKER_ARGS+=(--env GEODESIC_CUSTOMIZATION_DISABLED)
fi
if [ -n "${DOCKER_DNS}" ]; then
DOCKER_ARGS+=("--dns=${DOCKER_DNS}")
fi
if [ -n "${LOCAL_HOME}" ]; then
local_home=${LOCAL_HOME}
elif [[ $(uname -r) =~ Microsoft$ ]]; then
# Lookup correct mount path for WSL
mount_path=$(dirname $(findmnt -S C: -t drvfs -no target))
windows_user_name=$($mount_path/c/Windows/System32/cmd.exe /c 'echo %USERNAME%' | tr -d '\r')
user_local_app_data=$(cmd.exe /c echo %LOCALAPPDATA% | tr -d '\r' | sed -e 's/\\/\//g')
if [ -d "$mount_path/c/Users/${windows_user_name}/AppData/Local/lxss/" ]; then
local_home=${user_local_app_data}/lxss${HOME}
else
local restore_nullglob=$(shopt -p nullglob)
shopt -s nullglob
for dir in $mount_path/c/Users/${windows_user_name}/AppData/Local/Packages/CanonicalGroupLimited.Ubuntu*; do
folder_name=$(basename ${dir})
local_home=${user_local_app_data}/Packages/${folder_name}/LocalState/rootfs${HOME}
break
done
$restore_nullglob
fi
if [ -z "${local_home}" ]; then
echo "ERROR: can't identify user home directory, you may specify path via LOCAL_HOME variable"
exit 1
else
echo "Detected Windows Subsystem for Linux, mounting $local_home instead of $HOME"
fi
else
local_home=${HOME}
fi
if [ "${local_home}" == "/localhost" ]; then
echo "WARNING: not mounting ${local_home} because it conflicts with geodesic"
else
echo "# Mounting ${local_home} into container"
DOCKER_ARGS+=(--volume=${local_home}:/localhost)
DOCKER_ARGS+=(--env LOCAL_HOME=${local_home})
fi
DOCKER_ARGS+=(--privileged
--publish ${GEODESIC_PORT}:${GEODESIC_PORT}
--name "${DOCKER_NAME}"
--rm
--env GEODESIC_PORT=${GEODESIC_PORT}
--env DOCKER_IMAGE="${DOCKER_IMAGE%:*}"
--env DOCKER_NAME="${DOCKER_NAME}"
--env DOCKER_TAG="${DOCKER_TAG}")
trap run_exit_hooks EXIT
# the extra curly braces around .ID are because this file goes through go template substitution local before being installed as a shell script
container_id=$(docker ps --quiet --filter name="^/${DOCKER_NAME}\$" --format '{{ .ID }}')
if [ -n "$container_id" ]; then
echo "# Attaching to existing ${DOCKER_NAME} session ($container_id)"
if [ $# -eq 0 ]; then
set -- "/bin/bash" "-l" "$@"
fi
docker exec -it "${DOCKER_NAME}" $*
else
echo "# Starting new ${DOCKER_NAME} session from ${DOCKER_IMAGE}"
echo "# Exposing port ${GEODESIC_PORT}"
[ -z "${GEODESIC_DOCKER_EXTRA_ARGS}" ] || echo "# Launching with extra Docker args: ${GEODESIC_DOCKER_EXTRA_ARGS}"
docker run "${DOCKER_ARGS[@]}" ${GEODESIC_DOCKER_EXTRA_ARGS} ${DOCKER_IMAGE} -l $*
fi
}
function parse_args() {
while [[ $1 ]]; do
case "$1" in
-h | --help)
targets+=("help")
shift
;;
-v | --verbose)
export VERBOSE=true
shift
;;
--*)
options+=("${1}")
shift
;;
--) # End of all options
shift
;;
-*)
echo "Error: Unknown option: $1" >&2
exit 1
;;
*=*)
declare -g "${1}"
shift
;;
*)
targets+=("${1}")
shift
;;
esac
done
}
function uninstall() {
echo "# Uninstalling ${DOCKER_NAME}..."
docker rm -f ${DOCKER_NAME} >/dev/null 2>&1 || true
docker rmi -f ${DOCKER_IMAGE} >/dev/null 2>&1 || true
echo "# Not deleting $0"
exit 0
}
function update() {
echo "# Installing the latest version of ${DOCKER_IMAGE}"
docker run --rm ${DOCKER_IMAGE} | bash -s ${DOCKER_TAG}
if [ $? -eq 0 ]; then
echo "# ${DOCKER_IMAGE} has been updated."
exit 0
else
echo "Failed to update ${DOCKER_IMAGE}"
exit 1
fi
}
function stop() {
echo "# Stopping ${DOCKER_NAME}..."
exec docker kill ${DOCKER_NAME} >/dev/null 2>&1
}
function help() {
echo "Usage: $0 [target] ARGS"
echo ""
echo " Targets:"
echo " update Upgrade geodesic wrapper shell"
echo " stop Stop a running shell"
echo " uninstall Remove geodesic image"
echo " <empty> Enter into a shell"
echo ""
echo " Arguments:"
echo " --env-file=... Pass an environment file containing key=value pairs"
echo ""
}
require_installed tr
require_installed grep
parse_args "$@"
options_to_env
# Docker settings
export DOCKER_IMAGE="cloudposse/atmos"
export DOCKER_TAG="latest"
export DOCKER_NAME="atmos"
if [ -n "${GEODESIC_NAME}" ]; then
export DOCKER_NAME=$(basename "${GEODESIC_NAME:-}")
fi
if [ -n "${GEODESIC_TAG}" ]; then
export DOCKER_TAG=${GEODESIC_TAG}
fi
if [ -n "${GEODESIC_IMAGE}" ]; then
export DOCKER_IMAGE=${GEODESIC_IMAGE:-${DOCKER_IMAGE}:${DOCKER_TAG}}
else
export DOCKER_IMAGE=${DOCKER_IMAGE}:${DOCKER_TAG}
fi
export DOCKER_DNS=${DNS:-${DOCKER_DNS}}
if [ "${GEODESIC_SHELL}" == "true" ]; then
echo "Cannot run while in a geodesic shell"
exit 1
fi
if [ -z "${DOCKER_IMAGE}" ]; then
echo "Error: --image not specified (E.g. --image=cloudposse/foobar.example.com:1.0)"
exit 1
fi
require_installed docker
docker ps >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Unable to communicate with docker daemon. Make sure your environment is properly configured and then try again."
exit 1
fi
if [ -z "$targets" ]; then
# Execute default target
targets=("use")
fi
for target in $targets; do
if [ "$target" == "update" ]; then
update
elif [ "$target" == "uninstall" ]; then
uninstall
elif [ "$target" == "stop" ]; then
stop
elif [ "$target" == "use" ]; then
use
elif [ "$target" == "help" ]; then
help
else
echo "Unknown target: $target"
exit 1
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment