Skip to content

Commit

Permalink
feat: add bindfs to support linux users. Fixes #594 (#769)
Browse files Browse the repository at this point in the history
Co-authored-by: Nuru <[email protected]>
  • Loading branch information
drmikecrowe and Nuru authored Feb 3, 2022
1 parent 634aaa9 commit 90fa1b9
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 30 deletions.
12 changes: 12 additions & 0 deletions os/alpine/Dockerfile.alpine
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ RUN python3 -m pip install --upgrade pip setuptools wheel && \
pip install $(grep cryptography /requirements.txt) && \
pip install -r /requirements.txt --ignore-installed --prefix=/dist --no-build-isolation --no-warn-script-location

### While we have gcc installed, we take advantage of that and build bindfs
### Use fuse (FUSE 2) rather than fuse3 for consistency with Debian
RUN apk add curl fuse fuse-dev
RUN curl -qOsSL https://bindfs.org/downloads/bindfs-1.15.1.tar.gz
RUN tar zxf bindfs-1.15.1.tar.gz && cd bindfs-1.15.1/ && \
./configure && make && make install


#
# Google Cloud SDK
#
Expand Down Expand Up @@ -111,6 +119,9 @@ WORKDIR /tmp
# Copy python dependencies
COPY --from=python /dist/ /usr/

# Install bindfs
COPY --from=python /usr/local/bin/bindfs /usr/local/bin/bindfs

#
# Install Google Cloud SDK
#
Expand Down Expand Up @@ -151,6 +162,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh

RUN chmod 755 /etc/bash_completion.d/kubens.sh /etc/bash_completion.d/kubectx.sh /etc/profile.d/prompt:kube-ps1.sh

#
# Install helm
Expand Down
1 change: 1 addition & 0 deletions os/alpine/packages-alpine.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
busybox-extras
diffutils
drill
fuse
fzf-bash-completion
iputils
keybase-client@testing
Expand Down
3 changes: 2 additions & 1 deletion os/debian/Dockerfile.debian
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ COPY packages.txt os/debian/packages-debian.txt /etc/apt/
## Here is where we would copy in the repo checksum in an attempt to ensure updates bust the Docker build cache

# Add CloudPosse package repo
RUN apt-get update && apt-get install -y apt-utils && apt-get install -y curl
RUN apt-get update && apt-get install -y apt-utils curl
RUN curl -1sLf 'https://dl.cloudsmith.io/public/cloudposse/packages/cfg/setup/bash.deb.sh' | bash

# Install Google package repo
Expand Down Expand Up @@ -178,6 +178,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh

RUN chmod 755 /etc/bash_completion.d/kubens.sh /etc/bash_completion.d/kubectx.sh /etc/profile.d/prompt:kube-ps1.sh

#
# Install helm
Expand Down
1 change: 1 addition & 0 deletions os/debian/packages-debian.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Essential debian-only packages
bindfs
default-mysql-client
dnsutils
inetutils-ftp
Expand Down
14 changes: 7 additions & 7 deletions rootfs/etc/motd
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

IMPORTANT:
* Unless there were errors reported above,
* your host $HOME directory should be mounted to `/localhost`, and
* your host AWS configuration and credentials should be available.
* Use Leapp on your host computer to manage your credentials.
* Leapp is free, open source, and available from https://leapp.cloud
* Use AWS_PROFILE environment variable to manage your AWS IAM role.
* You can interactively select AWS profiles via the `assume-role` command.
# Unless there were errors reported above,
# * Your host $HOME directory should be available under `/localhost`
# * Your host AWS configuration and credentials should be available
# * Use Leapp on your host computer to manage your credentials
# * Leapp is free, open source, and available from https://leapp.cloud
# * Use AWS_PROFILE environment variable to manage your AWS IAM role
# * You can interactively select AWS profiles via the `assume-role` command


Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _colors.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here. This file has no dependencies and should come first.
# This file is named _10-colors.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here. The number portion is to ensure proper ordering among
# the high-priority scripts
# This file has no dependencies and should come first.
function red() {
echo "$(tput setaf 1)$*$(tput setaf 0)"
}
Expand Down Expand Up @@ -32,4 +34,4 @@ function bold() {
# The terminal does not support color
printf "%s\n" "$*"
fi
}
}
30 changes: 30 additions & 0 deletions rootfs/etc/profile.d/_20-localhost.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _20-localhost.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the file system mapping defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file has only depends on colors.sh and should come before any scripts that
# attempt to access files on the host via `/localhost`.

