diff --git a/devspaces-udi/Dockerfile b/devspaces-udi/Dockerfile index f720e88a78..cd11c6e9ac 100644 --- a/devspaces-udi/Dockerfile +++ b/devspaces-udi/Dockerfile @@ -23,7 +23,7 @@ RUN \ ######################################################################## dnf -y -q install golang make gzip which openshift-clients && \ # BEGIN Gopls - mkdir /home/user/go/bin -p && \ + mkdir /home/tooling/go/bin -p && \ cd $REMOTE_SOURCES_DIR/gopls/app/gopls && \ # gopls must refer to tools as local dependency, which is located one dir above in the project echo 'replace golang.org/x/tools => ../' >> go.mod && \ @@ -34,7 +34,6 @@ RUN \ # END Gopls # BEGIN Kubedock - mkdir /home/user/go/bin -p && \ cd $REMOTE_SOURCES_DIR/kubedock/app && \ # build kubedock application with dependencies resolved by Cachito source $REMOTE_SOURCES_DIR/kubedock/cachito.env && \ @@ -44,7 +43,7 @@ RUN \ -X github.com/joyrex2001/kubedock/internal/config.Image=joyrex2001/kubedock:0.11.0" && \ CGO_ENABLED=0 go build -ldflags "${LDFLAGS}" -o kubedock && \ chmod +x ./kubedock && \ - ./kubedock version + ./kubedock version && \ # END Kubedock # CRW-3193 disable until we have a camel-k sample again @@ -55,13 +54,25 @@ RUN \ # ./kamel version && \ # END Kamel + # BEGIN stow + dnf -y -q install perl texinfo texinfo-tex git && \ + cd $REMOTE_SOURCES_DIR/stow/app && \ + mkdir -p $REMOTE_SOURCES_DIR/stow/app/build && \ + autoreconf -iv && \ + ./configure --prefix=$REMOTE_SOURCES_DIR/stow/app/build && \ + make install && \ + cd $REMOTE_SOURCES_DIR/stow/app/build/bin/ && \ + ./stow --version + # END stow + # https://registry.access.redhat.com/ubi8-minimal FROM ubi8-minimal:8.9-1029 USER root ENV \ - HOME=/home/user \ + # We install everything to /home/tooling/ as /home/user/ may get overwritten, see github.com/eclipse/che/issues/22412 + HOME=/home/tooling \ NODEJS_VERSION="18" \ PYTHON_VERSION="3.11" \ PHP_VERSION="7.4" \ @@ -74,13 +85,16 @@ ENV \ JAVA_HOME_8=/usr/lib/jvm/java-1.8.0-openjdk \ JAVA_HOME="/home/user/.java/current" \ GOBIN="/home/user/go/bin/" \ - PATH="/home/user/.local/bin:/home/user/.java/current/bin:/home/user/node_modules/.bin/:/home/user/.npm-global/bin/:/opt/app-root/src/.npm-global/bin/:/usr/share/maven/bin:/usr/bin:/home/user/go/bin:${PATH:-/bin:/usr/bin}" \ + # We have $PATH entries in /home/tooling/ (in addition to /home/user/) to ensure binaries can be found in case /home/user/ has been ovewritten and stow has not yet run in the entrypoint + PATH="/home/user/.local/bin:/home/user/.java/current/bin:/home/user/node_modules/.bin/:/home/user/.npm-global/bin/:/opt/app-root/src/.npm-global/bin/:/usr/share/maven/bin:/usr/bin:/home/user/go/bin::/home/tooling/.local/bin:/home/tooling/.java/current/bin:/home/tooling/node_modules/.bin/:/home/tooling/.npm-global/bin/:/home/tooling/go/bin:${PATH:-/bin:/usr/bin}" \ MANPATH="/usr/share/man:${MANPATH}" \ JAVACONFDIRS="/etc/java${JAVACONFDIRS:+:}${JAVACONFDIRS:-}" \ XDG_CONFIG_DIRS="/etc/xdg:${XDG_CONFIG_DIRS:-/etc/xdg}" \ XDG_DATA_DIRS="/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" \ M2_HOME="/usr/share/maven" \ PKG_CONFIG_PATH="/usr/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}" \ + KUBECONFIG=/home/user/.kube/config \ + PROFILE_EXT=/etc/profile.d/udi_environment.sh \ # Rootless podman install #1: # Set up environment variables to note that this is # not starting with usernamespace and default to @@ -104,11 +118,13 @@ LABEL summary="$SUMMARY" \ io.openshift.expose-services="" \ usage="" +RUN mkdir -p /home/tooling/ ADD etc/storage.conf $HOME/.config/containers/storage.conf ADD etc/entrypoint.sh /entrypoint.sh COPY $REMOTE_SOURCES $REMOTE_SOURCES_DIR -RUN echo 'alias docker=podman' >> /home/user/.bashrc COPY --chown=0:0 etc/podman-wrapper.sh /usr/bin/ +RUN mkdir -p /home/tooling/ +COPY --chown=0:0 etc/.stow-local-ignore /home/tooling/ # NOTE: uncomment for local build. Must also set full registry path in FROM to registry.redhat.io or registry.access.redhat.com # enable rhel 8 content sets (from Brew) to resolve buildah @@ -121,7 +137,10 @@ COPY --chown=0:0 etc/podman-wrapper.sh /usr/bin/ RUN \ # install all the rpms and modules microdnf install -y dnf && \ - dnf -y -q module reset container-tools maven nodejs python3.11 php; \ + # Disable codeready-builder repos to prevent accidentally installing incorrect packages + dnf -y -q install 'dnf-command(config-manager)' && \ + dnf config-manager --set-disabled codeready-* && \ + dnf -y -q module reset container-tools maven nodejs php; \ dnf -y -q module install container-tools:rhel8 maven:3.6 nodejs:$NODEJS_VERSION php:$PHP_VERSION && \ dnf -y -q install --setopt=tsflags=nodocs \ golang \ @@ -136,7 +155,7 @@ RUN \ libssh-devel libffi-devel redhat-rpm-config cargo openssl-devel pkg-config jq \ podman buildah skopeo fuse-overlayfs \ e2fsprogs libatomic_ops git openssl-devel ca-certificates \ - bash tar gzip unzip bzip2 which shadow-utils findutils wget curl sudo git git-lfs procps-ng tree \ + bash bash-completion tar gzip unzip bzip2 which shadow-utils findutils wget curl sudo git git-lfs procps-ng tree vim \ # For OpenShift Client 4 (oc): rhocp-4.12-for-rhel-8-x86_64-rpms # must hard code a version because otherwise CVP/Brew fails with: Failed component comparison for components: openshift-clients # https://rhsm-pulp.corp.redhat.com/content/dist/layered/rhel8/x86_64/ocp-tools/4.12/os/Packages/o/odo-3.9.0-1.el8.x86_64.rpm @@ -158,8 +177,14 @@ RUN \ mkdir -p /opt && \ # add user and configure it useradd -u 1000 -G wheel,root -d /home/user --shell /bin/bash -m user && \ + # Bash-related files are backed up to /home/tooling/ in case they are deleted when persistUserHome is enabled. + cp /home/user/.bashrc /home/tooling/.bashrc && \ + cp /home/user/.bash_profile /home/tooling/.bash_profile && \ + # $PROFILE_EXT contains all additions made to the bash environment + touch ${PROFILE_EXT} && \ # Setup $PS1 for a consistent and reasonable prompt - echo "export PS1='\W \`git branch --show-current 2>/dev/null | sed -r -e \"s@^(.+)@\(\1\) @\"\`$ '" >> "${HOME}"/.bashrc && \ + touch /etc/profile.d/udi_prompt.sh && \ + echo "export PS1='\W \`git branch --show-current 2>/dev/null | sed -r -e \"s@^(.+)@\(\1\) @\"\`$ '" >> /etc/profile.d/udi_prompt.sh && \ # Change permissions to let any arbitrary user mkdir -p /projects && \ for f in "${HOME}" "/etc/passwd" "/etc/group" "/projects"; do \ @@ -172,7 +197,9 @@ RUN \ > ${HOME}/passwd.template && \ cat /etc/group | \ sed s#root:x:0:#root:x:0:0,\${USER_ID}:#g \ - > ${HOME}/group.template + > ${HOME}/group.template && \ + # Define user directory for binaries + mkdir -p /home/tooling/.local/bin RUN \ ## Rootless podman install #2: install podman buildah skopeo e2fsprogs (above) @@ -193,12 +220,21 @@ RUN \ ## Rootless podman install #6: rename podman to allow the execution of 'podman run' using ## kubedock but 'podman build' using podman.orig mv /usr/bin/podman /usr/bin/podman.orig && \ - # set up go/bin folder - mkdir /home/user/go/bin -p + # Docker alias + echo 'alias docker=podman' >> ${PROFILE_EXT} RUN \ # configure runtimes ######################################################################## + # Common tooling configuration directories + ######################################################################## + mkdir -p /home/tooling/.m2 && \ + mkdir -p /home/tooling/.config/pip && \ + mkdir -p /home/tooling/.cargo && \ + mkdir -p /home/tooling/certs && \ + mkdir -p /home/tooling/.composer && \ + mkdir -p /home/tooling/.nuget && \ + ######################################################################## # Java ######################################################################## mkdir -p ${HOME}/.java/current && \ @@ -249,7 +285,7 @@ RUN \ echo -n "/usr/local/bin/pytest: "; /usr/local/bin/pytest --version && \ echo -n "/usr/local/bin/yq: "; /usr/local/bin/yq --version && \ # set up ~/.venv - mkdir -p /home/user; cd /home/user; /usr/bin/python${PYTHON_VERSION} -m venv .venv && \ + cd /home/tooling; /usr/bin/python${PYTHON_VERSION} -m venv .venv && \ echo "<== Create python symlinks (or display existing ones)" # TODO: to enable flake8 as default linter, add this to project's .vscode/settings.json file # { @@ -330,6 +366,13 @@ xdebug.log=\${HOME}/xdebug.log" >> /etc/php.ini && \ # see container.yaml COPY --from=go-builder $REMOTE_SOURCES_DIR/gopls/app/gopls/gopls $HOME/go/bin/gopls COPY --from=go-builder $REMOTE_SOURCES_DIR/kubedock/app/kubedock $HOME/go/bin/kubedock +COPY --from=go-builder $REMOTE_SOURCES_DIR/stow/app/build/bin/ /usr/bin/ +COPY --from=go-builder $REMOTE_SOURCES_DIR/stow/app/build/share/ /usr/share/ + +# Create symbolic links from /home/tooling/ -> /home/user/ +RUN stow . -t /home/user/ -d /home/tooling/ --no-folding && \ + # .viminfo cannot be a symbolic link for security reasons, so copy it to /home/user/ + cp /home/tooling/.viminfo /home/user/.viminfo ######################################################################## @@ -393,8 +436,9 @@ RUN \ echo "========" # A last pass to make sure that an arbitrary user can write in $HOME -RUN mkdir -p /home/user && chgrp -R 0 /home && chmod -R g=u /home +RUN chgrp -R 0 /home && chmod -R g=u /home +ENV HOME=/home/user ENTRYPOINT [ "/entrypoint.sh" ] WORKDIR /projects CMD tail -f /dev/null diff --git a/devspaces-udi/container.yaml b/devspaces-udi/container.yaml index 6e6e755d58..ff4805545a 100644 --- a/devspaces-udi/container.yaml +++ b/devspaces-udi/container.yaml @@ -64,3 +64,10 @@ remote_sources: ref: 9d21955b52e4905d916d24e724dcad195aef3515 pkg_managers: - gomod + +- name: stow + remote_source: + repo: https://github.com/aspiers/stow + ref: 4ef5eca4a9d107b24e712bb4c2c91f47e7e0fb85 + pkg_managers: [] + flags: ["include-git-dir"] diff --git a/devspaces-udi/content_sets.yml b/devspaces-udi/content_sets.yml index 504ad0430f..a13a3f8abe 100644 --- a/devspaces-udi/content_sets.yml +++ b/devspaces-udi/content_sets.yml @@ -14,13 +14,16 @@ x86_64: - rhel-8-for-x86_64-appstream-rpms - ocp-tools-4.12-for-rhel-8-x86_64-rpms - rhocp-4.12-for-rhel-8-x86_64-rpms +- codeready-builder-for-rhel-8-x86_64-rpms s390x: - rhel-8-for-s390x-baseos-rpms - rhel-8-for-s390x-appstream-rpms - ocp-tools-4.12-for-rhel-8-s390x-rpms - rhocp-4.12-for-rhel-8-s390x-rpms +- codeready-builder-for-rhel-8-s390x-rpms ppc64le: - rhel-8-for-ppc64le-baseos-rpms - rhel-8-for-ppc64le-appstream-rpms - ocp-tools-4.12-for-rhel-8-ppc64le-rpms - rhocp-4.12-for-rhel-8-ppc64le-rpms +- codeready-builder-for-rhel-8-ppc64le-rpms diff --git a/devspaces-udi/etc/.stow-local-ignore b/devspaces-udi/etc/.stow-local-ignore new file mode 100644 index 0000000000..9a4d5ce28e --- /dev/null +++ b/devspaces-udi/etc/.stow-local-ignore @@ -0,0 +1,7 @@ +# .viminfo cannot be a symlink for security reasons +\.viminfo + +# We store bash related files in /home/tooling/ so they aren't overriden if persistUserHome is enabled +# but we don't want them to be symbolic links (or to cause stow conflicts). They will be copied to /home/user/ manually. +\.bashrc +\.bash_profile diff --git a/devspaces-udi/etc/entrypoint.sh b/devspaces-udi/etc/entrypoint.sh index a660218a66..bd9806d4f7 100755 --- a/devspaces-udi/etc/entrypoint.sh +++ b/devspaces-udi/etc/entrypoint.sh @@ -42,31 +42,24 @@ if [ -f "${HOME}"/.venv/bin/activate ]; then source "${HOME}"/.venv/bin/activate fi -############################################################################# -# Setup $PS1 for a consistent and reasonable prompt -############################################################################# -if [ -w "${HOME}" ] && [ ! -f "${HOME}"/.bashrc ]; then - echo "PS1='[\u@\h \W]\$ '" >> "${HOME}"/.bashrc -fi - ############################################################################# # use java 8 if USE_JAVA8 is set to 'true', # use java 17 if USE_JAVA17 is set to 'true', # by default it is java 11 ############################################################################# -rm -rf "${HOME}"/.java/current -mkdir -p "${HOME}"/.java/current +rm -rf /home/tooling/.java/current +mkdir -p /home/tooling/.java/current if [ "${USE_JAVA8}" == "true" ] && [ ! -z "${JAVA_HOME_8}" ]; then - ln -s "${JAVA_HOME_8}"/* "${HOME}"/.java/current + ln -s "${JAVA_HOME_8}"/* /home/tooling/.java/current echo "Java environment set to ${JAVA_HOME_8}" elif [ "${USE_JAVA17}" == "true" ] && [ ! -z "${JAVA_HOME_17}" ]; then - ln -s "${JAVA_HOME_17}"/* "${HOME}"/.java/current + ln -s "${JAVA_HOME_17}"/* /home/tooling/.java/current echo "Java environment set to ${JAVA_HOME_17}" else # End of Support for OpenJDK 11 in October 2024 # https://access.redhat.com/articles/1299013 echo "TODO: it needs to set JDK 17 as default before OpenJDK 11 hits EOL in October 2024" - ln -s "${JAVA_HOME_11}"/* "${HOME}"/.java/current + ln -s "${JAVA_HOME_11}"/* /home/tooling/.java/current echo "Java environment set to ${JAVA_HOME_11}" fi @@ -83,41 +76,73 @@ if [[ "${KUBEDOCK_ENABLED:-false}" == "true" ]]; then echo "Kubedock is enabled (env variable KUBEDOCK_ENABLED is set to true)." SECONDS=0 - until [ -f /home/user/.kube/config ]; do - if (( SECONDS > 10 )); then - echo "Giving up..." - exit 1 + KUBEDOCK_TIMEOUT=${KUBEDOCK_TIMEOUT:-10} + until [ -f $KUBECONFIG ]; do + if (( SECONDS > KUBEDOCK_TIMEOUT )); then + break fi echo "Kubeconfig doesn't exist yet. Waiting..." sleep 1 done - echo "Kubeconfig found." - KUBEDOCK_PARAMS=${KUBEDOCK_PARAMS:-"--reverse-proxy"} + if [ -f $KUBECONFIG ]; then + echo "Kubeconfig found." - echo "Starting kubedock with params \"${KUBEDOCK_PARAMS}\"..." - - kubedock server "${KUBEDOCK_PARAMS}" > /tmp/kubedock.log 2>&1 & - - echo "Done." + KUBEDOCK_PARAMS=${KUBEDOCK_PARAMS:-"--reverse-proxy --kubeconfig $KUBECONFIG"} - echo "Replacing podman with podman-wrapper.sh..." + echo "Starting kubedock with params \"${KUBEDOCK_PARAMS}\"..." - mkdir -p /home/user/.local/bin/ - ln -f -s /usr/bin/podman-wrapper.sh /home/user/.local/bin/podman + kubedock server ${KUBEDOCK_PARAMS} > /tmp/kubedock.log 2>&1 & - export TESTCONTAINERS_RYUK_DISABLED="true" - export TESTCONTAINERS_CHECKS_DISABLE="true" + echo "Done." - echo "Done." - echo + echo "Replacing podman with podman-wrapper.sh..." + + ln -f -s /usr/bin/podman-wrapper.sh /home/tooling/.local/bin/podman + + export TESTCONTAINERS_RYUK_DISABLED="true" + export TESTCONTAINERS_CHECKS_DISABLE="true" + + echo "Done." + echo + else + echo "Could not find Kubeconfig at $KUBECONFIG" + echo "Giving up..." + fi else echo echo "Kubedock is disabled. It can be enabled with the env variable \"KUBEDOCK_ENABLED=true\"" echo "set in the workspace Devfile or in a Kubernetes ConfigMap in the developer namespace." echo - mkdir -p /home/user/.local/bin/ - ln -f -s /usr/bin/podman.orig /home/user/.local/bin/podman + ln -f -s /usr/bin/podman.orig /home/tooling/.local/bin/podman +fi + +############################################################################# +# Stow: If persistUserHome is enabled, then the contents of /home/user/ +# will be mounted by a PVC and overwritten. In this case, we use stow to +# create symbolic links from /home/tooling/ -> /home/user/. +# Required for https://github.com/eclipse/che/issues/22412 +############################################################################# + +# /home/user/ will be mounted to by a PVC if persistUserHome is enabled +# We need to override the `set -e` from this script by ensuring the mountpoint command returns 0, +# but we also need to capture the exit code of mountpoint +HOME_USER_MOUNTED=0 +mountpoint -q /home/user/ || HOME_USER_MOUNTED=$? + +# This file will be created after stowing, to guard from executing stow everytime the container is started +STOW_COMPLETE=/home/user/.stow_completed + +if [ $HOME_USER_MOUNTED -eq 0 ] && [ ! -f $STOW_COMPLETE ]; then + # Create symbolic links from /home/tooling/ -> /home/user/ + stow . -t /home/user/ -d /home/tooling/ --no-folding -v 2 > /tmp/stow.log 2>&1 + # Vim does not permit .viminfo to be a symbolic link for security reasons, so manually copy it + cp --no-clobber /home/tooling/.viminfo /home/user/.viminfo + # We have to restore bash-related files back onto /home/user/ (since they will have been overwritten by the PVC) + # but we don't want them to be symbolic links (so that they persist on the PVC) + cp --no-clobber /home/tooling/.bashrc /home/user/.bashrc + cp --no-clobber /home/tooling/.bash_profile /home/user/.bash_profile + touch $STOW_COMPLETE fi exec "$@"