Skip to content
Draft
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
14 changes: 12 additions & 2 deletions src/common-utils/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -422,16 +422,26 @@ elif [ "${USERNAME}" = "none" ]; then
USER_GID=0
fi
# Create or update a non-root user to match UID/GID.
group_name="${USERNAME}"
group_name="$(id -gn "$USERNAME" 2>/dev/null || echo "$USERNAME")"
if id -u ${USERNAME} > /dev/null 2>&1; then
# User exists, update if needed
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
group_name="$(id -gn $USERNAME)"
groupmod --gid $USER_GID ${group_name}
usermod --gid $USER_GID $USERNAME
fi
# Check if the target UID is different from current user's UID before modifying
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
usermod --uid $USER_UID $USERNAME
# Additional safety check: ensure target UID isn't already taken by another user
# This prevents "UID already exists" errors when multiple users have the same UID
if id -u $USER_UID > /dev/null 2>&1; then
existing_user=$(id -nu $USER_UID)
if [ "$existing_user" != "$USERNAME" ]; then
echo "Warning: UID $USER_UID is already in use by user '$existing_user'. Skipping UID modification."
fi
else
usermod --uid $USER_UID $USERNAME
fi
fi
else
# Create user
Expand Down
57 changes: 57 additions & 0 deletions test/common-utils/devcontainer-custom-user.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Check current user
current_user=$(whoami)
echo "Current user: $current_user"

# Check user's primary group ID
user_gid=$(id -g)
echo "User's primary GID: $user_gid"

# Check user's primary group name
user_group_name=$(id -gn)
echo "User's primary group name: $user_group_name"

# Check if user exists and get their info
if id -u vscode > /dev/null 2>&1; then
echo "vscode user exists"
vscode_uid=$(id -u vscode)
vscode_gid=$(id -g vscode)
vscode_group_name=$(id -gn vscode)

echo "vscode UID: $vscode_uid"
echo "vscode GID: $vscode_gid"
echo "vscode group name: $vscode_group_name"
else
echo "vscode user does not exist"
fi

# Check what group has GID 100
if getent group 100 >/dev/null 2>&1; then
group_100_info=$(getent group 100)
echo "GID 100 belongs to: $group_100_info"
else
echo "No group found with GID 100"
fi

# Check all groups the user belongs to
echo "All groups for $current_user: $(groups)"

# Definition specific tests based on the scenario
check "user is vscode" grep "vscode" <(whoami)
check "vscode user exists" id -u vscode
check "vscode primary group exists" id -g vscode

# If the test is specifically for GID 100, check that
if [ "$(id -g vscode)" = "100" ]; then
check "vscode has GID 100" [ "$(id -g vscode)" = "100" ]
check "GID 100 group name" getent group 100
fi

# Report result
reportResults
13 changes: 13 additions & 0 deletions test/common-utils/devcontainer-custom-user/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM ubuntu:noble
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=100
RUN if ! getent group users > /dev/null 2>&1; then groupadd --gid $USER_GID users; fi \
&& if ! id -u $USERNAME > /dev/null 2>&1; then \
if ! id -u $USER_UID > /dev/null 2>&1; then \
useradd --uid $USER_UID --gid $USER_GID -m $USERNAME; \
else \
echo "UID $USER_UID already exists, creating user without specifying UID"; \
useradd --gid $USER_GID -m $USERNAME; \
fi; \
fi
13 changes: 13 additions & 0 deletions test/common-utils/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -284,5 +284,18 @@
"features": {
"common-utils": {}
}
},
"devcontainer-custom-user": {
"build": {
"dockerfile": "Dockerfile"
},
"remoteUser": "vscode",
"features": {
"common-utils": {
"username": "vscode",
"userUid": "1000",
"userGid": "100" // Test GID 100 conflict resolution (users group)
}
}
}
}