diff --git a/.gitignore b/.gitignore index 9580455..b707aa2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ /shared/system-logs/* !/shared/system-logs/.gitkeep +/bin/* +!/bin/.gitkeep + + **/.idea /.env /.env.ready.* diff --git a/README.md b/README.md index e342436..8c97ad8 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ graph TD; | git | N/A | Manual | - | | bash | 4.4 at least | Manual | - | | curl | N/A | Manual | - | -| yq | 4.35.1 | Manual | Use v4.35.1 instead of the latest version. The lastest version causes a parsing error | +| yq | 4.35.1 | Auto | Use v4.35.1 instead of the latest version. The lastest version causes a parsing error | | consul (docker image) | 1.14.11 | Auto | An error occurred due to a payload format issue while the lastest version of it was communicating with gliderlabs/registrator. | | gliderlabs/registrator (docker image) | master | Auto | | | nginx (docker image) | 1.25.4 | Auto | Considering changing it to a certain version, but until now no issues have been detected. | diff --git a/apply-security.sh b/apply-security.sh index fa4f512..88ff98b 100644 --- a/apply-security.sh +++ b/apply-security.sh @@ -32,7 +32,24 @@ sudo chmod 750 *.sh || echo "[WARN] Running chmod 750 *.sh failed." sudo chmod 770 *.yml || echo "[WARN] Running chmod 770 *.yml failed." sudo chmod 740 .env.* || echo "[WARN] Running chmod 740 .env.* failed." sudo chmod 740 .env || echo "[WARN] Running chmod 740 .env failed." +sudo chmod -R 750 bin || echo "[WARN] Running chmod 750 for the bin folder" sudo chmod 770 .gitignore || echo "[WARN] Running chmod 770 .gitignore failed." sudo chmod -R 770 .docker/ || echo "[WARN] Running chmod -R 770 .docker/ failed." -sudo chown -R 0:${shared_volume_group_id} .docker/ || echo "[WARN] Running chgrp ${shared_volume_group_id} .docker/ failed." -set_safe_filemode_on_app +# Check if the OS is not Darwin (macOS) before running the command +if [[ "$(uname)" != "Darwin" ]]; then + sudo chown -R 0:${shared_volume_group_id} .docker/ || echo "[WARN] Running chgrp ${shared_volume_group_id} .docker/ failed." +else + echo "[NOTICE] Skipping chown command on Darwin (macOS) platform. See the README." +fi + +if [[ "$(uname)" != "Darwin" ]]; then + sudo chown -R 0:${shared_volume_group_id} bin/ || echo "[WARN] Running chgrp ${shared_volume_group_id} bin/ failed." +else + echo "[NOTICE] Skipping chown command on Darwin (macOS) platform. See the README." +fi + +if [[ "$(uname)" != "Darwin" ]]; then + set_safe_filemode_on_app +else + echo "[NOTICE] Skipping chown command on Darwin (macOS) platform. See the README." +fi diff --git a/bin/.gitkeep b/bin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/emergency-consul-down-and-up.sh b/emergency-consul-down-and-up.sh index 935ccc5..ccb06d4 100644 --- a/emergency-consul-down-and-up.sh +++ b/emergency-consul-down-and-up.sh @@ -2,6 +2,7 @@ set -eu source use-common.sh +check_yq_installed check_bash_version check_gnu_grep_installed check_gnu_sed_installed diff --git a/emergency-nginx-down-and-up.sh b/emergency-nginx-down-and-up.sh index 30b7476..badbd0c 100644 --- a/emergency-nginx-down-and-up.sh +++ b/emergency-nginx-down-and-up.sh @@ -3,6 +3,7 @@ set -eu source use-common.sh +check_yq_installed check_bash_version check_gnu_grep_installed check_gnu_sed_installed diff --git a/emergency-nginx-restart.sh b/emergency-nginx-restart.sh index a1abf35..cb90cea 100644 --- a/emergency-nginx-restart.sh +++ b/emergency-nginx-restart.sh @@ -2,6 +2,8 @@ set -eu source use-common.sh + +check_yq_installed check_bash_version check_gnu_grep_installed check_gnu_sed_installed diff --git a/remove-all-images.sh b/remove-all-images.sh index f03af6a..4670620 100644 --- a/remove-all-images.sh +++ b/remove-all-images.sh @@ -2,6 +2,7 @@ set -eu source use-common.sh +check_yq_installed check_bash_version check_gnu_grep_installed check_gnu_sed_installed diff --git a/stop-all-containers.sh b/stop-all-containers.sh index 914b4d5..4755801 100644 --- a/stop-all-containers.sh +++ b/stop-all-containers.sh @@ -1,5 +1,6 @@ #!/bin/bash source use-common.sh +check_yq_installed check_bash_version check_gnu_grep_installed check_gnu_sed_installed diff --git a/use-app.sh b/use-app.sh index d0fbb8a..245337c 100644 --- a/use-app.sh +++ b/use-app.sh @@ -35,14 +35,14 @@ apply_env_service_name_onto_app_yaml(){ check_yq_installed if [[ ${orchestration_type} == 'stack' ]]; then - yq -i "with(.services; with_entries(select(.key ==\"*-${new_state}\") | .key |= \"${project_name}-${new_state}\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the green service name in the app YAML as ${project_name}." && exit 1) - # yq eval '(.services.[] | select(.image == "${PROJECT_NAME}:blue")).image |= \"${project_name}-blue\"' -i docker-${orchestration_type}-${project_name}-blue.yml || (echo "[ERROR] Failed to apply image : ${project_name}-blue in the app YAML." && exit 1) - yq -i "(.services.\"${project_name}-${new_state}\").image = \"${project_name}:${new_state}\"" -i docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply image : ${project_name}-${new_state} in the app YAML." && exit 1) + bin/yq -i "with(.services; with_entries(select(.key ==\"*-${new_state}\") | .key |= \"${project_name}-${new_state}\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the green service name in the app YAML as ${project_name}." && exit 1) + # bin/yq eval '(.services.[] | select(.image == "${PROJECT_NAME}:blue")).image |= \"${project_name}-blue\"' -i docker-${orchestration_type}-${project_name}-blue.yml || (echo "[ERROR] Failed to apply image : ${project_name}-blue in the app YAML." && exit 1) + bin/yq -i "(.services.\"${project_name}-${new_state}\").image = \"${project_name}:${new_state}\"" -i docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply image : ${project_name}-${new_state} in the app YAML." && exit 1) else echo "[NOTICE] PROJECT_NAME on .env is now being applied to docker-${orchestration_type}-${project_name}-${app_env}.yml." - yq -i "with(.services; with_entries(select(.key ==\"*-blue\") | .key |= \"${project_name}-blue\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the blue service name in the app YAML as ${project_name}." && exit 1) + bin/yq -i "with(.services; with_entries(select(.key ==\"*-blue\") | .key |= \"${project_name}-blue\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the blue service name in the app YAML as ${project_name}." && exit 1) sleep 2 - yq -i "with(.services; with_entries(select(.key ==\"*-green\") | .key |= \"${project_name}-green\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the green service name in the app YAML as ${project_name}." && exit 1) + bin/yq -i "with(.services; with_entries(select(.key ==\"*-green\") | .key |= \"${project_name}-green\"))" docker-${orchestration_type}-${project_name}-${app_env}.yml || (echo "[ERROR] Failed to apply the green service name in the app YAML as ${project_name}." && exit 1) fi } @@ -61,12 +61,12 @@ apply_docker_compose_environment_onto_app_yaml(){ for state in "${states[@]}" do - yq -i '.services.'${project_name}'-'${state}'.environment = []' docker-${orchestration_type}-${project_name}-${app_env}.yml - yq -i '.services.'${project_name}'-'${state}'.environment += "SERVICE_NAME='${state}'"' docker-${orchestration_type}-${project_name}-${app_env}.yml + bin/yq -i '.services.'${project_name}'-'${state}'.environment = []' docker-${orchestration_type}-${project_name}-${app_env}.yml + bin/yq -i '.services.'${project_name}'-'${state}'.environment += "SERVICE_NAME='${state}'"' docker-${orchestration_type}-${project_name}-${app_env}.yml - for ((i=1; i<=$(echo ${docker_compose_environment} | yq eval 'length'); i++)) + for ((i=1; i<=$(echo ${docker_compose_environment} | bin/yq eval 'length'); i++)) do - yq -i '.services.'${project_name}'-'${state}'.environment += "'$(echo ${docker_compose_environment} | yq -r 'to_entries | .['$((i-1))'].key')'='$(echo ${docker_compose_environment} | yq -r 'to_entries | .['$((i-1))'].value')'"' docker-${orchestration_type}-${project_name}-${app_env}.yml + bin/yq -i '.services.'${project_name}'-'${state}'.environment += "'$(echo ${docker_compose_environment} | bin/yq -r 'to_entries | .['$((i-1))'].key')'='$(echo ${docker_compose_environment} | bin/yq -r 'to_entries | .['$((i-1))'].value')'"' docker-${orchestration_type}-${project_name}-${app_env}.yml done done @@ -107,11 +107,11 @@ apply_docker_compose_volumes_onto_app_real_yaml(){ for state in "${states[@]}" do - #yq -i '.services.'${project_name}'-'${state}'.volumes = []' ./docker-${orchestration_type}-${project_name}-real.yml + #bin/yq -i '.services.'${project_name}'-'${state}'.volumes = []' ./docker-${orchestration_type}-${project_name}-real.yml for volume in "${docker_compose_real_selective_volumes[@]}" do - yq -i '.services.'${project_name}'-'${state}'.volumes += '${volume}'' ./docker-${orchestration_type}-${project_name}-real.yml + bin/yq -i '.services.'${project_name}'-'${state}'.volumes += '${volume}'' ./docker-${orchestration_type}-${project_name}-real.yml done done @@ -126,9 +126,9 @@ make_docker_build_arg_strings(){ local re="" - for ((i=1; i<=$(echo ${docker_build_args} | yq eval 'length'); i++)) + for ((i=1; i<=$(echo ${docker_build_args} | bin/yq eval 'length'); i++)) do - re="${re} --build-arg $(echo ${docker_build_args} | yq -r 'to_entries | .['$((i-1))'].key')=$(echo ${docker_build_args} | yq -r 'to_entries | .['$((i-1))'].value')" + re="${re} --build-arg $(echo ${docker_build_args} | bin/yq -r 'to_entries | .['$((i-1))'].key')=$(echo ${docker_build_args} | bin/yq -r 'to_entries | .['$((i-1))'].value')" done echo ${re} diff --git a/use-common.sh b/use-common.sh index 2002127..7547517 100644 --- a/use-common.sh +++ b/use-common.sh @@ -65,8 +65,8 @@ set_expose_and_app_port(){ fi if echo "${1}" | grep -Eq '^\[[0-9]+,[0-9]+\]$'; then - expose_port=$(echo "$project_port" | yq e '.[0]' -) - app_port=$(echo "$project_port" | yq e '.[1]' -) + expose_port=$(echo "$project_port" | bin/yq e '.[0]' -) + app_port=$(echo "$project_port" | bin/yq e '.[1]' -) else expose_port="$project_port" app_port="$project_port" @@ -255,25 +255,67 @@ cache_global_vars() { check_yq_installed(){ required_version="4.35.1" + yq_path="bin/yq" + + # Function to download yq + download_yq() { + echo "[NOTICE] Downloading bin/yq version $required_version..." >&2 + + # Detect OS and architecture + ARCH=$(uname -m) + OS=$(uname | tr '[:upper:]' '[:lower:]') + + # Determine the correct bin/yq binary based on architecture + case "$OS-$ARCH" in + linux-x86_64) + YQ_BINARY="yq_linux_amd64" + ;; + linux-aarch64) + YQ_BINARY="yq_linux_arm64" + ;; + linux-armv7l | linux-armhf) + YQ_BINARY="yq_linux_arm" + ;; + linux-i386 | linux-i686) + YQ_BINARY="yq_linux_386" + ;; + darwin-x86_64) + YQ_BINARY="yq_darwin_amd64" + ;; + darwin-arm64) + YQ_BINARY="yq_darwin_arm64" + ;; + *) + echo >&2 "[ERROR] Unsupported OS or architecture: $OS-$ARCH" + exit 1 + ;; + esac + + DOWNLOAD_URL="https://github.com/mikefarah/yq/releases/download/v$required_version/$YQ_BINARY" + + # Download yq + curl -L "$DOWNLOAD_URL" -o "$yq_path" + chmod +x "$yq_path" + echo "[NOTICE] bin/yq version $required_version from $DOWNLOAD_URL has been downloaded to $yq_path." >&2 + } - # Check if yq is installed - if ! command -v yq >/dev/null 2>&1; then - echo >&2 "[ERROR] yq is NOT installed. Please install yq version $required_version manually." - echo >&2 "You can download it from the following URL:" - echo >&2 "https://github.com/mikefarah/yq/releases/download/v$required_version/yq_linux_amd64" - exit 1 + # Check if bin/yq is installed in the bin directory + if [ ! -f "$yq_path" ]; then + echo "[WARNING] bin/yq is not found in $yq_path. Downloading..." >&2 + download_yq else - # Check if installed version is not 4.35.1 - installed_version=$(yq --version | grep -oP 'version v\K[0-9.]+') + # Check if installed bin/yq version is the required version + installed_version=$("$yq_path" --version | grep -oP 'version v\K[0-9.]+') if [ "$installed_version" != "$required_version" ]; then - echo >&2 "[ERROR] yq version is $installed_version. Please install yq version $required_version manually." - echo >&2 "You can download it from the following URL:" - echo >&2 "https://github.com/mikefarah/yq/releases/download/v$required_version/yq_linux_amd64" - exit 1 + echo "[WARNING] bin/yq version is $installed_version, which is not the required version $required_version." >&2 + download_yq + else + echo "[NOTICE] bin/yq version $required_version is already installed in $yq_path." >&2 fi fi } + check_gnu_grep_installed() { # Check if grep is installed if ! command -v grep >/dev/null 2>&1; then diff --git a/use-nginx.sh b/use-nginx.sh index 901559d..e2830a0 100644 --- a/use-nginx.sh +++ b/use-nginx.sh @@ -9,20 +9,20 @@ initiate_nginx_docker_compose_file(){ echo "[DEBUG] successfully copied docker-compose-app-nginx-original.yml" } apply_env_service_name_onto_nginx_yaml(){ - yq -i "with(.services; with_entries(select(.key ==\"*-nginx\") | .key |= \"${project_name}-nginx\"))" docker-compose-${project_name}-nginx.yml || (echo "[ERROR] Failed to apply the service name in the Nginx YML as ${project_name}." && exit 1) + bin/yq -i "with(.services; with_entries(select(.key ==\"*-nginx\") | .key |= \"${project_name}-nginx\"))" docker-compose-${project_name}-nginx.yml || (echo "[ERROR] Failed to apply the service name in the Nginx YML as ${project_name}." && exit 1) } apply_ports_onto_nginx_yaml(){ check_yq_installed echo "[NOTICE] PORTS on .env is now being applied to docker-compose-${project_name}-nginx.yml." - yq -i '.services.'${project_name}'-nginx.ports = []' docker-compose-${project_name}-nginx.yml - yq -i '.services.'${project_name}'-nginx.ports += "'${expose_port}':'${expose_port}'"' docker-compose-${project_name}-nginx.yml + bin/yq -i '.services.'${project_name}'-nginx.ports = []' docker-compose-${project_name}-nginx.yml + bin/yq -i '.services.'${project_name}'-nginx.ports += "'${expose_port}':'${expose_port}'"' docker-compose-${project_name}-nginx.yml for i in "${additional_ports[@]}" do [ -z "${i##*[!0-9]*}" ] && (echo "[ERROR] Wrong port number on .env : ${i}" && exit 1); - yq -i '.services.'${project_name}'-nginx.ports += "'$i:$i'"' docker-compose-${project_name}-nginx.yml + bin/yq -i '.services.'${project_name}'-nginx.ports += "'$i:$i'"' docker-compose-${project_name}-nginx.yml done } @@ -57,7 +57,7 @@ apply_docker_compose_volumes_onto_app_nginx_yaml(){ for volume in "${docker_compose_nginx_selective_volumes[@]}" do - yq -i '.services.'${project_name}'-'nginx'.volumes += '${volume}'' ./docker-compose-${project_name}-nginx.yml + bin/yq -i '.services.'${project_name}'-'nginx'.volumes += '${volume}'' ./docker-compose-${project_name}-nginx.yml done }