diff --git a/.agent/instructions.md b/.agent/instructions.md index ba7ed18..c587434 100644 --- a/.agent/instructions.md +++ b/.agent/instructions.md @@ -11,14 +11,55 @@ When maintaining this repository, you MUST adhere to the following rules based o 2. **Setup Scripts**: - If a setup script does not exist, CREATE one named `create__folders.sh` in the service directory. - - Use the following template for scripts: + - Use the following template for scripts (Intelligent Dry-run by default): ```bash #!/bin/bash - BASE="/volume1/docker/service_name" - MEDIA="/volume1/media/service_data" - mkdir -p "$BASE/config" "$BASE/data" "$MEDIA" - chown -R PUID:PGID "$BASE" "$MEDIA" - chmod -R 750 "$BASE" "$MEDIA" + DRY_RUN=true + if [[ "$1" == "--run" || "$1" == "-r" ]]; then DRY_RUN=false; fi + + if [ "$DRY_RUN" = "true" ]; then + echo "--- DRY RUN MODE ---" + echo "To apply changes, run: sudo bash $0 --run" + echo "--------------------" + fi + + run_mkdir() { + local path=$1 + if [ -d "$path" ]; then + echo "[OK] Folder exists, no changes will be made: $path" + else + if [ "$DRY_RUN" = "true" ]; then echo "[WILL CREATE] Folder: $path"; else mkdir -p "$path"; fi + fi + } + + run_chown_recursive() { + local owner=$1; local path=$2 + local uid=${owner%%:*}; local gid=${owner#*:} + + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then echo "[WILL SET] Owner to $owner upon creation: $path"; else chown -R "$owner" "$path"; fi + return + fi + + if find "$path" \( ! -uid "$uid" -o ! -gid "$gid" \) | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then echo "[WILL CHANGE] Owner to $owner (recursive): $path"; else chown -R "$owner" "$path"; fi + else + echo "[OK] Owner is $owner, no changes will be made: $path" + fi + } + + run_chmod_recursive() { + local mode=$1; local path=$2 + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then echo "[WILL SET] Permissions to $mode upon creation: $path"; else chmod -R "$mode" "$path"; fi + return + fi + if find "$path" ! -perm -"$mode" | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then echo "[WILL CHANGE] Permissions to $mode (recursive): $path"; else chmod -R "$mode" "$path"; fi + else + echo "[OK] Permissions are $mode, no changes will be made: $path" + fi + } ``` - Ensure the script is idempotent (safe to run multiple times). diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md index a880532..b8bd0bd 100644 --- a/REQUIREMENTS.md +++ b/REQUIREMENTS.md @@ -18,6 +18,12 @@ This document outlines the mandatory standards for services managed in this repo ## 3. Deployment and Setup - **Idempotent Scripts**: Every service must include a `create__folders.sh` script. - **Setup Documentation**: Every service folder must contain a `SETUP.md` file documenting the end-to-end flow, highlighting manual pre-setup steps (user creation, ID lookup). +- **Intelligent Dry-Run Mode**: Scripts must support a dry-run mode (default) that compares current system state with target state: + - If a folder exists, report it as "existing" with the phrase "no changes will be made". + - If owner/permissions already match, report as "matched" with current state and the phrase "no changes will be made". + - If a target folder does not exist yet during a dry-run check, report ownership/permissions as "WILL SET upon creation". + - **Recursion**: For recursive operations (`chown -R`, `chmod -R`), dry-run must verify all nested items and report if any deviate from the target state. + - **Execute Instructions**: The dry-run output must clearly instruct the user how to apply the changes (e.g., "To apply changes, run: sudo bash $0 --run"). - **Script Requirements**: - Must use `mkdir -p` to handle existing directories. - Must set correct ownership (`chown`) and permissions (`chmod`) based on the service user. diff --git a/portracker/create_portracker_folders.sh b/portracker/create_portracker_folders.sh index 7ded59c..4831686 100644 --- a/portracker/create_portracker_folders.sh +++ b/portracker/create_portracker_folders.sh @@ -1,13 +1,93 @@ #!/bin/bash -# Define base path +# Default to dry-run mode +DRY_RUN=true +if [[ "$1" == "--run" || "$1" == "-r" ]]; then DRY_RUN=false; fi + +if [ "$DRY_RUN" = "true" ]; then + echo "--- DRY RUN MODE ---" + echo "To apply changes, run: sudo bash $0 --run" + echo "--------------------" +fi + +# Configuration BASE="/volume1/docker/portracker" +USER_ID="1043:65538" # svc-portracker -# Create folders -mkdir -p "${BASE}/data" +# Helper functions +run_mkdir() { + local path=$1 + if [ -d "$path" ]; then + echo "[OK] Folder exists, no changes will be made: $path" + else + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CREATE] Folder: $path" + else + echo "[EXECUTE] Creating folder: $path" + mkdir -p "$path" + fi + fi +} -# Set ownership and permissions -# Set ownership and permissions for svc-portracker (1043:65538) -chown -R 1043:65538 "${BASE}" -chmod -R 750 "${BASE}" +run_chown_recursive() { + local owner=$1; local path=$2 + local uid=${owner%%:*}; local gid=${owner#*:} + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Owner to $owner upon creation: $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target ownership + if find "$path" \( ! -uid "$uid" -o ! -gid "$gid" \) | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Owner to $owner (recursive): $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + else + echo "[OK] Owner is $owner, no changes will be made: $path" + fi +} -echo "Folders created and permissions set for ${BASE}" +run_chmod_recursive() { + local mode=$1; local path=$2 + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Permissions to $mode upon creation: $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target permissions + if find "$path" ! -perm -"$mode" | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Permissions to $mode (recursive): $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + else + echo "[OK] Permissions are $mode, no changes will be made: $path" + fi +} + +# Run tasks +run_mkdir "${BASE}/data" +run_chown_recursive "$USER_ID" "${BASE}" +run_chmod_recursive 750 "${BASE}" + +if [ "$DRY_RUN" = "false" ]; then + echo "Done." +fi