Created
July 22, 2022 18:36
-
-
Save 3h4x/883cf3c04d860ff6386b030d82be3d33 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
# 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