Skip to content

Commit 90fa1b9

Browse files
drmikecroweNuru
andauthored
feat: add bindfs to support linux users. Fixes #594 (#769)
Co-authored-by: Nuru <Nuru@users.noreply.github.com>
1 parent 634aaa9 commit 90fa1b9

12 files changed

+92
-30
lines changed

os/alpine/Dockerfile.alpine

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ RUN python3 -m pip install --upgrade pip setuptools wheel && \
3333
pip install $(grep cryptography /requirements.txt) && \
3434
pip install -r /requirements.txt --ignore-installed --prefix=/dist --no-build-isolation --no-warn-script-location
3535

36+
### While we have gcc installed, we take advantage of that and build bindfs
37+
### Use fuse (FUSE 2) rather than fuse3 for consistency with Debian
38+
RUN apk add curl fuse fuse-dev
39+
RUN curl -qOsSL https://bindfs.org/downloads/bindfs-1.15.1.tar.gz
40+
RUN tar zxf bindfs-1.15.1.tar.gz && cd bindfs-1.15.1/ && \
41+
./configure && make && make install
42+
43+
3644
#
3745
# Google Cloud SDK
3846
#
@@ -111,6 +119,9 @@ WORKDIR /tmp
111119
# Copy python dependencies
112120
COPY --from=python /dist/ /usr/
113121

122+
# Install bindfs
123+
COPY --from=python /usr/local/bin/bindfs /usr/local/bin/bindfs
124+
114125
#
115126
# Install Google Cloud SDK
116127
#
@@ -151,6 +162,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
151162
ARG KUBE_PS1_VERSION
152163
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh
153164

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

155167
#
156168
# Install helm

os/alpine/packages-alpine.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
busybox-extras
33
diffutils
44
drill
5+
fuse
56
fzf-bash-completion
67
iputils
78
keybase-client@testing

os/debian/Dockerfile.debian

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ COPY packages.txt os/debian/packages-debian.txt /etc/apt/
107107
## Here is where we would copy in the repo checksum in an attempt to ensure updates bust the Docker build cache
108108

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

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

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

182183
#
183184
# Install helm

os/debian/packages-debian.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Essential debian-only packages
2+
bindfs
23
default-mysql-client
34
dnsutils
45
inetutils-ftp

rootfs/etc/motd

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11

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

1111

rootfs/etc/profile.d/_colors.sh renamed to rootfs/etc/profile.d/_10-colors.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Files in the profile.d directory are executed by the lexicographical order of their file names.
2-
# This file is named _colors.sh. The leading underscore is needed to ensure this file executes before
3-
# other files that depend on the functions defined here. This file has no dependencies and should come first.
2+
# This file is named _10-colors.sh. The leading underscore is needed to ensure this file executes before
3+
# other files that depend on the functions defined here. The number portion is to ensure proper ordering among
4+
# the high-priority scripts
5+
# This file has no dependencies and should come first.
46
function red() {
57
echo "$(tput setaf 1)$*$(tput setaf 0)"
68
}
@@ -32,4 +34,4 @@ function bold() {
3234
# The terminal does not support color
3335
printf "%s\n" "$*"
3436
fi
35-
}
37+
}

rootfs/etc/profile.d/_20-localhost.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Files in the profile.d directory are executed by the lexicographical order of their file names.
2+
# This file is named _20-localhost.sh. The leading underscore is needed to ensure this file executes before
3+
# other files that depend on the file system mapping defined here.
4+
# The number portion is to ensure proper ordering among the high-priority scripts.
5+
# This file has only depends on colors.sh and should come before any scripts that
6+
# attempt to access files on the host via `/localhost`.
7+
8+
if [[ $SHLVL == 1 ]] && [[ -n $GEODESIC_HOST_UID ]] && [[ -n $GEODESIC_HOST_GID ]] \
9+
&& [[ -n $GEODESIC_LOCALHOST ]] && df -a | grep -q " ${GEODESIC_LOCALHOST}\$"; then
10+
if [[ $(df -a | grep ' /localhost$') =~ ^${GEODESIC_LOCALHOST} ]]; then
11+
echo "# Host file ownership mapping already configured"
12+
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
13+
elif df -a | grep -q ' /localhost$'; then
14+
red "# Host filesystems found mounted at both /localhost and /localhost.bindfs."
15+
red "# * Verify that content under /localhost is what you expect."
16+
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
17+
red "# Include the output of `env | grep GEODESIC` in your issue description."
18+
elif bindfs -o nonempty ${GEODESIC_BINDFS_OPTIONS} --create-for-user="$GEODESIC_HOST_UID" --create-for-group="$GEODESIC_HOST_GID" "${GEODESIC_LOCALHOST}" /localhost; then
19+
green "# Files on host (under /localhost) will be created with UID:GID ${GEODESIC_HOST_UID}:${GEODESIC_HOST_GID}"
20+
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
21+
else
22+
red "# ERROR: Unable to mirror /localhost.bindfs to /localhost"
23+
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
24+
red "# * Work around the issue by setting shell environment variable"
25+
red "# GEODESIC_HOST_BINDFS=disabled"
26+
red "# before running Geodesic."
27+
red "# * Exiting."
28+
exec false
29+
fi
30+
fi