if [[ $SHLVL == 1 ]] && [[ -n $GEODESIC_HOST_UID ]] && [[ -n $GEODESIC_HOST_GID ]] \
&& [[ -n $GEODESIC_LOCALHOST ]] && df -a | grep -q " ${GEODESIC_LOCALHOST}\$"; then
if [[ $(df -a | grep ' /localhost$') =~ ^${GEODESIC_LOCALHOST} ]]; then
echo "# Host file ownership mapping already configured"
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
elif df -a | grep -q ' /localhost$'; then
red "# Host filesystems found mounted at both /localhost and /localhost.bindfs."
red "# * Verify that content under /localhost is what you expect."
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
red "# Include the output of `env | grep GEODESIC` in your issue description."
elif bindfs -o nonempty ${GEODESIC_BINDFS_OPTIONS} --create-for-user="$GEODESIC_HOST_UID" --create-for-group="$GEODESIC_HOST_GID" "${GEODESIC_LOCALHOST}" /localhost; then
green "# Files on host (under /localhost) will be created with UID:GID ${GEODESIC_HOST_UID}:${GEODESIC_HOST_GID}"
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
else
red "# ERROR: Unable to mirror /localhost.bindfs to /localhost"
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
red "# * Work around the issue by setting shell environment variable"
red "# GEODESIC_HOST_BINDFS=disabled"
red "# before running Geodesic."
red "# * Exiting."
exec false
fi
fi
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _geodesic-config.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here.
# This file has depends on _colors.sh and should come second.
# This file is named _30-geodesic-config.sh. The leading underscore is needed to ensure this file
# executes before other files that depend on the functions defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file defines functions but does not execute them, so it can come anywhere
# before the first script to use one of its functions, such as preferences.sh.

# bash functions that support the user customization framework
#
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _preferences.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here.
# This file has depends on _geodesic-config.sh and should come third.
# This file is named _40-preferences.sh. The leading underscore is needed to ensure this file
# executes before other files that depend on the functions defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file has depends on colors.sh, geodesic-config.sh, and localhost.sh and should come after them.
# This file loads user preferences/customizations and must load before any user-visible configuration takes place.

# In case this output is being piped into a shell, print a warning message
Expand Down Expand Up @@ -58,10 +59,10 @@ elif [[ ! -d $GEODESIC_CONFIG_HOME ]]; then
fi

if [[ ! -d $GEODESIC_CONFIG_HOME ]]; then
if ! df | grep -q /localhost; then
if ! df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
if [[ -z $KUBERNETES_PORT ]]; then
red "########################################################################################" >&2
red "# No filesystem is mounted at $(bold /localhost) which limits Geodesic functionality." >&2
red "# No filesystem is mounted at $(bold ${GEODESIC_LOCALHOST:-/localhost}) which limits Geodesic functionality." >&2
boot install
else
echo $(green Kubernetes host detected, Geodesic customization disabled.)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file sets the working directory inside Geodesic to match the host directory Geodesic
# was launched from, if possible. If the host directory is not accessible, it sets the working directory to `/`.
#
# This file is named _workdir.sh. The leading underscore is needed to ensure this file executes before
# other files that may depend on it. The "w" is needed to ensure it is loaded *after* _preferences.sh
# This file is named _50-workdir.sh. The leading underscore is needed to ensure this file
# executes before other files that may depend on it.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file depends on colors.sh, localhost.sh, and preferences,sh and must come after them
#

