mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 04:30:13 -08:00
Add Docker test scripts for setup validation
- Created run-docker-tests.sh to execute setup tests in isolated Docker containers (Ubuntu and Debian). - Implemented logging functionality to track test results and errors. - Added startup.sh to ensure proper permissions and run tests within Docker containers. - Developed test-setup.sh to validate bootstrap.sh and setup.sh scripts, including package availability checks. - Enhanced error handling and reporting for package installations and missing dependencies. - Included detailed logging for system information and test results.
This commit is contained in:
80
shell-setup/Dockerfile
Normal file
80
shell-setup/Dockerfile
Normal file
@@ -0,0 +1,80 @@
|
||||
# Dockerfile to test bootstrap.sh and setup.sh scripts in different environments
|
||||
# This allows testing the setup process in isolated containers
|
||||
|
||||
# Ubuntu test environment
|
||||
FROM ubuntu:24.04 as ubuntu-test
|
||||
LABEL description="Ubuntu test environment for shell setup scripts"
|
||||
|
||||
# Install minimal dependencies needed to run the test
|
||||
ENV TZ=America/New_York
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y curl git sudo wget
|
||||
|
||||
# Pre-install cowsay and lolcat packages for testing
|
||||
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y cowsay lolcat
|
||||
|
||||
# Create logs directory with proper permissions
|
||||
RUN mkdir -p /logs && chmod -R 777 /logs
|
||||
|
||||
# Create a test user with sudo permissions
|
||||
RUN useradd -ms /bin/bash testuser && \
|
||||
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||
|
||||
USER testuser
|
||||
WORKDIR /home/testuser
|
||||
|
||||
# Create directory structure for shell setup
|
||||
RUN mkdir -p /home/testuser/shell/setup
|
||||
|
||||
# Copy test script, startup script, and packages.list
|
||||
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||
COPY --chown=testuser:testuser startup.sh /home/testuser/
|
||||
COPY --chown=testuser:testuser setup/packages.list /home/testuser/shell/setup/
|
||||
|
||||
# Make scripts executable
|
||||
RUN chmod +x /home/testuser/test-setup.sh
|
||||
RUN chmod +x /home/testuser/startup.sh
|
||||
|
||||
CMD ["/bin/bash", "-c", "./startup.sh"]
|
||||
|
||||
# Debian test environment
|
||||
FROM debian:12 as debian-test
|
||||
LABEL description="Debian test environment for shell setup scripts"
|
||||
|
||||
# Install minimal dependencies needed to run the test
|
||||
ENV TZ=America/New_York
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y curl git sudo wget
|
||||
|
||||
# Pre-install cowsay and lolcat packages for testing
|
||||
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y cowsay lolcat
|
||||
|
||||
# Create logs directory with proper permissions
|
||||
RUN mkdir -p /logs && chmod -R 777 /logs
|
||||
|
||||
# Create a test user with sudo permissions
|
||||
RUN useradd -ms /bin/bash testuser && \
|
||||
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||
|
||||
USER testuser
|
||||
WORKDIR /home/testuser
|
||||
|
||||
# Create directory structure for shell setup
|
||||
RUN mkdir -p /home/testuser/shell/setup
|
||||
|
||||
# Copy test script, startup script, and packages.list
|
||||
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||
COPY --chown=testuser:testuser startup.sh /home/testuser/
|
||||
COPY --chown=testuser:testuser setup/packages.list /home/testuser/shell/setup/
|
||||
|
||||
# Make scripts executable
|
||||
RUN chmod +x /home/testuser/test-setup.sh
|
||||
RUN chmod +x /home/testuser/startup.sh
|
||||
|
||||
CMD ["/bin/bash", "-c", "./startup.sh"]
|
||||
40
shell-setup/bootstrap.sh
Executable file
40
shell-setup/bootstrap.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
DOTFILES_REPO="acedanger/shell"
|
||||
DOTFILES_BRANCH="main"
|
||||
DOTFILES_DIR="$HOME/shell"
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${GREEN}Setting up your system...${NC}"
|
||||
|
||||
# Install git if not present
|
||||
if ! command -v git &>/dev/null; then
|
||||
echo -e "${YELLOW}Installing git...${NC}"
|
||||
sudo apt update && sudo apt install -y git
|
||||
fi
|
||||
|
||||
# Create shell directory if it doesn't exist
|
||||
mkdir -p "$HOME/shell"
|
||||
|
||||
# Clone or update repository
|
||||
if [ -d "$DOTFILES_DIR" ]; then
|
||||
echo -e "${YELLOW}Updating existing shell repository...${NC}"
|
||||
cd "$DOTFILES_DIR"
|
||||
git pull origin $DOTFILES_BRANCH
|
||||
else
|
||||
echo -e "${YELLOW}Cloning shell repository...${NC}"
|
||||
git clone "https://github.com/$DOTFILES_REPO.git" "$DOTFILES_DIR"
|
||||
cd "$DOTFILES_DIR"
|
||||
fi
|
||||
|
||||
# Make scripts executable
|
||||
chmod +x "$DOTFILES_DIR/setup/setup.sh"
|
||||
|
||||
# Run setup script
|
||||
"$DOTFILES_DIR/setup/setup.sh"
|
||||
|
||||
echo -e "${GREEN}Bootstrap completed! Please restart your terminal for changes to take effect.${NC}"
|
||||
225
shell-setup/debian-patches.sh
Executable file
225
shell-setup/debian-patches.sh
Executable file
@@ -0,0 +1,225 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script applies Debian-specific patches to the setup scripts
|
||||
# It should be run before bootstrap.sh on Debian systems
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if running on Debian
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
if [[ "$ID" == "debian" ]]; then
|
||||
echo -e "${BLUE}Running on Debian $VERSION_ID ($PRETTY_NAME)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}This script is intended for Debian systems but detected $PRETTY_NAME${NC}"
|
||||
echo -e "${YELLOW}Continue anyway? [y/N]${NC}"
|
||||
read -r response
|
||||
if [[ ! "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||
echo -e "${RED}Exiting...${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create a packages mapping file
|
||||
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||
mkdir -p "$PATCH_DIR"
|
||||
|
||||
echo -e "${YELLOW}Creating Debian package name mappings...${NC}"
|
||||
cat > "$PATCH_DIR/debian-packages.map" << 'EOF'
|
||||
# Debian package name mappings
|
||||
# format: ubuntu-name|debian-name
|
||||
|
||||
# bat is called batcat on Debian
|
||||
bat|batcat
|
||||
|
||||
# Keep original names for packages that are the same
|
||||
git|git
|
||||
python3|python3
|
||||
wget|wget
|
||||
curl|curl
|
||||
cowsay|cowsay
|
||||
lolcat|lolcat
|
||||
fzf|fzf
|
||||
zsh|zsh
|
||||
|
||||
# Different package names for Nala source
|
||||
software-properties-common|software-properties-common
|
||||
EOF
|
||||
|
||||
# Create a patching script that will be called by setup.sh
|
||||
echo -e "${YELLOW}Creating Debian patching script...${NC}"
|
||||
cat > "$PATCH_DIR/apply-debian-patches.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Script to apply Debian-specific patches to the setup process
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||
|
||||
# Check if running on Debian
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
if [[ "$ID" != "debian" ]]; then
|
||||
echo -e "${YELLOW}Not running on Debian, skipping patches${NC}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Applying Debian-specific patches...${NC}"
|
||||
|
||||
# Function to map package names from Ubuntu to Debian
|
||||
map_package() {
|
||||
local ubuntu_pkg="$1"
|
||||
local debian_pkg
|
||||
|
||||
# Look for the package in the mapping file
|
||||
if [ -f "$PATCH_DIR/debian-packages.map" ]; then
|
||||
debian_pkg=$(grep -v "^#" "$PATCH_DIR/debian-packages.map" | grep "^$ubuntu_pkg|" | cut -d'|' -f2)
|
||||
fi
|
||||
|
||||
# If not found or empty, use the original name
|
||||
if [ -z "$debian_pkg" ]; then
|
||||
debian_pkg="$ubuntu_pkg"
|
||||
fi
|
||||
|
||||
echo "$debian_pkg"
|
||||
}
|
||||
|
||||
# Patch the packages.list file if it exists
|
||||
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||
echo -e "${YELLOW}Patching packages.list for Debian compatibility...${NC}"
|
||||
|
||||
# Create a temporary patched file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Process each line
|
||||
while IFS= read -r line; do
|
||||
# Skip comments and empty lines
|
||||
if [[ "$line" =~ ^//.*$ ]] || [[ -z "$line" ]]; then
|
||||
echo "$line" >> "$temp_file"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Map the package name
|
||||
debian_pkg=$(map_package "$line")
|
||||
echo "$debian_pkg" >> "$temp_file"
|
||||
|
||||
done < "$HOME/shell/setup/packages.list"
|
||||
|
||||
# Backup original and replace with patched version
|
||||
cp "$HOME/shell/setup/packages.list" "$HOME/shell/setup/packages.list.orig"
|
||||
mv "$temp_file" "$HOME/shell/setup/packages.list"
|
||||
|
||||
echo -e "${GREEN}Patched packages.list for Debian compatibility${NC}"
|
||||
fi
|
||||
|
||||
# Other Debian-specific patches can be added here...
|
||||
|
||||
# Add contrib and non-free repositories if they're not already enabled
|
||||
echo -e "${YELLOW}Checking Debian repositories...${NC}"
|
||||
if ! grep -q "contrib" /etc/apt/sources.list; then
|
||||
echo -e "${YELLOW}Adding contrib and non-free repositories...${NC}"
|
||||
# Create a backup of the original sources.list
|
||||
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
|
||||
|
||||
# Add contrib and non-free to each deb line
|
||||
sudo sed -i 's/main$/main contrib non-free non-free-firmware/g' /etc/apt/sources.list
|
||||
|
||||
echo -e "${GREEN}Added contrib and non-free repositories${NC}"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Debian patches applied successfully${NC}"
|
||||
EOF
|
||||
|
||||
chmod +x "$PATCH_DIR/apply-debian-patches.sh"
|
||||
|
||||
# Create a wrapper script for bootstrap.sh
|
||||
echo -e "${YELLOW}Creating Debian bootstrap wrapper...${NC}"
|
||||
cat > "$HOME/debian-bootstrap.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Debian wrapper for bootstrap.sh
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||
|
||||
# Apply Debian patches first
|
||||
if [ -x "$PATCH_DIR/apply-debian-patches.sh" ]; then
|
||||
echo -e "${BLUE}Applying Debian patches before bootstrap...${NC}"
|
||||
"$PATCH_DIR/apply-debian-patches.sh"
|
||||
fi
|
||||
|
||||
# Download and run the bootstrap script
|
||||
echo -e "${BLUE}Running bootstrap script...${NC}"
|
||||
curl -s https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh | bash
|
||||
|
||||
# Apply patches again after bootstrap (in case packages.list was just downloaded)
|
||||
if [ -x "$PATCH_DIR/apply-debian-patches.sh" ]; then
|
||||
echo -e "${BLUE}Applying Debian patches after bootstrap...${NC}"
|
||||
"$PATCH_DIR/apply-debian-patches.sh"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Debian bootstrap completed!${NC}"
|
||||
EOF
|
||||
|
||||
chmod +x "$HOME/debian-bootstrap.sh"
|
||||
|
||||
# Add a hook to setup.sh to call the Debian patch script
|
||||
echo -e "${YELLOW}Creating setup.sh hook for Debian...${NC}"
|
||||
cat > "$PATCH_DIR/setup-hook.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Hook to modify setup.sh to call Debian patches
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
if [[ "$ID" == "debian" ]]; then
|
||||
# Modify setup.sh to call Debian patches
|
||||
if [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||
# Check if the patch hasn't been applied yet
|
||||
if ! grep -q "apply-debian-patches" "$HOME/shell/setup/setup.sh"; then
|
||||
# Add call to Debian patch script right after the shebang
|
||||
sed -i '2i\
|
||||
# Apply Debian patches if available\
|
||||
if [ -x "$HOME/.shell-debian-patches/apply-debian-patches.sh" ]; then\
|
||||
echo -e "${YELLOW}Applying Debian-specific patches...${NC}"\
|
||||
"$HOME/.shell-debian-patches/apply-debian-patches.sh"\
|
||||
fi' "$HOME/shell/setup/setup.sh"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x "$PATCH_DIR/setup-hook.sh"
|
||||
|
||||
echo -e "${GREEN}Debian compatibility patch has been set up!${NC}"
|
||||
echo -e "${YELLOW}To bootstrap your Debian system, run:${NC}"
|
||||
echo -e " ${BLUE}bash ~/debian-bootstrap.sh${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}This has created:${NC}"
|
||||
echo -e "1. Package name mappings for Debian"
|
||||
echo -e "2. A patch script for Debian-specific adjustments"
|
||||
echo -e "3. A Debian-specific bootstrap wrapper"
|
||||
237
shell-setup/run-docker-tests.sh
Executable file
237
shell-setup/run-docker-tests.sh
Executable file
@@ -0,0 +1,237 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to run setup tests in Docker containers
|
||||
# This allows testing the setup process in isolated environments
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if Docker is installed and working
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Error: Docker is not installed. Please install Docker to run tests.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create logs directory at the top level to ensure it exists
|
||||
LOGS_DIR="$(pwd)/logs"
|
||||
if [ ! -d "$LOGS_DIR" ]; then
|
||||
echo -e "${YELLOW}Creating logs directory at: $LOGS_DIR${NC}"
|
||||
mkdir -p "$LOGS_DIR" || {
|
||||
echo -e "${RED}Failed to create logs directory! Check permissions.${NC}"
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
echo -e "${GREEN}Logs directory already exists at: $LOGS_DIR${NC}"
|
||||
fi
|
||||
|
||||
# Ensure the logs directory is writable
|
||||
if [ ! -w "$LOGS_DIR" ]; then
|
||||
echo -e "${YELLOW}Setting permissions on logs directory...${NC}"
|
||||
chmod -R 777 "$LOGS_DIR" || {
|
||||
echo -e "${RED}Failed to set write permissions on logs directory!${NC}"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Create a test file to verify we can write to it
|
||||
if touch "$LOGS_DIR/test_file" && rm "$LOGS_DIR/test_file"; then
|
||||
echo -e "${GREEN}Log directory is writable and ready for use${NC}"
|
||||
else
|
||||
echo -e "${RED}Cannot write to logs directory even after setting permissions!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Docker is running
|
||||
if ! docker info &>/dev/null; then
|
||||
echo -e "${YELLOW}Warning: Docker appears to be installed but not running or not properly configured.${NC}"
|
||||
echo -e "${YELLOW}If using WSL2, ensure Docker Desktop is running with WSL integration enabled.${NC}"
|
||||
echo -e "${YELLOW}Would you like to run the local test instead? [Y/n]${NC}"
|
||||
read -r response
|
||||
if [[ "$response" =~ ^([nN][oO]|[nN])$ ]]; then
|
||||
echo -e "${RED}Exiting...${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "${BLUE}Running local test instead...${NC}"
|
||||
./test-setup.sh
|
||||
exit $?
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build and run Ubuntu test container
|
||||
run_ubuntu_test() {
|
||||
echo -e "\n${BLUE}=== Running test in Ubuntu container ===${NC}"
|
||||
# Create the logs directory if it doesn't exist
|
||||
local log_dir="$(pwd)/logs"
|
||||
mkdir -p "$log_dir" || true
|
||||
|
||||
# Use sudo for chmod only if necessary
|
||||
if [ ! -w "$log_dir" ]; then
|
||||
echo -e "${YELLOW}Attempting to fix permissions with sudo...${NC}"
|
||||
sudo chmod -R 777 "$log_dir" 2>/dev/null || {
|
||||
echo -e "${YELLOW}Could not change permissions with sudo, continuing anyway...${NC}"
|
||||
}
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Logs will be saved to: $log_dir${NC}"
|
||||
echo -e "${YELLOW}Building Ubuntu test container...${NC}"
|
||||
docker build --target ubuntu-test -t shell-test:ubuntu .
|
||||
|
||||
echo -e "${GREEN}Running tests with package installation...${NC}"
|
||||
|
||||
# Create a timestamp for this test run
|
||||
TEST_TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
||||
echo -e "${YELLOW}Test run timestamp: $TEST_TIMESTAMP${NC}"
|
||||
|
||||
# Run container with proper volume mount and add environment variable for timestamp
|
||||
docker run --rm -it \
|
||||
-e TEST_TIMESTAMP="$TEST_TIMESTAMP" \
|
||||
-e CONTAINER_TYPE="ubuntu" \
|
||||
-v "$log_dir:/logs:z" \
|
||||
shell-test:ubuntu
|
||||
|
||||
# Check if logs were created
|
||||
if ls "$log_dir"/setup-test-*"$TEST_TIMESTAMP"* &>/dev/null 2>&1; then
|
||||
echo -e "${GREEN}Test logs successfully created in host directory${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Warning: No log files found matching timestamp $TEST_TIMESTAMP${NC}"
|
||||
echo -e "${YELLOW}This may indicate issues with volume mounting or permissions${NC}"
|
||||
echo -e "${YELLOW}Contents of log directory:${NC}"
|
||||
ls -la "$log_dir" || echo "Cannot list directory contents"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Test completed. Check logs in $log_dir directory${NC}"
|
||||
}
|
||||
|
||||
# Build and run Debian test container
|
||||
run_debian_test() {
|
||||
echo -e "\n${BLUE}=== Running test in Debian container ===${NC}"
|
||||
# Create the logs directory if it doesn't exist
|
||||
local log_dir="$(pwd)/logs"
|
||||
mkdir -p "$log_dir" || true
|
||||
|
||||
# Use sudo for chmod only if necessary
|
||||
if [ ! -w "$log_dir" ]; then
|
||||
echo -e "${YELLOW}Attempting to fix permissions with sudo...${NC}"
|
||||
sudo chmod -R 777 "$log_dir" 2>/dev/null || {
|
||||
echo -e "${YELLOW}Could not change permissions with sudo, continuing anyway...${NC}"
|
||||
}
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Logs will be saved to: $log_dir${NC}"
|
||||
echo -e "${YELLOW}Building Debian test container...${NC}"
|
||||
docker build --target debian-test -t shell-test:debian .
|
||||
|
||||
echo -e "${GREEN}Running tests with package installation...${NC}"
|
||||
|
||||
# Create a timestamp for this test run
|
||||
TEST_TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
||||
echo -e "${YELLOW}Test run timestamp: $TEST_TIMESTAMP${NC}"
|
||||
|
||||
# Run container with proper volume mount and add environment variable for timestamp
|
||||
docker run --rm -it \
|
||||
-e TEST_TIMESTAMP="$TEST_TIMESTAMP" \
|
||||
-e CONTAINER_TYPE="debian" \
|
||||
-v "$log_dir:/logs:z" \
|
||||
shell-test:debian
|
||||
|
||||
# Check if logs were created
|
||||
if ls "$log_dir"/setup-test-*"$TEST_TIMESTAMP"* &>/dev/null 2>&1; then
|
||||
echo -e "${GREEN}Test logs successfully created in host directory${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Warning: No log files found matching timestamp $TEST_TIMESTAMP${NC}"
|
||||
echo -e "${YELLOW}This may indicate issues with volume mounting or permissions${NC}"
|
||||
echo -e "${YELLOW}Contents of log directory:${NC}"
|
||||
ls -la "$log_dir" || echo "Cannot list directory contents"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Test completed. Check logs in $log_dir directory${NC}"
|
||||
}
|
||||
|
||||
# Full test with bootstrap script
|
||||
run_full_test() {
|
||||
local distro=$1
|
||||
local tag_name=$(echo $distro | sed 's/:/-/g') # Replace colon with hyphen for tag
|
||||
echo -e "\n${BLUE}=== Running full bootstrap test in $distro container ===${NC}"
|
||||
|
||||
# Create a Dockerfile for full test
|
||||
cat > Dockerfile.fulltest <<EOF
|
||||
FROM $distro
|
||||
LABEL description="$distro full test environment for bootstrap.sh script"
|
||||
|
||||
# Install minimal dependencies needed to run the bootstrap
|
||||
ENV TZ=America/New_York
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||
&& apt-get update && apt-get install -y curl git sudo wget
|
||||
|
||||
# Create a test user with sudo permissions
|
||||
RUN useradd -ms /bin/bash testuser && \\
|
||||
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||
|
||||
# Create directory structure for setup files
|
||||
RUN mkdir -p /home/testuser/shell
|
||||
|
||||
# Copy test script for post-bootstrap validation
|
||||
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||
|
||||
# Copy entire repo structure to ensure we have all needed files
|
||||
COPY --chown=testuser:testuser . /home/testuser/shell/
|
||||
|
||||
USER testuser
|
||||
WORKDIR /home/testuser
|
||||
|
||||
# Make the script executable
|
||||
RUN chmod +x /home/testuser/test-setup.sh
|
||||
|
||||
# Run tests before and after bootstrap to verify package installation
|
||||
CMD ["/bin/bash", "-c", "echo -e '\\n\\nRunning pre-bootstrap tests...' && ./test-setup.sh && echo -e '\\n\\nRunning bootstrap...' && /home/testuser/shell/bootstrap.sh && echo -e '\\n\\nRunning post-bootstrap tests...' && ./test-setup.sh"]
|
||||
EOF
|
||||
|
||||
# Build and run the container
|
||||
# Create the logs directory if it doesn't exist
|
||||
mkdir -p "$(pwd)/logs"
|
||||
docker build -f Dockerfile.fulltest -t shell-full-test:$tag_name .
|
||||
docker run --rm -it -v "$(pwd)/logs:/logs" shell-full-test:$tag_name
|
||||
|
||||
# Clean up
|
||||
rm Dockerfile.fulltest
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
case "$1" in
|
||||
ubuntu)
|
||||
run_ubuntu_test
|
||||
;;
|
||||
debian)
|
||||
run_debian_test
|
||||
;;
|
||||
full-ubuntu)
|
||||
run_full_test "ubuntu:24.04"
|
||||
;;
|
||||
full-debian)
|
||||
run_full_test "debian:12"
|
||||
;;
|
||||
all)
|
||||
run_ubuntu_test
|
||||
run_debian_test
|
||||
;;
|
||||
*)
|
||||
echo -e "${BLUE}Shell Setup Test Runner${NC}"
|
||||
echo -e "Usage: $0 [option]"
|
||||
echo -e "\nOptions:"
|
||||
echo " ubuntu Run test on Ubuntu container (tests packages and components)"
|
||||
echo " debian Run test on Debian container (tests packages and components)"
|
||||
echo " full-ubuntu Run full bootstrap test on Ubuntu container (performs complete installation)"
|
||||
echo " full-debian Run full bootstrap test on Debian container (performs complete installation)"
|
||||
echo " all Run tests on both Ubuntu and Debian containers (component tests only)"
|
||||
echo -e "\nExamples:"
|
||||
echo -e " $0 ubuntu # Quick test for package availability"
|
||||
echo -e " $0 full-debian # Test complete bootstrap installation"
|
||||
;;
|
||||
esac
|
||||
75
shell-setup/startup.sh
Executable file
75
shell-setup/startup.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Startup script for Docker containers to ensure permissions and run tests
|
||||
|
||||
# Define colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}=== Container Startup Checks ===${NC}"
|
||||
|
||||
# Display system information
|
||||
echo -e "${BLUE}System information:${NC}"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
echo -e "- OS: ${GREEN}$PRETTY_NAME${NC}"
|
||||
else
|
||||
echo -e "- OS: ${YELLOW}Unknown${NC}"
|
||||
fi
|
||||
|
||||
# Ensure packages.list is available
|
||||
echo -e "${BLUE}Checking for packages.list:${NC}"
|
||||
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||
echo -e "- packages.list: ${GREEN}Found${NC}"
|
||||
# Count packages in list (excluding comments and empty lines)
|
||||
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||
echo -e "- Package count: ${GREEN}$pkg_count packages${NC}"
|
||||
else
|
||||
echo -e "- packages.list: ${RED}Not found${NC}"
|
||||
echo "Error: Could not find packages.list file. Tests will fail."
|
||||
fi
|
||||
|
||||
# Ensure logs directory has correct permissions
|
||||
echo -e "${BLUE}Setting up logs directory:${NC}"
|
||||
if [ -d "/logs" ]; then
|
||||
echo -e "- Logs directory: ${GREEN}Found${NC}"
|
||||
|
||||
# Check ownership and permissions
|
||||
logs_owner=$(stat -c '%U:%G' /logs)
|
||||
echo -e "- Current ownership: $logs_owner"
|
||||
|
||||
echo "- Setting permissions on /logs directory..."
|
||||
sudo chown -R $(whoami):$(whoami) /logs 2>/dev/null || echo -e "${YELLOW}Failed to set ownership${NC}"
|
||||
sudo chmod -R 777 /logs 2>/dev/null || echo -e "${YELLOW}Failed to set permissions${NC}"
|
||||
|
||||
# Verify permissions are correct
|
||||
if [ -w "/logs" ]; then
|
||||
echo -e "- Write permission: ${GREEN}OK${NC}"
|
||||
|
||||
# Create a test file to really verify we can write
|
||||
if touch "/logs/test_file" 2>/dev/null; then
|
||||
echo -e "- Test write: ${GREEN}Succeeded${NC}"
|
||||
rm -f "/logs/test_file"
|
||||
else
|
||||
echo -e "- Test write: ${RED}Failed${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "- Write permission: ${RED}Failed${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "- Logs directory: ${YELLOW}Not found${NC}"
|
||||
echo "- Creating /logs directory..."
|
||||
if sudo mkdir -p /logs && sudo chown -R $(whoami):$(whoami) /logs && sudo chmod -R 777 /logs; then
|
||||
echo -e "- Created logs directory with proper permissions: ${GREEN}Success${NC}"
|
||||
else
|
||||
echo -e "- Creating logs directory: ${RED}Failed${NC}"
|
||||
echo "Warning: Logs will be saved inside container only"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}=== Starting Test Script ===${NC}"
|
||||
# Run the test script
|
||||
./test-setup.sh
|
||||
764
shell-setup/test-setup.sh
Executable file
764
shell-setup/test-setup.sh
Executable file
@@ -0,0 +1,764 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to test bootstrap.sh and setup.sh scripts in different environments
|
||||
# This script can be run on different systems to validate the setup process
|
||||
|
||||
# NOTE: We don't use 'set -e' to allow testing all packages even if some fail
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Maximum number of installation attempts
|
||||
MAX_INSTALL_ATTEMPTS=3
|
||||
CURRENT_ATTEMPT=1
|
||||
|
||||
# Log file
|
||||
# Create logs directory if it doesn't exist and is writable
|
||||
# First, try creating the logs directory in case it doesn't exist
|
||||
if [ -d "/logs" ] || mkdir -p /logs 2>/dev/null; then
|
||||
if [ -w "/logs" ]; then
|
||||
LOGS_DIR="/logs"
|
||||
echo -e "${GREEN}Logs will be saved to host system at ./logs/${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Warning: /logs directory exists but is not writable${NC}"
|
||||
sudo chmod -R 777 /logs 2>/dev/null || true
|
||||
if [ -w "/logs" ]; then
|
||||
LOGS_DIR="/logs"
|
||||
echo -e "${GREEN}Logs will be saved to host system at ./logs/ (permissions fixed)${NC}"
|
||||
else
|
||||
LOGS_DIR="/tmp"
|
||||
echo -e "${RED}Warning: Could not fix /logs permissions. Logs will be saved to $LOGS_DIR (container only)${NC}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
LOGS_DIR="/tmp"
|
||||
echo -e "${YELLOW}Warning: /logs directory not available or could not be created. Logs will be saved to $LOGS_DIR (container only)${NC}"
|
||||
fi
|
||||
# Use the timestamp from environment variable if set, otherwise generate a new one
|
||||
TIMESTAMP="${TEST_TIMESTAMP:-$(date +"%Y%m%d-%H%M%S")}"
|
||||
CONTAINER_INFO="${CONTAINER_TYPE:+$CONTAINER_TYPE-}"
|
||||
|
||||
LOG_FILE="$LOGS_DIR/setup-test-${CONTAINER_INFO}${TIMESTAMP}.log"
|
||||
echo "Starting setup test at $(date)" > "$LOG_FILE" || {
|
||||
echo -e "${RED}Error: Failed to write to log file at $LOG_FILE. Check permissions.${NC}"
|
||||
ls -la "$LOGS_DIR" 2>/dev/null || echo "Cannot list logs directory contents"
|
||||
LOGS_DIR="/tmp"
|
||||
LOG_FILE="$LOGS_DIR/setup-test-${CONTAINER_INFO}${TIMESTAMP}.log"
|
||||
echo -e "${YELLOW}Attempting to use fallback log location: $LOG_FILE${NC}"
|
||||
echo "Starting setup test at $(date)" > "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Identify the system
|
||||
echo -e "${BLUE}=== System Information ===${NC}"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
echo -e "Detected: ${GREEN}$PRETTY_NAME${NC}"
|
||||
echo "Testing on: $PRETTY_NAME" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}Could not determine OS${NC}"
|
||||
echo "Could not determine OS" >> "$LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine if this is a pre-bootstrap or post-bootstrap test
|
||||
TEST_STAGE="Unknown"
|
||||
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ] && [ -d "$HOME/shell/setup" ] && [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||
# Check if there are any signs that bootstrap has been completed
|
||||
if [ -d "$HOME/.oh-my-zsh" ] || [ -f "$HOME/.zshrc" ] || [ -d "$HOME/.nvm" ]; then
|
||||
TEST_STAGE="Post-Bootstrap"
|
||||
else
|
||||
TEST_STAGE="Mid-Bootstrap"
|
||||
fi
|
||||
else
|
||||
TEST_STAGE="Pre-Bootstrap"
|
||||
fi
|
||||
echo -e "Test Stage: ${GREEN}$TEST_STAGE${NC}"
|
||||
echo "Test Stage: $TEST_STAGE" >> "$LOG_FILE"
|
||||
|
||||
# Check if this is running in a test environment (container or VM)
|
||||
ENV_TYPE="Unknown"
|
||||
if [ -f /.dockerenv ]; then
|
||||
ENV_TYPE="Docker container"
|
||||
elif grep -q "^flags.*hypervisor" /proc/cpuinfo 2>/dev/null; then
|
||||
ENV_TYPE="Virtual machine"
|
||||
else
|
||||
ENV_TYPE="Physical machine"
|
||||
fi
|
||||
echo -e "Environment: ${GREEN}$ENV_TYPE${NC}"
|
||||
echo "Environment: $ENV_TYPE" >> "$LOG_FILE"
|
||||
|
||||
# Initialize arrays for tracking
|
||||
missing_packages=()
|
||||
installed_this_round=()
|
||||
failed_packages=()
|
||||
|
||||
# Helper functions
|
||||
check_command() {
|
||||
command -v "$1" &> /dev/null
|
||||
}
|
||||
|
||||
test_package() {
|
||||
local pkg=$1
|
||||
local cmd=${2:-$1}
|
||||
local alt_cmd=$3 # Optional alternative command name
|
||||
|
||||
echo -en "Testing if $pkg is installed... "
|
||||
|
||||
# Special case for cowsay and lolcat which might be in different paths
|
||||
if [ "$pkg" = "cowsay" ]; then
|
||||
if check_command "$cmd"; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
|
||||
return 0
|
||||
elif [ -x "/usr/games/cowsay" ]; then
|
||||
echo -e "${GREEN}✓${NC} (in /usr/games)"
|
||||
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
|
||||
# Create a symlink to make it available in PATH for other scripts
|
||||
if [ ! -e "$HOME/.local/bin" ]; then
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
fi
|
||||
if [ ! -e "$HOME/.local/bin/cowsay" ] && [ -w "$HOME/.local/bin" ]; then
|
||||
ln -sf /usr/games/cowsay "$HOME/.local/bin/cowsay"
|
||||
echo "Created symlink for cowsay in $HOME/.local/bin" >> "$LOG_FILE"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
elif [ "$pkg" = "lolcat" ]; then
|
||||
if check_command "$cmd"; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
|
||||
return 0
|
||||
elif [ -x "/usr/games/lolcat" ]; then
|
||||
echo -e "${GREEN}✓${NC} (in /usr/games)"
|
||||
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
|
||||
# Create a symlink to make it available in PATH for other scripts
|
||||
if [ ! -e "$HOME/.local/bin" ]; then
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
fi
|
||||
if [ ! -e "$HOME/.local/bin/lolcat" ] && [ -w "$HOME/.local/bin" ]; then
|
||||
ln -sf /usr/games/lolcat "$HOME/.local/bin/lolcat"
|
||||
echo "Created symlink for lolcat in $HOME/.local/bin" >> "$LOG_FILE"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
elif check_command "$cmd"; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$pkg: Installed (as $cmd)" >> "$LOG_FILE"
|
||||
return 0
|
||||
elif [ -n "$alt_cmd" ] && check_command "$alt_cmd"; then
|
||||
echo -e "${GREEN}✓${NC} (as $alt_cmd)"
|
||||
echo "$pkg: Installed (as $alt_cmd)" >> "$LOG_FILE"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
echo "$pkg: Missing" >> "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
# Note: The calling code will handle the failure and continue testing
|
||||
}
|
||||
|
||||
test_file_exists() {
|
||||
local file=$1
|
||||
local description=${2:-"File exists"}
|
||||
echo -en "Testing if $file exists... "
|
||||
if [ -e "$file" ]; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$description: Yes" >> "$LOG_FILE"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
echo "$description: No" >> "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get actual package name based on distribution
|
||||
get_package_name() {
|
||||
local pkg=$1
|
||||
|
||||
# Handle Debian-specific package name differences
|
||||
if [[ "$ID" == "debian" ]]; then
|
||||
case "$pkg" in
|
||||
"bat")
|
||||
echo "batcat"
|
||||
;;
|
||||
*)
|
||||
echo "$pkg"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# Default to the original package name for Ubuntu and others
|
||||
echo "$pkg"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to install missing packages
|
||||
install_missing_packages() {
|
||||
local packages=("$@")
|
||||
local install_cmd_name
|
||||
local install_cmd=()
|
||||
|
||||
if [ ${#packages[@]} -eq 0 ]; then
|
||||
echo -e "${GREEN}No packages to install${NC}"
|
||||
echo "No packages to install" >> "$LOG_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===${NC}"
|
||||
echo "=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===" >> "$LOG_FILE"
|
||||
|
||||
# Determine the best installation command
|
||||
if check_command nala; then
|
||||
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive nala install -y)
|
||||
install_cmd_name="nala"
|
||||
echo -e "${GREEN}Using nala for package installation${NC}"
|
||||
echo "Using nala for package installation" >> "$LOG_FILE"
|
||||
else
|
||||
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y)
|
||||
install_cmd_name="apt-get"
|
||||
echo -e "${YELLOW}Using apt-get for package installation${NC}"
|
||||
echo "Using apt-get for package installation" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Convert package list to distribution-specific names
|
||||
local install_list=()
|
||||
for pkg in "${packages[@]}"; do
|
||||
local actual_pkg=$(get_package_name "$pkg")
|
||||
install_list+=("$actual_pkg")
|
||||
done
|
||||
|
||||
# Update package lists
|
||||
echo -e "${YELLOW}Updating package lists...${NC}"
|
||||
echo "Updating package lists" >> "$LOG_FILE"
|
||||
if check_command nala; then
|
||||
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive nala update${NC}"
|
||||
sudo DEBIAN_FRONTEND=noninteractive nala update | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive apt-get update${NC}"
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update | tee -a "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Install packages
|
||||
echo -e "${YELLOW}Installing packages: ${install_list[*]}${NC}"
|
||||
echo "Installing packages: ${install_list[*]}" >> "$LOG_FILE"
|
||||
|
||||
# Show the exact command being run for debugging
|
||||
echo -e "${BLUE}Running: ${install_cmd[*]} ${install_list[*]}${NC}"
|
||||
|
||||
# Execute the install command with the package list
|
||||
if ! "${install_cmd[@]}" "${install_list[@]}" 2>&1 | tee -a "$LOG_FILE"; then
|
||||
echo -e "${RED}Failed to install some packages. Check the log for details.${NC}"
|
||||
echo "Failed to install some packages" >> "$LOG_FILE"
|
||||
|
||||
# Try to install packages one by one to identify problematic ones
|
||||
echo -e "${YELLOW}Trying to install packages individually...${NC}"
|
||||
echo "Trying to install packages individually" >> "$LOG_FILE"
|
||||
|
||||
installed_this_round=()
|
||||
local failed_this_round=()
|
||||
|
||||
for i in "${!packages[@]}"; do
|
||||
local pkg="${packages[$i]}"
|
||||
local actual_pkg="${install_list[$i]}"
|
||||
|
||||
echo -en "Installing $pkg as $actual_pkg... "
|
||||
if "${install_cmd[@]}" "$actual_pkg" >> "$LOG_FILE" 2>&1; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$pkg: Installed successfully" >> "$LOG_FILE"
|
||||
installed_this_round+=("$pkg")
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
echo "$pkg: Installation failed" >> "$LOG_FILE"
|
||||
failed_this_round+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
failed_packages=("${failed_this_round[@]}")
|
||||
return 1
|
||||
else
|
||||
echo -e "${GREEN}Successfully installed all packages!${NC}"
|
||||
echo "Successfully installed all packages" >> "$LOG_FILE"
|
||||
installed_this_round=("${packages[@]}")
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Create a temporary backup of .zshrc if it exists
|
||||
if [ -f "$HOME/.zshrc" ]; then
|
||||
cp "$HOME/.zshrc" "$HOME/.zshrc.test_backup"
|
||||
echo "Backed up existing .zshrc" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Main testing sequence
|
||||
echo -e "\n${BLUE}=== Testing bootstrap.sh ===${NC}"
|
||||
echo "=== Testing bootstrap.sh ===" >> "$LOG_FILE"
|
||||
|
||||
# Get the bootstrap script if it doesn't exist locally
|
||||
if [ ! -f "$HOME/shell/bootstrap.sh" ]; then
|
||||
echo -e "${YELLOW}Downloading bootstrap.sh...${NC}"
|
||||
echo "Downloading bootstrap.sh" >> "$LOG_FILE"
|
||||
curl -s -o /tmp/bootstrap.sh https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh || {
|
||||
echo -e "${RED}Failed to download bootstrap.sh${NC}"
|
||||
echo "Failed to download bootstrap.sh" >> "$LOG_FILE"
|
||||
exit 1
|
||||
}
|
||||
chmod +x /tmp/bootstrap.sh
|
||||
else
|
||||
echo -e "${YELLOW}Using local bootstrap.sh${NC}"
|
||||
echo "Using local bootstrap.sh" >> "$LOG_FILE"
|
||||
cp "$HOME/shell/bootstrap.sh" /tmp/bootstrap.sh
|
||||
fi
|
||||
|
||||
# Run bootstrap in test mode (no actual execution)
|
||||
echo -e "${YELLOW}Analyzing bootstrap script...${NC}"
|
||||
bash -n /tmp/bootstrap.sh
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}Bootstrap script syntax is valid${NC}"
|
||||
echo "Bootstrap script syntax: Valid" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}Bootstrap script has syntax errors${NC}"
|
||||
echo "Bootstrap script syntax: Invalid" >> "$LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}=== Testing setup.sh ===${NC}"
|
||||
echo "=== Testing setup.sh ===" >> "$LOG_FILE"
|
||||
|
||||
# Check setup.sh script if available
|
||||
if [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||
echo -e "${YELLOW}Analyzing setup script...${NC}"
|
||||
bash -n "$HOME/shell/setup/setup.sh"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}Setup script syntax is valid${NC}"
|
||||
echo "Setup script syntax: Valid" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}Setup script has syntax errors${NC}"
|
||||
echo "Setup script syntax: Invalid" >> "$LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}Setup script not available locally. Will be downloaded by bootstrap.${NC}"
|
||||
echo "Setup script not available locally" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}=== Testing Debian compatibility ===${NC}"
|
||||
echo "=== Testing Debian compatibility ===" >> "$LOG_FILE"
|
||||
|
||||
# Check for Debian-specific commands used in scripts
|
||||
echo -en "Checking if apt is available... "
|
||||
if check_command apt; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "apt: Available" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}✗${NC} (Scripts may not work here)"
|
||||
echo "apt: Not available" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Check if the package list is valid for this system
|
||||
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||
echo -e "${YELLOW}Testing package availability in repositories:${NC}"
|
||||
echo "Testing package availability:" >> "$LOG_FILE"
|
||||
|
||||
# Exclude commented lines and empty lines
|
||||
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
|
||||
|
||||
for pkg in $packages; do
|
||||
echo -en "Checking if $pkg is available in repos... "
|
||||
actual_pkg=$(get_package_name "$pkg")
|
||||
if apt-cache show "$actual_pkg" &>/dev/null; then
|
||||
echo -e "${GREEN}✓${NC}"
|
||||
echo "$pkg: Available in repos as $actual_pkg" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}✗${NC}"
|
||||
echo "$pkg: Not available in repos" >> "$LOG_FILE"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Main testing and installation loop
|
||||
while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
|
||||
echo -e "\n${BLUE}=== Testing installed components (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===${NC}"
|
||||
echo "=== Testing installed components (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===" >> "$LOG_FILE"
|
||||
|
||||
errors=0
|
||||
missing_packages=()
|
||||
|
||||
# Test core required tools
|
||||
core_tools=("git" "curl" "wget")
|
||||
for tool in "${core_tools[@]}"; do
|
||||
if ! test_package "$tool"; then
|
||||
((errors++))
|
||||
missing_packages+=("$tool")
|
||||
fi
|
||||
done
|
||||
|
||||
# Test if setup has already been run
|
||||
if [ -d "$HOME/.oh-my-zsh" ]; then
|
||||
echo -e "Oh My Zsh: ${GREEN}Installed${NC}"
|
||||
echo "Oh My Zsh: Installed" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "Oh My Zsh: ${YELLOW}Not installed${NC}"
|
||||
echo "Oh My Zsh: Not installed" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Check custom packages from packages.list
|
||||
echo -e "${YELLOW}Testing packages listed in packages.list:${NC}"
|
||||
echo "Testing packages listed in packages.list:" >> "$LOG_FILE"
|
||||
|
||||
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||
# Exclude commented lines and empty lines
|
||||
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
|
||||
|
||||
for pkg in $packages; do
|
||||
case "$pkg" in
|
||||
"bat")
|
||||
if ! test_package "bat" "bat" "batcat"; then
|
||||
((errors++))
|
||||
missing_packages+=("$pkg")
|
||||
fi
|
||||
;;
|
||||
"cowsay")
|
||||
# Extra debugging for cowsay
|
||||
echo -e "\n${BLUE}Debugging cowsay package:${NC}" | tee -a "$LOG_FILE"
|
||||
if [ -f "/usr/games/cowsay" ]; then
|
||||
echo -e "- Cowsay found at /usr/games/cowsay" | tee -a "$LOG_FILE"
|
||||
ls -la /usr/games/cowsay | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo -e "- Cowsay not found at /usr/games/cowsay" | tee -a "$LOG_FILE"
|
||||
fi
|
||||
if check_command cowsay; then
|
||||
echo -e "- Cowsay found in PATH" | tee -a "$LOG_FILE"
|
||||
command -v cowsay | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo -e "- Cowsay not found in PATH" | tee -a "$LOG_FILE"
|
||||
fi
|
||||
|
||||
if ! test_package "cowsay" "cowsay"; then
|
||||
((errors++))
|
||||
missing_packages+=("$pkg")
|
||||
fi
|
||||
;;
|
||||
"lolcat")
|
||||
# Extra debugging for lolcat
|
||||
echo -e "\n${BLUE}Debugging lolcat package:${NC}" | tee -a "$LOG_FILE"
|
||||
if [ -f "/usr/games/lolcat" ]; then
|
||||
echo -e "- Lolcat found at /usr/games/lolcat" | tee -a "$LOG_FILE"
|
||||
ls -la /usr/games/lolcat | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo -e "- Lolcat not found at /usr/games/lolcat" | tee -a "$LOG_FILE"
|
||||
fi
|
||||
if check_command lolcat; then
|
||||
echo -e "- Lolcat found in PATH" | tee -a "$LOG_FILE"
|
||||
command -v lolcat | tee -a "$LOG_FILE"
|
||||
else
|
||||
echo -e "- Lolcat not found in PATH" | tee -a "$LOG_FILE"
|
||||
fi
|
||||
|
||||
if ! test_package "lolcat" "lolcat"; then
|
||||
((errors++))
|
||||
missing_packages+=("$pkg")
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if ! test_package "$pkg" "$pkg"; then
|
||||
((errors++))
|
||||
missing_packages+=("$pkg")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Report missing packages
|
||||
if [ ${#missing_packages[@]} -gt 0 ]; then
|
||||
echo -e "\n${YELLOW}Missing packages:${NC}"
|
||||
for pkg in "${missing_packages[@]}"; do
|
||||
echo -e "- ${RED}$pkg${NC}"
|
||||
done
|
||||
|
||||
# Count installed vs. total packages
|
||||
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||
installed_pkgs=$((total_pkgs - ${#missing_packages[@]}))
|
||||
echo -e "${GREEN}$installed_pkgs of $total_pkgs packages installed${NC} (${YELLOW}${#missing_packages[@]} missing${NC})"
|
||||
echo "$installed_pkgs of $total_pkgs packages installed (${#missing_packages[@]} missing)" >> "$LOG_FILE"
|
||||
|
||||
# Install missing packages if we haven't reached the maximum attempts
|
||||
if [ $CURRENT_ATTEMPT -lt $MAX_INSTALL_ATTEMPTS ]; then
|
||||
install_missing_packages "${missing_packages[@]}"
|
||||
|
||||
echo -e "\n${BLUE}=== Installation Results ===${NC}"
|
||||
if [ ${#installed_this_round[@]} -gt 0 ]; then
|
||||
echo -e "${GREEN}Successfully installed:${NC}"
|
||||
for pkg in "${installed_this_round[@]}"; do
|
||||
echo -e "- ${GREEN}$pkg${NC}"
|
||||
done
|
||||
echo "Successfully installed: ${installed_this_round[*]}" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
if [ ${#failed_packages[@]} -gt 0 ]; then
|
||||
echo -e "${RED}Failed to install:${NC}"
|
||||
for pkg in "${failed_packages[@]}"; do
|
||||
echo -e "- ${RED}$pkg${NC}"
|
||||
done
|
||||
echo "Failed to install: ${failed_packages[*]}" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
CURRENT_ATTEMPT=$((CURRENT_ATTEMPT + 1))
|
||||
echo -e "\n${YELLOW}Continuing to next test iteration...${NC}"
|
||||
echo "Continuing to next test iteration" >> "$LOG_FILE"
|
||||
continue
|
||||
fi
|
||||
else
|
||||
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||
echo -e "\n${GREEN}All $total_pkgs packages are installed!${NC}"
|
||||
echo "All $total_pkgs packages are installed" >> "$LOG_FILE"
|
||||
break
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}packages.list file not found at $HOME/shell/setup/packages.list${NC}"
|
||||
echo "packages.list file not found" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# If no missing packages or we've reached max attempts, break out of the loop
|
||||
if [ ${#missing_packages[@]} -eq 0 ] || [ $CURRENT_ATTEMPT -ge $MAX_INSTALL_ATTEMPTS ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
CURRENT_ATTEMPT=$((CURRENT_ATTEMPT + 1))
|
||||
done
|
||||
|
||||
# Test nvm installation
|
||||
if [ -d "$HOME/.nvm" ]; then
|
||||
echo -e "NVM: ${GREEN}Installed${NC}"
|
||||
echo "NVM: Installed" >> "$LOG_FILE"
|
||||
|
||||
# Source NVM
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
|
||||
# Test Node.js installed by NVM
|
||||
if check_command node; then
|
||||
node_version=$(node -v)
|
||||
echo -e "Node.js: ${GREEN}$node_version${NC}"
|
||||
echo "Node.js: $node_version" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "Node.js: ${RED}Not installed${NC}"
|
||||
echo "Node.js: Not installed" >> "$LOG_FILE"
|
||||
((errors++))
|
||||
fi
|
||||
else
|
||||
echo -e "NVM: ${YELLOW}Not installed${NC}"
|
||||
echo "NVM: Not installed" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Test zoxide
|
||||
if test_package "zoxide"; then
|
||||
echo -e "Zoxide integration: ${GREEN}Available${NC}"
|
||||
echo "Zoxide integration: Available" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Test ZSH plugins
|
||||
zsh_plugins=(
|
||||
"$HOME/.oh-my-zsh/custom/plugins/zsh-autosuggestions"
|
||||
"$HOME/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting"
|
||||
"$HOME/.oh-my-zsh/custom/plugins/zsh-you-should-use"
|
||||
)
|
||||
|
||||
for plugin_dir in "${zsh_plugins[@]}"; do
|
||||
plugin_name=$(basename "$plugin_dir")
|
||||
if [ -d "$plugin_dir" ]; then
|
||||
echo -e "ZSH plugin $plugin_name: ${GREEN}Installed${NC}"
|
||||
echo "ZSH plugin $plugin_name: Installed" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "ZSH plugin $plugin_name: ${YELLOW}Not installed${NC}"
|
||||
echo "ZSH plugin $plugin_name: Not installed" >> "$LOG_FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
# Test dotfile linking
|
||||
dotfiles=(
|
||||
"$HOME/.zshrc"
|
||||
"$HOME/.nanorc"
|
||||
"$HOME/.profile"
|
||||
"$HOME/.gitconfig"
|
||||
)
|
||||
|
||||
for dotfile in "${dotfiles[@]}"; do
|
||||
if [ -L "$dotfile" ]; then
|
||||
echo -e "Dotfile $dotfile: ${GREEN}Symlinked${NC}"
|
||||
echo "Dotfile $dotfile: Symlinked" >> "$LOG_FILE"
|
||||
|
||||
# Check if symlink is valid
|
||||
if [ -e "$dotfile" ]; then
|
||||
target=$(readlink -f "$dotfile")
|
||||
echo -e " → Links to: ${GREEN}$target${NC}"
|
||||
echo " → Links to: $target" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e " → ${RED}Broken symlink${NC}"
|
||||
echo " → Broken symlink" >> "$LOG_FILE"
|
||||
((errors++))
|
||||
fi
|
||||
elif [ -f "$dotfile" ]; then
|
||||
echo -e "Dotfile $dotfile: ${YELLOW}Exists but not symlinked${NC}"
|
||||
echo "Dotfile $dotfile: Exists but not symlinked" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "Dotfile $dotfile: ${YELLOW}Not present${NC}"
|
||||
echo "Dotfile $dotfile: Not present" >> "$LOG_FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\n${BLUE}=== Summary ===${NC}"
|
||||
echo "=== Summary ===" >> "$LOG_FILE"
|
||||
|
||||
# Test summary
|
||||
if [ $errors -eq 0 ]; then
|
||||
echo -e "${GREEN}All critical components and packages passed! Your setup appears to be working correctly.${NC}"
|
||||
echo "Result: All critical components and packages passed" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e "${RED}Found $errors potential issues with your setup.${NC}"
|
||||
echo "Result: Found $errors potential issues" >> "$LOG_FILE"
|
||||
|
||||
# Display missing packages if any
|
||||
if [ ${#missing_packages[@]} -gt 0 ]; then
|
||||
echo -e "\n${YELLOW}The following packages were not found:${NC}"
|
||||
echo "Missing packages:" >> "$LOG_FILE"
|
||||
for pkg in "${missing_packages[@]}"; do
|
||||
echo -e " - ${RED}$pkg${NC}"
|
||||
echo " - $pkg" >> "$LOG_FILE"
|
||||
done
|
||||
|
||||
if [ $CURRENT_ATTEMPT -gt $MAX_INSTALL_ATTEMPTS ]; then
|
||||
echo -e "\n${RED}Reached maximum installation attempts ($MAX_INSTALL_ATTEMPTS).${NC}"
|
||||
echo -e "${YELLOW}Some packages could not be installed automatically.${NC}"
|
||||
echo "Reached maximum installation attempts" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}You can manually install these packages with:${NC}"
|
||||
echo -e " sudo apt-get install ${missing_packages[*]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Provide more detailed information about log files
|
||||
if [[ "$LOG_FILE" == "/logs/"* ]]; then
|
||||
HOST_LOG_FILE="./logs/$(basename "$LOG_FILE")"
|
||||
echo -e "\n${YELLOW}Complete test log saved to:${NC} $LOG_FILE"
|
||||
echo -e "${GREEN}This log file is accessible on the host system at:${NC} $HOST_LOG_FILE"
|
||||
else
|
||||
echo -e "\n${YELLOW}Complete test log saved to:${NC} $LOG_FILE (in container only)"
|
||||
echo -e "${YELLOW}Note: This log file will be lost when the container exits."
|
||||
echo -e "To preserve logs, run with the logs volume mounted using run-docker-tests.sh${NC}"
|
||||
fi
|
||||
|
||||
# Check for Debian-specific issues
|
||||
if [[ "$ID" == "debian" ]]; then
|
||||
echo -e "\n${BLUE}=== Debian-Specific Recommendations ===${NC}"
|
||||
echo "=== Debian-Specific Recommendations ===" >> "$LOG_FILE"
|
||||
echo "1. Ensure Debian's 'universe' equivalent repositories are enabled (contrib, non-free)"
|
||||
echo "2. Some packages like 'bat' may have different names in Debian (batcat)"
|
||||
echo "3. Consider adding Debian-specific adjustments to setup.sh"
|
||||
|
||||
# Add specific Debian package name mappings
|
||||
echo -e "\nOn Debian, you may need these package name adjustments:"
|
||||
echo " - bat → batcat"
|
||||
echo " - (add more as needed)"
|
||||
|
||||
echo "Debian package name mappings may be required" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Enhanced testing for bootstrapped environment
|
||||
check_bootstrapped_environment() {
|
||||
echo -e "\n${BLUE}=== Checking for bootstrapped environment ===${NC}"
|
||||
echo "=== Checking for bootstrapped environment ===" >> "$LOG_FILE"
|
||||
|
||||
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ]; then
|
||||
echo -e "${GREEN}Environment appears to be bootstrapped:${NC}"
|
||||
echo "Environment is bootstrapped" >> "$LOG_FILE"
|
||||
|
||||
# Check the shell repository structure
|
||||
if [ -d "$HOME/shell/setup" ] && [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||
echo -e " - ${GREEN}Setup directory and script present${NC}"
|
||||
echo "Setup directory and script: Present" >> "$LOG_FILE"
|
||||
|
||||
# Check if setup.sh is executable
|
||||
if [ -x "$HOME/shell/setup/setup.sh" ]; then
|
||||
echo -e " - ${GREEN}Setup script is executable${NC}"
|
||||
echo "Setup script is executable: Yes" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e " - ${RED}Setup script is not executable${NC}"
|
||||
echo "Setup script is executable: No" >> "$LOG_FILE"
|
||||
fi
|
||||
else
|
||||
echo -e " - ${RED}Setup directory or setup.sh missing${NC}"
|
||||
echo "Setup directory or setup.sh: Missing" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Check packages.list
|
||||
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||
echo -e " - ${GREEN}Packages list present${NC}"
|
||||
echo "Packages list: Present" >> "$LOG_FILE"
|
||||
|
||||
# Count packages in list
|
||||
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||
echo -e " - ${GREEN}Package list contains $pkg_count packages${NC}"
|
||||
echo "Package list count: $pkg_count" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e " - ${RED}Packages list missing${NC}"
|
||||
echo "Packages list: Missing" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# Check dotfiles directory
|
||||
if [ -d "$HOME/shell/dotfiles" ]; then
|
||||
echo -e " - ${GREEN}Dotfiles directory present${NC}"
|
||||
echo "Dotfiles directory: Present" >> "$LOG_FILE"
|
||||
|
||||
# Check if dotfiles are properly symlinked
|
||||
dotfiles_linked=true
|
||||
for dotfile in "$HOME/.zshrc" "$HOME/.nanorc" "$HOME/.profile" "$HOME/.gitconfig"; do
|
||||
if [ -L "$dotfile" ]; then
|
||||
target=$(readlink -f "$dotfile" 2>/dev/null)
|
||||
if [[ "$target" == *"shell/dotfiles"* ]]; then
|
||||
continue
|
||||
else
|
||||
dotfiles_linked=false
|
||||
break
|
||||
fi
|
||||
else
|
||||
dotfiles_linked=false
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if $dotfiles_linked; then
|
||||
echo -e " - ${GREEN}Dotfiles are properly symlinked${NC}"
|
||||
echo "Dotfiles symlinked: Yes" >> "$LOG_FILE"
|
||||
else
|
||||
echo -e " - ${YELLOW}Some dotfiles are not properly symlinked${NC}"
|
||||
echo "Dotfiles symlinked: No" >> "$LOG_FILE"
|
||||
fi
|
||||
else
|
||||
echo -e " - ${RED}Dotfiles directory missing${NC}"
|
||||
echo "Dotfiles directory: Missing" >> "$LOG_FILE"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}No bootstrapped environment detected${NC}"
|
||||
echo "No bootstrapped environment detected" >> "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Call the check if we're not in a simple test environment
|
||||
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ]; then
|
||||
check_bootstrapped_environment
|
||||
fi
|
||||
|
||||
# Restore .zshrc if we backed it up
|
||||
if [ -f "$HOME/.zshrc.test_backup" ]; then
|
||||
echo -e "\n${YELLOW}Restoring original .zshrc${NC}"
|
||||
mv "$HOME/.zshrc.test_backup" "$HOME/.zshrc"
|
||||
echo "Restored original .zshrc" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}Test completed!${NC}"
|
||||
echo "Test completed at $(date)" >> "$LOG_FILE"
|
||||
Reference in New Issue
Block a user