Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions base/ubi9/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,15 @@ RUN KUBEDOCK_ARCH="linux_amd64" && \
COPY --chown=0:0 kubedock_setup.sh /usr/local/bin/kubedock_setup

# Configure Podman wrapper
ENV PODMAN_WRAPPER_PATH=/usr/bin/podman.wrapper
ENV ORIGINAL_PODMAN_PATH=/usr/bin/podman.orig
COPY --chown=0:0 kubedock_setup.sh /usr/local/bin/kubedock_setup
ENV PODMAN_WRAPPER_PATH=/usr/bin/podman.wrapper \
ORIGINAL_PODMAN_PATH=/usr/bin/podman.orig
COPY --chown=0:0 podman-wrapper.sh "${PODMAN_WRAPPER_PATH}"
COPY --chown=0:0 podman-compose-down-wrapper.sh "/usr/bin/podman-compose-down-wrapper.sh"
COPY --chown=0:0 podman-interactive-wrapper.sh "/usr/bin/podman-interactive-wrapper.sh"
COPY --chown=0:0 podman-cp-wrapper.sh "/usr/bin/podman-cp-wrapper.sh"
RUN mv /usr/bin/podman "${ORIGINAL_PODMAN_PATH}"
COPY --chown=0:0 docker.sh "/usr/bin/docker"

COPY --chown=0:0 entrypoint.sh /
COPY --chown=0:0 .stow-local-ignore /home/tooling/
Expand Down
9 changes: 9 additions & 0 deletions base/ubi9/docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/sh

[ -e /etc/containers/nodocker ] || \
echo "Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg." >&2
if [ "${KUBEDOCK_ENABLED:-false}" = "true" ]; then
exec /usr/bin/podman.wrapper "$@"
else
exec /usr/bin/podman "$@"
fi
Empty file modified base/ubi9/entrypoint.sh
100644 → 100755
Empty file.
13 changes: 12 additions & 1 deletion base/ubi9/kubedock_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,18 @@ if [ "${KUBEDOCK_ENABLED:-false}" = "true" ]; then
if [ -f $KUBECONFIG ]; then
echo "Kubeconfig found."

KUBEDOCK_PARAMS=${KUBEDOCK_PARAMS:-"--reverse-proxy --kubeconfig $KUBECONFIG"}
echo "Fix Kubeconfig permission."
chmod 600 $KUBECONFIG

if [ -z "$KUBEDOCK_PARAMS" ]; then
KUBEDOCK_PARAMS="--reverse-proxy --kubeconfig $KUBECONFIG"
if [ -n "$REQUEST_CPU" ] && [ -n "$REQUEST_MEMORY" ]; then
KUBEDOCK_PARAMS="$KUBEDOCK_PARAMS --request-cpu=$REQUEST_CPU --request-memory=$REQUEST_MEMORY"
fi
if [ -n "$REAPER_KEEPMAX" ]; then
KUBEDOCK_PARAMS="$KUBEDOCK_PARAMS --reapmax=$REAPER_KEEPMAX"
fi
fi

echo "Starting kubedock with params \"${KUBEDOCK_PARAMS}\"..."

Expand Down
105 changes: 105 additions & 0 deletions base/ubi9/podman-compose-down-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/bash
set -euo pipefail

# This script is a wrapper for 'podman compose down' or 'docker compose down'
# It removes the containers/services defined in the docker-compose file using 'podman rm'
# This is needed when running with kubedock, as 'compose down' cannot shut down pods directly

usage() {
echo "Usage: $0 [OPTIONS] [SERVICES]"
echo " OPTIONS: Options for docker-compose down (e.g., -f docker-compose.yml)"
echo " SERVICES: Optional list of services to remove"
exit 1
}

# Parse options and service names
COMPOSE_FILE="docker-compose.yml"
OPTIONS=()
SERVICES=()
while [[ $# -gt 0 ]]; do
case "$1" in
-f|--file)
if [[ -n "${2:-}" ]]; then
COMPOSE_FILE="$2"
OPTIONS+=("$1" "$2")
shift 2
else
echo "Error: Missing argument for $1"
usage
fi
;;
--file=*)
COMPOSE_FILE="${1#*=}"
OPTIONS+=("$1")
shift
;;
-h|--help)
usage
;;
-*)
OPTIONS+=("$1")
shift
;;
*)
SERVICES+=("$1")
shift
;;
esac
done

# If no -f/--file was provided, support both docker-compose.yml and docker-compose.yaml
if [[ "${COMPOSE_FILE}" == "docker-compose.yml" ]]; then
if [[ -f "docker-compose.yml" ]]; then
COMPOSE_FILE="docker-compose.yml"
elif [[ -f "docker-compose.yaml" ]]; then
COMPOSE_FILE="docker-compose.yaml"
else
echo "Error: No docker-compose.yml or docker-compose.yaml found in the current directory."
exit 1
fi
fi

if [[ ! -f "$COMPOSE_FILE" ]]; then
echo "Error: Compose file '$COMPOSE_FILE' not found."
exit 1
fi