function _file_device() {
Expand All @@ -16,8 +15,8 @@ function _file_device() {
# Therefore we cache some info in the environment.
if [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]]; then
red "# Host filesystem device detection disabled."
elif df -a | grep -q /localhost; then
export GEODESIC_LOCALHOST_DEVICE=$(_file_device /localhost)
elif df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
export GEODESIC_LOCALHOST_DEVICE=$(_file_device "${GEODESIC_LOCALHOST:-/localhost}")
if [[ $GEODESIC_LOCALHOST_DEVICE == $(_file_device /) ]]; then
red "# Host filesystem device detection failed. Falling back to \"path starts with /localhost\"."
GEODESIC_LOCALHOST_DEVICE="same-as-root"
Expand All @@ -32,7 +31,8 @@ function file_on_host() {
elif [[ $GEODESIC_LOCALHOST_DEVICE == "same-as-root" ]]; then
[[ $(readlink -e "$1") =~ ^/localhost(/.*)?$ ]]
else
[[ $(_file_device "$1") == ${GEODESIC_LOCALHOST_DEVICE} ]]
local regex="^(${GEODESIC_LOCALHOST_DEVICE}${GEODESIC_LOCALHOST_MAPPED_DEVICE:+|${GEODESIC_LOCALHOST_MAPPED_DEVICE}})\$"
[[ $(_file_device "$1") =~ ${regex} ]]
fi
}

Expand All @@ -52,7 +52,7 @@ if [[ -d $GEODESIC_WORKDIR ]]; then
[[ $SHLVL == 1 ]] && green "# Initial working directory configured as ${GEODESIC_WORKDIR}"
else
if [[ -d $GEODESIC_HOST_CWD ]]; then
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || $(file_on_host "$GEODESIC_HOST_CWD"); }; then
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || file_on_host "$GEODESIC_HOST_CWD"; }; then
export GEODESIC_WORKDIR=$(readlink -e "${GEODESIC_HOST_CWD}")
green "# Initial working directory set from host CWD to ${GEODESIC_WORKDIR}"
else
Expand Down
5 changes: 4 additions & 1 deletion rootfs/etc/profile.d/prompt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export SCREEN_SIZE="${LINES}x${COLUMNS}"
# So we cannot just unthinkingly set PROMPT_COMMAND=prompter or PROMPT_COMMAND="${PROMPT_COMMAND};prompter"
# Instead, we examine the PROMPT_COMMAND variable, initialize it to "prompter;" if it is empty,
# or otherwise add "prompter;" to the end of the command string (inserting a ; before it if needed).
export PROMPT_COMMAND
# We do not want subshells to try to run prompt commands if they are not defined, so we do not export PROMPT_COMMAND
export -n PROMPT_COMMAND
# We do not want our dynamic prompt to be copied and not updated in a subshell, so we do not export PS1, either
export -n PS1
function _install_prompter() {
if ! [[ $PROMPT_COMMAND =~ prompter ]]; then
local final_colon=';$'
Expand Down
11 changes: 10 additions & 1 deletion rootfs/templates/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ function use() {
DOCKER_ARGS=()
fi

if [ "${GEODESIC_HOST_BINDFS}" = "forced" ] || { [ "${OS}" = 'Linux' ] && [ "${GEODESIC_HOST_BINDFS}" != "disabled" ]; }; then
DOCKER_ARGS+=(
--env GEODESIC_HOST_UID="${USER_ID}"
--env GEODESIC_HOST_GID="${GROUP_ID}"
--env GEODESIC_LOCALHOST="${GEODESIC_LOCALHOST:=/localhost.bindfs}"
--env GEODESIC_BINDFS_OPTIONS
)
fi

if [ "${WITH_DOCKER}" == "true" ]; then
# Bind-mount docker socket into container
# Should work on Linux and Mac.
Expand Down Expand Up @@ -157,7 +166,7 @@ function use() {
else
echo "# Mounting ${local_home} into container with workdir ${GEODESIC_HOST_CWD}"
DOCKER_ARGS+=(
--volume="${local_home}:/localhost"
--volume="${local_home}:${GEODESIC_LOCALHOST:-/localhost}"
--env LOCAL_HOME="${local_home}"
)
fi
Expand Down

0 comments on commit 90fa1b9

Please sign in to comment.