rootfs/etc/profile.d/_geodesic-config.sh renamed to rootfs/etc/profile.d/_30-geodesic-config.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Files in the profile.d directory are executed by the lexicographical order of their file names.
2-
# This file is named _geodesic-config.sh. The leading underscore is needed to ensure this file executes before
3-
# other files that depend on the functions defined here.
4-
# This file has depends on _colors.sh and should come second.
2+
# This file is named _30-geodesic-config.sh. The leading underscore is needed to ensure this file
3+
# executes before other files that depend on the functions defined here.
4+
# The number portion is to ensure proper ordering among the high-priority scripts.
5+
# This file defines functions but does not execute them, so it can come anywhere
6+
# before the first script to use one of its functions, such as preferences.sh.
57

68
# bash functions that support the user customization framework
79
#

rootfs/etc/profile.d/_preferences.sh renamed to rootfs/etc/profile.d/_40-preferences.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Files in the profile.d directory are executed by the lexicographical order of their file names.
2-
# This file is named _preferences.sh. The leading underscore is needed to ensure this file executes before
3-
# other files that depend on the functions defined here.
4-
# This file has depends on _geodesic-config.sh and should come third.
2+
# This file is named _40-preferences.sh. The leading underscore is needed to ensure this file
3+
# executes before other files that depend on the functions defined here.
4+
# The number portion is to ensure proper ordering among the high-priority scripts.
5+
# This file has depends on colors.sh, geodesic-config.sh, and localhost.sh and should come after them.
56
# This file loads user preferences/customizations and must load before any user-visible configuration takes place.
67

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

6061
if [[ ! -d $GEODESIC_CONFIG_HOME ]]; then
61-
if ! df | grep -q /localhost; then
62+
if ! df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
6263
if [[ -z $KUBERNETES_PORT ]]; then
6364
red "########################################################################################" >&2
64-
red "# No filesystem is mounted at $(bold /localhost) which limits Geodesic functionality." >&2
65+
red "# No filesystem is mounted at $(bold ${GEODESIC_LOCALHOST:-/localhost}) which limits Geodesic functionality." >&2
6566
boot install
6667
else
6768
echo $(green Kubernetes host detected, Geodesic customization disabled.)

rootfs/etc/profile.d/_workdir.sh renamed to rootfs/etc/profile.d/_50-workdir.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# Files in the profile.d directory are executed by the lexicographical order of their file names.
2-
# This file sets the working directory inside Geodesic to match the host directory Geodesic
3-
# was launched from, if possible. If the host directory is not accessible, it sets the working directory to `/`.
4-
#
5-
# This file is named _workdir.sh. The leading underscore is needed to ensure this file executes before
6-
# other files that may depend on it. The "w" is needed to ensure it is loaded *after* _preferences.sh
2+
# This file is named _50-workdir.sh. The leading underscore is needed to ensure this file
3+
# executes before other files that may depend on it.
4+
# The number portion is to ensure proper ordering among the high-priority scripts.
5+
# This file depends on colors.sh, localhost.sh, and preferences,sh and must come after them
76
#
87