# Get service names from compose file if none specified
if [[ ${#SERVICES[@]} -eq 0 ]]; then
# Try to use yq if available, else fallback to grep/sed/awk
if command -v yq >/dev/null 2>&1; then
mapfile -t SERVICES < <(yq '.services | keys | .[]' "$COMPOSE_FILE")
else
# Fallback: extract service names by finding top-level keys under 'services:'
mapfile -t SERVICES < <(awk '/services:/ {flag=1; next} /^[^[:space:]]/ {flag=0} flag && /^[[:space:]]+[a-zA-Z0-9_-]+:/ {gsub(":",""); print $1}' "$COMPOSE_FILE" | sed 's/^[[:space:]]*//')
fi
fi

if [[ ${#SERVICES[@]} -eq 0 ]]; then
echo "No services found in compose file '$COMPOSE_FILE'."
exit 0
fi

# Compose container name: <current-dir>-<service-name>-1
PROJECT_NAME="$(basename "$PWD")"

echo "Removing services: ${SERVICES[*]}"
for svc in "${SERVICES[@]}"; do
# Try to get container_name from compose file
CONTAINER_NAME=""
if command -v yq >/dev/null 2>&1; then
CONTAINER_NAME=$(yq ".services.${svc}.container_name // \"\"" "$COMPOSE_FILE" | tr -d '"')
fi
if [[ -z "$CONTAINER_NAME" ]]; then
CONTAINER_NAME="${PROJECT_NAME}-${svc}-1"
fi
# Check if the container exists
if ! podman ps -a --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
echo "No container found for service '$svc' (expected name: $CONTAINER_NAME)"
continue
fi
echo "Removing container: $CONTAINER_NAME"
podman rm -f "$CONTAINER_NAME"
done

echo "All specified services have been removed."
46 changes: 46 additions & 0 deletions base/ubi9/podman-cp-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
set -euo pipefail

# This script replaces 'podman cp' with 'oc cp', mapping the container to the correct pod via the kubedock label.

# Parse options (stop at first non-option argument)
OPTIONS=()
while [[ $# -gt 0 ]]; do
case "$1" in
-*) OPTIONS+=("$1"); shift ;;
*) break ;;
esac
done

# Now $1 and $2 are [CONTAINER:]SRC_PATH [CONTAINER:]DEST_PATH
if [[ $# -lt 2 || -z "${1:-}" || -z "${2:-}" ]]; then
echo "Error: Both [CONTAINER:]SRC_PATH and [CONTAINER:]DEST_PATH must be specified." >&2
exit 1
fi

SRC="$1"
DEST="$2"

get_pod_for_container() {
local container_ref="$1"
if [[ "$container_ref" == *:* ]]; then
local container_id="${container_ref%%:*}"
# Find pod with label kubedock.containerid=<container_id>
local pod_name
pod_name=$(oc get pods -l "kubedock.containerid=${container_id}" -o jsonpath='{.items[0].metadata.name}')
if [[ -z "$pod_name" ]]; then
echo "Error: No pod found for container id: $container_id" >&2
exit 1
fi
# Return pod:rest_of_path
echo "${pod_name}:${container_ref#*:}"
else
# No container ref, just return as is
echo "$container_ref"
fi
}

OC_SRC=$(get_pod_for_container "$SRC")
OC_DEST=$(get_pod_for_container "$DEST")

exec oc cp "${OPTIONS[@]}" "$OC_SRC" "$OC_DEST"
136 changes: 136 additions & 0 deletions base/ubi9/podman-interactive-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/bin/bash
set -euo pipefail

# This script transparently replaces problematic 'podman run -it ...' invocations
# with a workaround for kubedock compatibility:
# podman exec -it $(podman run -d --rm [OPTIONS] IMAGE tail -f /dev/null) [COMMAND]

usage() {
echo "Usage: $0 run [OPTIONS] IMAGE [COMMAND] [ARG...]"
exit 1
}

ARGS=( "$@" )
if [[ "${ARGS[0]:-}" != "run" ]]; then
usage
fi

RUN_OPTS=()
IMAGE=""
CMD_ARGS=()

skip_next=0
found_image=0
for ((i=1; i<${#ARGS[@]}; i++)); do
arg="${ARGS[$i]}"
if [[ $skip_next -eq 1 ]]; then
# Only skip for --tty/--interactive with space value
RUN_OPTS+=("$arg")
skip_next=0
continue
fi
if [[ $found_image -eq 0 ]]; then
# Remove all forms of interactive/tty options for internal run
case "$arg" in
-i|-t|-it|-ti)
continue
;;
--tty|--interactive)
# skip this and the next arg if it does not start with '-'
if [[ $((i+1)) -lt ${#ARGS[@]} && "${ARGS[$((i+1))]}" != "-"* ]]; then
skip_next=1
fi
continue
;;
--tty=*|--interactive=*)
continue
;;
# Options that take a value
-u=*|--user=*)
# Handle -u=root and --user=root
RUN_OPTS+=("--user=$(id -u)")
continue
;;
-u|--user)
# Handle -u root and --user root
RUN_OPTS+=("--user=$(id -u)")
((i++)) # Skip the next argument (the value)
continue
;;
-v|--volume|-e|--env|-w|--workdir|--name|--hostname|--entrypoint|--add-host|--device|--label|--network|--cap-add|--cap-drop|--security-opt|--tmpfs|--ulimit|--mount|--publish|--expose|--dns|--dns-search|--dns-option|--mac-address|--memory|--memory-swap|--cpu-shares|--cpus|--cpu-period|--cpu-quota|--cpu-rt-runtime|--cpu-rt-period|--cpuset-cpus|--cpuset-mems|--blkio-weight|--blkio-weight-device|--device-read-bps|--device-write-bps|--device-read-iops|--device-write-iops|--shm-size|--sysctl|--log-driver|--log-opt|--restart|--stop-signal|--stop-timeout|--health-cmd|--health-interval|--health-retries|--health-timeout|--health-start-period|--userns|--cgroup-parent|--pid|--ipc|--uts|--runtime|--storage-opt|--volume-driver|--volumes-from|--env-file|--group-add|--init|--isolation|--kernel-memory|--memory-reservation|--memory-swappiness|--oom-kill-disable|--oom-score-adj|--pids-limit|--privileged|--publish-all|--read-only|--sig-proxy
RUN_OPTS+=("$arg")
skip_next=1
continue
;;
--*=*)
# long option with value, e.g. --workdir=/foo
# filter out --tty= and --interactive=
if [[ "$arg" == --tty=* || "$arg" == --interactive=* ]]; then
continue
fi
if [[ "$arg" == --user=* ]]; then
RUN_OPTS+=("--user=$(id -u)")
continue
fi
RUN_OPTS+=("$arg")
continue
;;
--)
found_image=1
continue
;;
-*)
# Handle combined short options, e.g. -itv, -tiv, etc.
# Remove i and t, keep the rest
if [[ "$arg" =~ ^-([it]+)$ ]]; then
# skip if only i/t/it/ti
continue
elif [[ "$arg" =~ ^-([it]+)(.+)$ ]]; then
rest="${BASH_REMATCH[2]}"
if [[ -n "$rest" ]]; then
RUN_OPTS+=("-$rest")
fi
continue
else
RUN_OPTS+=("$arg")
continue
fi
;;
*)
IMAGE="$arg"
found_image=1
continue
;;
esac
else
CMD_ARGS+=("$arg")
fi
done
# Remove duplicate --rm if present
has_rm=0
for opt in "${RUN_OPTS[@]}"; do
if [[ "$opt" == "--rm" ]]; then
has_rm=1
break
fi
done


FINAL_RUN_OPTS=("${RUN_OPTS[@]}")
if [[ $has_rm -eq 0 ]]; then
FINAL_RUN_OPTS+=("--rm")
fi

if [[ -z "$IMAGE" ]]; then
echo "Error: Could not determine image name in podman run command."
usage
fi


CONTAINER_ID=$(podman run -d "${FINAL_RUN_OPTS[@]}" "$IMAGE" tail -f /dev/null)

if [[ ${#CMD_ARGS[@]} -eq 0 ]]; then
CMD_ARGS=(bash)
fi

exec podman exec -it "$CONTAINER_ID" "${CMD_ARGS[@]}"
27 changes: 27 additions & 0 deletions base/ubi9/podman-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ KUBEDOCK_SUPPORTED_COMMANDS=${KUBEDOCK_SUPPORTED_COMMANDS:-"run ps exec cp logs

PODMAN_ARGS=( "$@" )

# Check for 'compose down' command and delegate to the special wrapper
if [[ "${PODMAN_ARGS[0]:-}" == "compose" && "${PODMAN_ARGS[1]:-}" == "down" ]]; then
# Forward all args after 'compose down' to the wrapper
exec "/usr/bin/podman-compose-down-wrapper.sh" "${PODMAN_ARGS[@]:2}"
fi

# Intercept 'podman run' with interactive/tty flags and delegate to the interactive wrapper
if [[ "${PODMAN_ARGS[0]:-}" == "run" ]]; then
has_interactive=0
has_tty=0
for arg in "${PODMAN_ARGS[@]}"; do
case "$arg" in
-i|--interactive) has_interactive=1 ;;
-t|--tty) has_tty=1 ;;
-it|-ti) has_interactive=1; has_tty=1 ;;
esac
done
if [[ $has_interactive -eq 1 && $has_tty -eq 1 ]]; then
exec "/usr/bin/podman-interactive-wrapper.sh" "${PODMAN_ARGS[@]}"
fi
fi

# Intercept 'podman cp' and delegate to the cp wrapper
if [[ "${PODMAN_ARGS[0]:-}" == "cp" ]]; then
exec "/usr/bin/podman-cp-wrapper.sh" "${PODMAN_ARGS[@]:1}"
fi

TRUE=0
FALSE=1

Expand Down
Loading