From 8df891a400454d8e4230e0d72bf9d73972867f03 Mon Sep 17 00:00:00 2001 From: xZero707 Date: Tue, 21 Mar 2023 01:40:07 +0100 Subject: [PATCH] Refactor plugin installer - Fixes issue where installation is dependent of existence of working database connection - Overall improvements - Move out some logic to wp-plugin script - Use curl to download plugins, instead of wp cli --- rootfs/etc/cont-init.d/20-install-plugins | 93 +++++++++++-------- rootfs/usr/local/bin/wp-plugin | 103 ++++++++++++++++++++++ 2 files changed, 158 insertions(+), 38 deletions(-) create mode 100755 rootfs/usr/local/bin/wp-plugin diff --git a/rootfs/etc/cont-init.d/20-install-plugins b/rootfs/etc/cont-init.d/20-install-plugins index 735e84c..0329d3c 100755 --- a/rootfs/etc/cont-init.d/20-install-plugins +++ b/rootfs/etc/cont-init.d/20-install-plugins @@ -14,18 +14,40 @@ function scriptExitHandler() { exit "${LAST_EXIT_CODE}" } -# Check if plugin installed. This is very basic check that doesn't involve database -function isPluginInstalled() { - if [ -d "${PLUGIN_PATH}" ] || [ -f "${PLUGIN_PATH}.php" ]; then - return 0 +# Install plugin +installPlugin() { + ARCHIVE="$(wp-plugin download "${@}" 2>/dev/null)" + if [ -z "${ARCHIVE}" ]; then + return 1 fi - return 1 + + wp-plugin unpack "${@}" + return $? } -# Install plugin -function installPlugin() { - wp plugin install "${@}" >/dev/null 2>&1 - sleep 0.5 +checkInstalled() { + FAILED_COUNT=0 + + for PLUGIN_EXPR in ${PLUGIN_LIST}; do + IFS=':' read -ra PLUGIN <<<"${PLUGIN_EXPR}" + + PLUGIN_SLUG="${PLUGIN[0]}" + + if wp-plugin check "${PLUGIN_SLUG}"; then + echo "> Plugin '${PLUGIN_SLUG}' installed" + continue + fi + + ((FAILED_COUNT = FAILED_COUNT + 1)) + echo "> Warning: Plugin '${PLUGIN_SLUG}' failed to install" + done + + if [ "${FAILED_COUNT}" = "0" ]; then + return 0 + fi + + echo "> Total of ${FAILED_COUNT} plugins failed to install" + return 1 } # Main function @@ -33,8 +55,11 @@ function main() { PLUGIN_LIST="${WORDPRESS_PLUGIN_LIST:-}" PLUGIN_STRICT_INSTALL="${WORDPRESS_PLUGIN_INSTALL_STRICT:-false}" WP_CONTENT_PATH="/var/www/html/wp-content" + WP_PLUGINS_PATH="${WP_CONTENT_PATH}/plugins" CONCURRENCY_LIMIT="${CONCURRENCY_LIMIT:-4}" + export WP_PLUGINS_PATH + echo "> Automated WordPress Plugin Installer" if [ -z "${PLUGIN_LIST}" ]; then echo "> No plugins defined. Skipping installation." @@ -43,24 +68,26 @@ function main() { echo "> About to install defined plugins" for PLUGIN_EXPR in ${PLUGIN_LIST}; do + + # Split plugin name and version IFS=':' read -ra PLUGIN <<<"${PLUGIN_EXPR}" - PLUGIN_PATH="${WP_CONTENT_PATH}/plugins/${PLUGIN[0]}" + PLUGIN_SLUG="${PLUGIN[0]}" + PLUGIN_VERSION="${PLUGIN[1]:-}" - if isPluginInstalled; then - echo "> Plugin '${PLUGIN[0]}' already installed and will be skipped." + if wp-plugin check "${PLUGIN_SLUG}"; then + echo "> Plugin '${PLUGIN_SLUG}' already installed and will be skipped." continue fi - WP_PLUGIN_INSTALL_ARGS="${PLUGIN[0]}" - - if [ -n "${PLUGIN[1]}" ]; then - WP_PLUGIN_INSTALL_ARGS="${WP_PLUGIN_INSTALL_ARGS} --version=${PLUGIN[1]}" + if [ -n "${PLUGIN_VERSION}" ]; then + echo "> Installing plugin '${PLUGIN_SLUG}' version '${PLUGIN_VERSION}'" + installPlugin "${PLUGIN_SLUG}" "${PLUGIN_VERSION}" & + else + echo "> Installing plugin '${PLUGIN_SLUG}'" + installPlugin "${PLUGIN_SLUG}" & fi - echo "> Installing plugin '${PLUGIN[0]}' version '${PLUGIN[1]}'" - installPlugin "${WP_PLUGIN_INSTALL_ARGS}" & - # Run maximum of X plugin installs in parallel while [ "$(jobs | wc -l)" -ge "${CONCURRENCY_LIMIT}" ]; do echo " Waiting for batch of ${CONCURRENCY_LIMIT} plugins to install..." @@ -68,35 +95,25 @@ function main() { done done - echo "> Waiting for all tasks to finish..." wait # Plugins are installed concurrently, so we need to verify if installed, separately echo "> About to verify install of defined plugins" - FAILED_COUNT=0 + if ! checkInstalled; then + echo "> Some plugins failed to install" - for PLUGIN_EXPR in ${PLUGIN_LIST}; do - IFS=':' read -ra PLUGIN <<<"${PLUGIN_EXPR}" - - PLUGIN_PATH="${WP_CONTENT_PATH}/plugins/${PLUGIN[0]}" - - if isPluginInstalled; then - echo "> Plugin '${PLUGIN[0]}' installed" - continue + if [ "${PLUGIN_STRICT_INSTALL}" = "true" ]; then + echo "> WORDPRESS_PLUGIN_INSTALL_STRICT is set to true. Terminating with non-zero exit code" + return 1 fi - ((FAILED_COUNT = FAILED_COUNT + 1)) - echo "> Warning: Plugin '${PLUGIN[0]}' failed to install" - done - - echo "> Total of ${FAILED_COUNT} plugins failed to install" - - if [ "${PLUGIN_STRICT_INSTALL}" = "true" ] && [ ${FAILED_COUNT} != "0" ]; then - echo "> WORDPRESS_PLUGIN_INSTALL_STRICT is set to true. Terminating with non-zero exit code" - return 1 + return 0 fi + + echo "> All plugins installed successfully" + return 0 } main "${@}" diff --git a/rootfs/usr/local/bin/wp-plugin b/rootfs/usr/local/bin/wp-plugin new file mode 100755 index 0000000..d924a6e --- /dev/null +++ b/rootfs/usr/local/bin/wp-plugin @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Download plugin (curl) +# $1 - plugin slug +# $2 - plugin version (optional) +# Returns 0 on success, X on failure +download() { + PLUGIN_SLUG="${1:?download: PLUGIN_SLUG is required}" + PLUGIN_VERSION="${2:-}" + + if [ -n "${PLUGIN_VERSION}" ]; then + PLUGIN_FILENAME="${PLUGIN_SLUG}.${PLUGIN_VERSION}.zip" + else + PLUGIN_FILENAME="${PLUGIN_SLUG}.zip" + fi + + curl --fail -gsO "https://downloads.wordpress.org/plugin/${PLUGIN_FILENAME}" || return $? + echo "${PLUGIN_FILENAME}" + return 0 +} + +# Unpack plugin (unzip) +# $1 - plugin slug +# $2 - plugin version (optional) +# $3 - target directory (optional) +# Returns 0 on success, 1 on failure +unpack() { + TARGET_PLUGINS_DIR="${TARGET_PLUGINS_DIR:?check: TARGET_PLUGINS_DIR is required}" + PLUGIN_SLUG="${1:?unpack: PLUGIN_SLUG is required}" + PLUGIN_VERSION="${2:-}" + + if [ -n "${PLUGIN_VERSION}" ]; then + PLUGIN_FILENAME="${PLUGIN_SLUG}.${PLUGIN_VERSION}.zip" + else + PLUGIN_FILENAME="${PLUGIN_SLUG}.zip" + fi + + if [ -f "${PLUGIN_FILENAME}" ]; then + unzip -qq -d "${TARGET_PLUGINS_DIR}" "${PLUGIN_FILENAME}" || return $? + rm "${PLUGIN_FILENAME}" -f + return 0 + fi + return 1 +} + +# Check if plugin is installed +# $1 - plugin slug +# Returns 0 if plugin is installed, 1 otherwise +check() { + TARGET_PLUGINS_DIR="${TARGET_PLUGINS_DIR:?check: TARGET_PLUGINS_DIR is required}" + PLUGIN_SLUG="${1:?check: PLUGIN_SLUG is required}" + + PLUGIN_PATH="${TARGET_PLUGINS_DIR}/${PLUGIN_SLUG}" + + # Check if plugin directory exists + if [ ! -d "${PLUGIN_PATH}" ]; then + return 1 + fi + + # Check if plugin file exists - if yes, plugin is probably installed successfully + if [ -f "${PLUGIN_PATH}/${PLUGIN_SLUG}.php" ]; then + return 0 + fi + + # Check if plugin directory is empty - if not, plugin is probably installed successfully + if [ "$(ls -A "${PLUGIN_PATH}")" ]; then + return 0 + fi + + # If we got here, then plugin is not installed + return 1 +} + +# Main function +main() { + COMMAND="${1:?COMMAND is required}" + TARGET_PLUGINS_DIR="${WP_PLUGINS_PATH:?WP_PLUGINS_PATH is required}" + + export TARGET_PLUGINS_DIR + + # Execute command by calling function with the same name + case "${COMMAND}" in + download) + download "${@:2}" + return $? + ;; + unpack) + unpack "${@:2}" + return $? + ;; + check) + check "${@:2}" + return $? + ;; + *) + echo "Error: Unknown command '${COMMAND}'" + return 1 + ;; + esac +} + +main "${@}" +exit $?