98
function _file_device() {
@@ -16,8 +15,8 @@ function _file_device() {
1615
# Therefore we cache some info in the environment.
1716
if [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]]; then
1817
red "# Host filesystem device detection disabled."
19-
elif df -a | grep -q /localhost; then
20-
export GEODESIC_LOCALHOST_DEVICE=$(_file_device /localhost)
18+
elif df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
19+
export GEODESIC_LOCALHOST_DEVICE=$(_file_device "${GEODESIC_LOCALHOST:-/localhost}")
2120
if [[ $GEODESIC_LOCALHOST_DEVICE == $(_file_device /) ]]; then
2221
red "# Host filesystem device detection failed. Falling back to \"path starts with /localhost\"."
2322
GEODESIC_LOCALHOST_DEVICE="same-as-root"
@@ -32,7 +31,8 @@ function file_on_host() {
3231
elif [[ $GEODESIC_LOCALHOST_DEVICE == "same-as-root" ]]; then
3332
[[ $(readlink -e "$1") =~ ^/localhost(/.*)?$ ]]
3433
else
35-
[[ $(_file_device "$1") == ${GEODESIC_LOCALHOST_DEVICE} ]]
34+
local regex="^(${GEODESIC_LOCALHOST_DEVICE}${GEODESIC_LOCALHOST_MAPPED_DEVICE:+|${GEODESIC_LOCALHOST_MAPPED_DEVICE}})\$"
35+
[[ $(_file_device "$1") =~ ${regex} ]]
3636
fi
3737
}
3838

@@ -52,7 +52,7 @@ if [[ -d $GEODESIC_WORKDIR ]]; then
5252
[[ $SHLVL == 1 ]] && green "# Initial working directory configured as ${GEODESIC_WORKDIR}"
5353
else
5454
if [[ -d $GEODESIC_HOST_CWD ]]; then
55-
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || $(file_on_host "$GEODESIC_HOST_CWD"); }; then
55+
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || file_on_host "$GEODESIC_HOST_CWD"; }; then
5656
export GEODESIC_WORKDIR=$(readlink -e "${GEODESIC_HOST_CWD}")
5757
green "# Initial working directory set from host CWD to ${GEODESIC_WORKDIR}"
5858
else

rootfs/etc/profile.d/prompt.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ export SCREEN_SIZE="${LINES}x${COLUMNS}"
1616
# So we cannot just unthinkingly set PROMPT_COMMAND=prompter or PROMPT_COMMAND="${PROMPT_COMMAND};prompter"
1717
# Instead, we examine the PROMPT_COMMAND variable, initialize it to "prompter;" if it is empty,
1818
# or otherwise add "prompter;" to the end of the command string (inserting a ; before it if needed).
19-
export PROMPT_COMMAND
19+
# We do not want subshells to try to run prompt commands if they are not defined, so we do not export PROMPT_COMMAND
20+
export -n PROMPT_COMMAND
21+
# We do not want our dynamic prompt to be copied and not updated in a subshell, so we do not export PS1, either
22+
export -n PS1
2023
function _install_prompter() {
2124
if ! [[ $PROMPT_COMMAND =~ prompter ]]; then
2225
local final_colon=';$'

rootfs/templates/wrapper

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ function use() {
8383
DOCKER_ARGS=()
8484
fi
8585

86+
if [ "${GEODESIC_HOST_BINDFS}" = "forced" ] || { [ "${OS}" = 'Linux' ] && [ "${GEODESIC_HOST_BINDFS}" != "disabled" ]; }; then
87+
DOCKER_ARGS+=(
88+
--env GEODESIC_HOST_UID="${USER_ID}"
89+
--env GEODESIC_HOST_GID="${GROUP_ID}"
90+
--env GEODESIC_LOCALHOST="${GEODESIC_LOCALHOST:=/localhost.bindfs}"
91+
--env GEODESIC_BINDFS_OPTIONS
92+
)
93+
fi
94+
8695
if [ "${WITH_DOCKER}" == "true" ]; then
8796
# Bind-mount docker socket into container
8897
# Should work on Linux and Mac.
@@ -157,7 +166,7 @@ function use() {
157166
else
158167
echo "# Mounting ${local_home} into container with workdir ${GEODESIC_HOST_CWD}"
159168
DOCKER_ARGS+=(
160-
--volume="${local_home}:/localhost"
169+
--volume="${local_home}:${GEODESIC_LOCALHOST:-/localhost}"
161170
--env LOCAL_HOME="${local_home}"
162171
)
163172
fi

0 commit comments

Comments
 (0)