Merge pull request #180 from WordOps/updating-configuration

Updating configuration
This commit is contained in:
VirtuBox
2019-10-18 21:59:50 +02:00
committed by GitHub
26 changed files with 349 additions and 286 deletions

4
.gitattributes vendored
View File

@@ -2,11 +2,11 @@
* text=auto * text=auto
# Documents # Documents
*.md text *.md text eol=lf
*.tex text diff=tex *.tex text diff=tex
*.adoc text *.adoc text
*.textile text *.textile text
*.mustache text *.mustache text eol=lf
*.csv text *.csv text
*.tab text *.tab text
*.tsv text *.tsv text

View File

@@ -28,7 +28,6 @@ before_script:
after_script: after_script:
- sudo cat /var/log/wo/install.log | ccze -A -p syslog
- sudo bash install --purge - sudo bash install --purge

View File

@@ -8,7 +8,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### v3.9.x - [Unreleased] ### v3.9.x - [Unreleased]
### v3.9.9.3 - [Unreleased] ### v3.9.9.4 - 2019-10-18
#### Changed
- [STACK] New Nginx package built with libbrotli-dev for all linux distro supported by WordOps
#### Fixed
- GPG keys error with previous EasyEngine Nginx repository
- Issue with `--ngxblocker` stack removal/purge
- Install/Update issues with python3 setup.py
- WordOps deploying SSL certificate even if acme.sh failed
### v3.9.9.3 - 2019-10-15
#### Added #### Added

160
install
View File

@@ -9,7 +9,7 @@
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# wget -qO wo wops.cc && sudo bash wo # wget -qO wo wops.cc && sudo bash wo
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Version 3.9.9.3 - 2019-10-14 # Version 3.9.9.4 - 2019-10-18
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# CONTENTS # CONTENTS
@@ -119,39 +119,6 @@ _run() {
} }
###
# 1- Update the apt sewers with fresh info
###
if [ -z "$wo_travis" ]; then
if ! {
apt-get update --allow-releaseinfo-change -qq > /dev/null 2>&1
}; then
apt-get update -qq > /dev/null 2>&1
fi
if ! command_exists curl; then
apt-get -y install curl -qq > /dev/null 2>&1
fi
fi
if [ -f ./setup.py ]; then
readonly wo_version_new=$(grep "version='" setup.py | awk -F "'" '{print$2}' 2>&1)
else
readonly wo_version_new=$(curl -sL https://wops.cc/setup.py 2>&1 | grep "version='" | awk -F "'" '{print$2}' 2>&1)
fi
echo ""
wo_lib_echo "Welcome to WordOps install/update script v${wo_version_new}"
echo ""
###
# 1- Check whether lsb_release is installed, and if not, install it
###
if ! command_exists lsb_release; then
apt-get install lsb-release -qq
fi
### ###
# 1 - Define variables for later use # 1 - Define variables for later use
### ###
@@ -162,8 +129,6 @@ readonly wo_log_dir=/var/log/wo/
readonly wo_backup_dir=/var/lib/wo-backup/ readonly wo_backup_dir=/var/lib/wo-backup/
readonly wo_tmp_dir=/var/lib/wo/tmp readonly wo_tmp_dir=/var/lib/wo/tmp
readonly wo_install_log=/var/log/wo/install.log readonly wo_install_log=/var/log/wo/install.log
readonly wo_linux_distro=$(lsb_release -is)
readonly wo_distro_version=$(lsb_release -sc)
readonly TIME_FORMAT='%d-%b-%Y-%H%M%S' readonly TIME_FORMAT='%d-%b-%Y-%H%M%S'
readonly TIME=$(date +"$TIME_FORMAT") readonly TIME=$(date +"$TIME_FORMAT")
readonly NGINX_BACKUP_FILE="/var/lib/wo-backup/nginx-backup.$TIME.tar.gz" readonly NGINX_BACKUP_FILE="/var/lib/wo-backup/nginx-backup.$TIME.tar.gz"
@@ -171,43 +136,55 @@ readonly EE_BACKUP_FILE="/var/lib/wo-backup/ee-backup.$TIME.tar.gz"
readonly WO_BACKUP_FILE="/var/lib/wo-backup/wo-backup.$TIME.tar.gz" readonly WO_BACKUP_FILE="/var/lib/wo-backup/wo-backup.$TIME.tar.gz"
readonly wo_lxc=$(grep "container=lxc" /proc/1/environ) readonly wo_lxc=$(grep "container=lxc" /proc/1/environ)
readonly wo_wsl=$(grep "wsl" /proc/1/environ) readonly wo_wsl=$(grep "wsl" /proc/1/environ)
WO_ARCH="$(uname -m)" readonly wo_arch="$(uname -m)"
if [ -x /usr/local/bin/ee ]; then if [ -x /usr/local/bin/ee ]; then
ee_migration=1 ee_migration=1
elif [ -x /usr/local/bin/wo ]; then elif [ -x /usr/local/bin/wo ]; then
wo_upgrade=1 wo_upgrade=1
fi fi
### ###
# 1 - Checking linux distro # 1 - Checking linux distro
### ###
if [ -z "$wo_force_install" ]; then
if [ "$wo_linux_distro" != "Ubuntu" ] && [ "$wo_linux_distro" != "Debian" ] && [ "$wo_linux_distro" != "Raspbian" ]; then wo_check_distro() {
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu, Debian & Raspbian at the moment." local wo_linux_distro
wo_lib_echo_fail "If you are feeling adventurous, you are free to fork WordOps to support" wo_linux_distro=$(lsb_release -is)
wo_lib_echo_fail "other Linux distributions and perhaps even Unix deratives." local wo_distro_version
exit 100 wo_distro_version=$(lsb_release -sc)
else if [ -z "$wo_force_install" ]; then
check_wo_linux_distro=$(lsb_release -sc | grep -E "xenial|bionic|disco|jessie|stretch|buster") if [ "$wo_linux_distro" != "Ubuntu" ] && [ "$wo_linux_distro" != "Debian" ] && [ "$wo_linux_distro" != "Raspbian" ]; then
if [ -z "$check_wo_linux_distro" ]; then wo_lib_echo_fail "WordOps (wo) only supports Ubuntu, Debian & Raspbian at the moment."
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu 16.04/18.04/19.04 LTS, Debian 9.x/10.x and Raspbian 9.x/10x" wo_lib_echo_fail "If you are feeling adventurous, you are free to fork WordOps to support"
wo_lib_echo_fail "other Linux distributions and perhaps even Unix deratives."
exit 100 exit 100
else
check_wo_linux_distro=$(lsb_release -sc | grep -E "xenial|bionic|disco|jessie|stretch|buster")
if [ -z "$check_wo_linux_distro" ]; then
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu 16.04/18.04/19.04 LTS, Debian 9.x/10.x and Raspbian 9.x/10x"
exit 100
fi
fi fi
fi fi
fi
}
### ###
# 1 - To prevent errors or unexpected behaviour, create the log and ACL it # 1 - To prevent errors or unexpected behaviour, create the log and ACL it
### ###
if [ ! -d "$wo_log_dir" ] || [ ! -d "$wo_backup_dir" ] || [ ! -d "$wo_tmp_dir" ]; then wo_dir_init() {
if [ ! -d "$wo_log_dir" ] || [ ! -d "$wo_backup_dir" ] || [ ! -d "$wo_tmp_dir" ]; then
mkdir -p "$wo_backup_dir" "$wo_log_dir" "$wo_tmp_dir" || wo_lib_error "Whoops - seems we are unable to create the log directory $wo_log_dir, exit status " $? mkdir -p "$wo_backup_dir" "$wo_log_dir" "$wo_tmp_dir" || wo_lib_error "Whoops - seems we are unable to create the log directory $wo_log_dir, exit status " $?
# create wordops log files # create wordops log files
touch /var/log/wo/{wordops.log,install.log} touch /var/log/wo/{wordops.log,install.log}
chmod -R 700 "$wo_log_dir" "$wo_backup_dir" "$wo_tmp_dir" || wo_lib_error "Whoops, there was an error setting the permissions on the WordOps log folder, exit status " $? chmod -R 700 "$wo_log_dir" "$wo_backup_dir" "$wo_tmp_dir" || wo_lib_error "Whoops, there was an error setting the permissions on the WordOps log folder, exit status " $?
fi fi
}
### ###
# 2 - Setup the dependencies for installation # 2 - Setup the dependencies for installation
@@ -219,12 +196,14 @@ wo_dist_upgrade() {
} }
wo_install_dep() { wo_install_dep() {
local wo_linux_distro
wo_linux_distro=$(lsb_release -is)
if [ "$wo_linux_distro" == "Ubuntu" ]; then if [ "$wo_linux_distro" == "Ubuntu" ]; then
# install dependencies # install dependencies
apt-get -option=Dpkg::options::=--force-confmiss --option=Dpkg::options::=--force-confold --assume-yes install \ apt-get -option=Dpkg::options::=--force-confmiss --option=Dpkg::options::=--force-confold --assume-yes install \
build-essential curl gzip python3-pip python3-wheel python3-apt python3-setuptools python3-dev sqlite3 git tar software-properties-common pigz \ build-essential curl gzip python3-pip python3-wheel python3-apt python3-setuptools python3-dev sqlite3 git tar software-properties-common pigz \
gnupg2 cron ccze rsync apt-transport-https tree haveged ufw unattended-upgrades tzdata ntp > /dev/null 2>&1 gnupg2 cron ccze rsync apt-transport-https tree haveged ufw unattended-upgrades tzdata ntp > /dev/null 2>&1
curl -sL https://download.opensuse.org/repositories/home:/virtubox:/WordOps/xUbuntu_18.04/Release.key | apt-key add -
add-apt-repository ppa:wordops/nginx-wo -yn add-apt-repository ppa:wordops/nginx-wo -yn
else else
# install dependencies # install dependencies
@@ -462,6 +441,7 @@ wo_download() {
curl -sL https://github.com/WordOps/WordOps/archive/v${wo_version}.tar.gz | tar -I pigz -xf - -C /var/lib/wo/tmp curl -sL https://github.com/WordOps/WordOps/archive/v${wo_version}.tar.gz | tar -I pigz -xf - -C /var/lib/wo/tmp
mv "/var/lib/wo/tmp/WordOps-$wo_version" /var/lib/wo/tmp/WordOps-install mv "/var/lib/wo/tmp/WordOps-$wo_version" /var/lib/wo/tmp/WordOps-install
fi fi
return 0
} }
# WordOps install # WordOps install
@@ -487,6 +467,10 @@ wo_travis_install() {
} }
wo_upgrade_nginx() { wo_upgrade_nginx() {
local wo_linux_distro
wo_linux_distro=$(lsb_release -is)
local wo_distro_version
wo_distro_version=$(lsb_release -sc)
if [ -d /var/lib/wo-backup/nginx ]; then if [ -d /var/lib/wo-backup/nginx ]; then
/bin/tar -I pigz "$NGINX_BACKUP_FILE" /var/lib/wo-backup/nginx /bin/tar -I pigz "$NGINX_BACKUP_FILE" /var/lib/wo-backup/nginx
@@ -620,8 +604,9 @@ wo_remove_ee_cron() {
} }
wo_tweak_kernel() { wo_tweak_kernel() {
local wo_distro_version
if [ "$WO_ARCH" = "x86_64" ] && [ -z "$wo_lxc" ] && [ -z "$wo_wsl" ]; then wo_distro_version=$(lsb_release -sc)
if [ "$wo_arch" = "x86_64" ] && [ -z "$wo_lxc" ] && [ -z "$wo_wsl" ]; then
rm -f /etc/sysctl.d/60-ubuntu-nginx-web-server.conf rm -f /etc/sysctl.d/60-ubuntu-nginx-web-server.conf
wget -qO /etc/sysctl.d/60-wo-tweaks.conf https://raw.githubusercontent.com/WordOps/WordOps/"$wo_branch"/wo/cli/templates/sysctl.mustache wget -qO /etc/sysctl.d/60-wo-tweaks.conf https://raw.githubusercontent.com/WordOps/WordOps/"$wo_branch"/wo/cli/templates/sysctl.mustache
if [ "$wo_distro_version" = "bionic" ] || [ "$wo_distro_version" = "disco" ] || [ "$wo_distro_version" = "buster" ]; then if [ "$wo_distro_version" = "bionic" ] || [ "$wo_distro_version" = "disco" ] || [ "$wo_distro_version" = "buster" ]; then
@@ -680,12 +665,12 @@ wo_nginx_tweak() {
} }
wo_clean() { wo_clean() {
rm -rf /usr/local/lib/python3.*/dist-packages/wo-* rm -rf /usr/local/lib/python3.*/dist-packages/wo-* /usr/local/lib/python3.*/dist-packages/wordops-*
} }
wo_uninstall() { wo_uninstall() {
python3 -m pip uninstall wordops -y rm -rf /usr/local/lib/python3.*/dist-packages/{pystache-*,cement-2.*,wo-*,wordops-*} /usr/local/bin/wo /etc/bash_completion.d/wo_auto.rc /var/lib/wo /etc/wo /usr/lib/wo/templates
rm -rf /usr/local/lib/python3.*/dist-packages/{pystache-*,cement-2.*,wo-*} /usr/local/bin/wo /etc/bash_completion.d/wo_auto.rc /var/lib/wo /etc/wo /usr/lib/wo/templates
} }
wo_cheat_install() { wo_cheat_install() {
@@ -698,6 +683,56 @@ wo_cheat_install() {
curl -sL https://cheat.sh/:bash_completion > /etc/bash_completion.d/cht.sh curl -sL https://cheat.sh/:bash_completion > /etc/bash_completion.d/cht.sh
} }
wo_clean_repo() {
# remove old EasyEngine Nginx repository
if [ -f /etc/apt/sources.list.d/ee-repo.list ]; then
cp -f /etc/apt/sources.list.d/ee-repo.list /etc/apt/sources.list.d/ee-repo.list.save
grep -v "/home:/rtCamp:/EasyEngine" /etc/apt/sources.list.d/ee-repo.list.save > /etc/apt/sources.list.d/ee-repo.list
fi
if [ -f /etc/apt/sources.list.d/wo-repo.list ]; then
local wo_linux_distro
wo_linux_distro=$(lsb_release -is)
cp -f /etc/apt/sources.list.d/wo-repo.list /etc/apt/sources.list.d/wo-repo.list.save
if [ "$wo_linux_distro" = "Ubuntu" ]; then
grep -v "opensuse" /etc/apt/sources.list.d/wo-repo.list.save > /etc/apt/sources.list.d/wo-repo.list
else
grep -v "/home:/rtCamp:/EasyEngine" /etc/apt/sources.list.d/wo-repo.list.save > /etc/apt/sources.list.d/wo-repo.list
fi
fi
}
wo_init() {
###
# 1- Update the apt sewers with fresh info
###
if [ -z "$wo_travis" ]; then
if ! {
apt-get update --allow-releaseinfo-change -qq > /dev/null 2>&1
}; then
apt-get update -qq > /dev/null 2>&1
fi
if ! command_exists curl; then
apt-get -y install curl -qq > /dev/null 2>&1
fi
if ! command_exists lsb_release; then
apt-get install lsb-release -qq
fi
fi
if [ -f ./setup.py ]; then
readonly wo_version_new=$(grep "version='" setup.py | awk -F "'" '{print$2}' 2>&1)
else
readonly wo_version_new=$(curl -sL https://wops.cc/setup.py 2>&1 | grep "version='" | awk -F "'" '{print$2}' 2>&1)
fi
echo ""
wo_lib_echo "Welcome to WordOps install/update script v${wo_version_new}"
echo ""
}
### ###
# 4 - WO MAIN SETUP # 4 - WO MAIN SETUP
### ###
@@ -709,6 +744,10 @@ if [ "$wo_purge" = "y" ]; then
wo_lib_echo "The WordOps backup files can be found in $WO_BACKUP_FILE" wo_lib_echo "The WordOps backup files can be found in $WO_BACKUP_FILE"
exit 0 exit 0
else else
wo_clean_repo
wo_init
wo_check_distro
wo_dir_init
# 1 - WO already installed # 1 - WO already installed
if [ -x /usr/local/bin/wo ]; then if [ -x /usr/local/bin/wo ]; then
if [ -z "$wo_force_install" ]; then if [ -z "$wo_force_install" ]; then
@@ -734,7 +773,6 @@ else
_run wo_timesync _run wo_timesync
# skip steps if travis # skip steps if travis
if [ -z "$wo_travis" ]; then if [ -z "$wo_travis" ]; then
_run wo_dist_upgrade
_run wo_download "Downloading WordOps" _run wo_download "Downloading WordOps"
wo_git_config wo_git_config
_run wo_install "Installing WordOps" _run wo_install "Installing WordOps"

View File

@@ -4,8 +4,11 @@ import os
from setuptools import find_packages, setup from setuptools import find_packages, setup
with open("README.md", "r", encoding="utf-8") as fh:
LONG = fh.read() # read the contents of your README file
this_directory = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
LONG = f.read()
conf = [] conf = []
templates = [] templates = []
@@ -24,9 +27,10 @@ if os.geteuid() == 0:
os.makedirs('/var/lib/wo/tmp/') os.makedirs('/var/lib/wo/tmp/')
setup(name='wordops', setup(name='wordops',
version='3.9.9.3', version='3.9.9.4',
description='WordPress & server administration toolset', description='WordPress & server administration toolset',
long_description=LONG, long_description=LONG,
long_description_content_type='text/markdown',
classifiers=[ classifiers=[
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",

View File

@@ -145,7 +145,7 @@ if [ -z "$1" ]; then
echo -e "${CGREEN}#############################################${CEND}" echo -e "${CGREEN}#############################################${CEND}"
echo -e ' wo stack upgrade ' echo -e ' wo stack upgrade '
echo -e "${CGREEN}#############################################${CEND}" echo -e "${CGREEN}#############################################${CEND}"
stack_upgrade='nginx php mysql redis netdata dashboard phpmyadmin' stack_upgrade='nginx php php73 mysql redis netdata dashboard phpmyadmin composer'
for stack in $stack_upgrade; do for stack in $stack_upgrade; do
echo -ne " Upgrading $stack [..]\r" echo -ne " Upgrading $stack [..]\r"
if { if {
@@ -229,7 +229,7 @@ wo site info wp.net
echo -e "${CGREEN}#############################################${CEND}" echo -e "${CGREEN}#############################################${CEND}"
echo -e ' wo stack purge ' echo -e ' wo stack purge '
echo -e "${CGREEN}#############################################${CEND}" echo -e "${CGREEN}#############################################${CEND}"
stack_purge='nginx php php73 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis ufw' stack_purge='nginx php php73 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis ufw ngxblocker'
for stack in $stack_purge; do for stack in $stack_purge; do
echo -ne " purging $stack [..]\r" echo -ne " purging $stack [..]\r"
if { if {

View File

@@ -3,7 +3,6 @@
# All built-in application controllers should be imported, and registered # All built-in application controllers should be imported, and registered
# in this file in the same way as WOBaseController. # in this file in the same way as WOBaseController.
from cement.core import handler
from wo.cli.controllers.base import WOBaseController from wo.cli.controllers.base import WOBaseController

View File

@@ -3,7 +3,6 @@
import os import os
import urllib.request import urllib.request
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.aptget import WOAptGet from wo.core.aptget import WOAptGet

View File

@@ -5,7 +5,6 @@ import glob
import os import os
import signal import signal
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from pynginxconfig import NginxConfig from pynginxconfig import NginxConfig

View File

@@ -1,4 +1,3 @@
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.logging import Log from wo.core.logging import Log

View File

@@ -3,7 +3,6 @@
import configparser import configparser
import os import os
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from pynginxconfig import NginxConfig from pynginxconfig import NginxConfig
@@ -80,20 +79,20 @@ class WOInfoController(CementBaseController):
max_execution_time = config['PHP']['max_execution_time'] max_execution_time = config['PHP']['max_execution_time']
config.read('/etc/{0}/fpm/pool.d/www.conf'.format("php/7.2")) config.read('/etc/{0}/fpm/pool.d/www.conf'.format("php/7.2"))
www_listen = config['www']['listen'] www_listen = config['www-php72']['listen']
www_ping_path = config['www']['ping.path'] www_ping_path = config['www-php72']['ping.path']
www_pm_status_path = config['www']['pm.status_path'] www_pm_status_path = config['www-php72']['pm.status_path']
www_pm = config['www']['pm'] www_pm = config['www-php72']['pm']
www_pm_max_requests = config['www']['pm.max_requests'] www_pm_max_requests = config['www-php72']['pm.max_requests']
www_pm_max_children = config['www']['pm.max_children'] www_pm_max_children = config['www-php72']['pm.max_children']
www_pm_start_servers = config['www']['pm.start_servers'] www_pm_start_servers = config['www-php72']['pm.start_servers']
www_pm_min_spare_servers = config['www']['pm.min_spare_servers'] www_pm_min_spare_servers = config['www-php72']['pm.min_spare_servers']
www_pm_max_spare_servers = config['www']['pm.max_spare_servers'] www_pm_max_spare_servers = config['www-php72']['pm.max_spare_servers']
www_request_terminate_time = (config['www'] www_request_terminate_time = (config['www-php72']
['request_terminate_timeout']) ['request_terminate_timeout'])
try: try:
www_xdebug = (config['www']['php_admin_flag[xdebug.profiler_enable' www_xdebug = (config['www-php72']['php_admin_flag[xdebug.profiler_enable'
'_trigger]']) '_trigger]'])
except Exception as e: except Exception as e:
Log.debug(self, "{0}".format(e)) Log.debug(self, "{0}".format(e))
www_xdebug = 'off' www_xdebug = 'off'
@@ -157,20 +156,21 @@ class WOInfoController(CementBaseController):
max_execution_time = config['PHP']['max_execution_time'] max_execution_time = config['PHP']['max_execution_time']
config.read('/etc/php/7.3/fpm/pool.d/www.conf') config.read('/etc/php/7.3/fpm/pool.d/www.conf')
www_listen = config['www']['listen'] www_listen = config['www-php73']['listen']
www_ping_path = config['www']['ping.path'] www_ping_path = config['www-php73']['ping.path']
www_pm_status_path = config['www']['pm.status_path'] www_pm_status_path = config['www-php73']['pm.status_path']
www_pm = config['www']['pm'] www_pm = config['www-php73']['pm']
www_pm_max_requests = config['www']['pm.max_requests'] www_pm_max_requests = config['www-php73']['pm.max_requests']
www_pm_max_children = config['www']['pm.max_children'] www_pm_max_children = config['www-php73']['pm.max_children']
www_pm_start_servers = config['www']['pm.start_servers'] www_pm_start_servers = config['www-php73']['pm.start_servers']
www_pm_min_spare_servers = config['www']['pm.min_spare_servers'] www_pm_min_spare_servers = config['www-php73']['pm.min_spare_servers']
www_pm_max_spare_servers = config['www']['pm.max_spare_servers'] www_pm_max_spare_servers = config['www-php73']['pm.max_spare_servers']
www_request_terminate_time = (config['www'] www_request_terminate_time = (config['www-php73']
['request_terminate_timeout']) ['request_terminate_timeout'])
try: try:
www_xdebug = (config['www']['php_admin_flag[xdebug.profiler_enable' www_xdebug = (config['www-php73']
'_trigger]']) ['php_admin_flag[xdebug.profiler_enable'
'_trigger]'])
except Exception as e: except Exception as e:
Log.debug(self, "{0}".format(e)) Log.debug(self, "{0}".format(e))
www_xdebug = 'off' www_xdebug = 'off'

View File

@@ -4,7 +4,6 @@ import glob
import gzip import gzip
import os import os
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.cli.plugins.site_functions import logwatch from wo.cli.plugins.site_functions import logwatch

View File

@@ -1,6 +1,5 @@
"""Maintenance Plugin for WordOps""" """Maintenance Plugin for WordOps"""
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.aptget import WOAptGet from wo.core.aptget import WOAptGet

View File

@@ -1,8 +1,8 @@
import getpass import getpass
import os import os
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.fileutils import WOFileUtils from wo.core.fileutils import WOFileUtils
from wo.core.git import WOGit from wo.core.git import WOGit
from wo.core.logging import Log from wo.core.logging import Log

View File

@@ -3,7 +3,6 @@ import json
import os import os
import subprocess import subprocess
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.cli.plugins.site_functions import * from wo.cli.plugins.site_functions import *
from wo.cli.plugins.sitedb import (addNewSite, deleteSiteInfo, getAllsites, from wo.cli.plugins.sitedb import (addNewSite, deleteSiteInfo, getAllsites,

View File

@@ -2,11 +2,8 @@
import os import os
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.cli.plugins.site_functions import *
from wo.cli.plugins.sitedb import *
from wo.cli.plugins.stack_migrate import WOStackMigrateController from wo.cli.plugins.stack_migrate import WOStackMigrateController
from wo.cli.plugins.stack_pref import post_pref, pre_pref from wo.cli.plugins.stack_pref import post_pref, pre_pref
from wo.cli.plugins.stack_services import WOStackStatusController from wo.cli.plugins.stack_services import WOStackStatusController
@@ -343,21 +340,22 @@ class WOStackController(CementBaseController):
"adminer/index.php" "adminer/index.php"
.format(wo_webroot)): .format(wo_webroot)):
Log.debug(self, "Setting packages variable for Adminer ") Log.debug(self, "Setting packages variable for Adminer ")
packages = packages + [["https://github.com/vrana/adminer/" packages = packages + [[
"releases/download/v{0}" "https://github.com/vrana/adminer/"
"/adminer-{0}.php" "releases/download/v{0}"
.format(WOVar.wo_adminer), "/adminer-{0}.php"
"{0}22222/" .format(WOVar.wo_adminer),
"htdocs/db/adminer/index.php" "{0}22222/"
.format(WOVar.wo_webroot), "htdocs/db/adminer/index.php"
"Adminer"], .format(WOVar.wo_webroot),
["https://raw.githubusercontent.com" "Adminer"],
"/vrana/adminer/master/designs/" ["https://raw.githubusercontent.com"
"pepa-linha/adminer.css", "/vrana/adminer/master/designs/"
"{0}22222/" "pepa-linha/adminer.css",
"htdocs/db/adminer/adminer.css" "{0}22222/"
.format(WOVar.wo_webroot), "htdocs/db/adminer/adminer.css"
"Adminer theme"]] .format(WOVar.wo_webroot),
"Adminer theme"]]
else: else:
Log.debug(self, "Adminer already installed") Log.debug(self, "Adminer already installed")
Log.info(self, "Adminer already installed") Log.info(self, "Adminer already installed")
@@ -402,14 +400,14 @@ class WOStackController(CementBaseController):
if not os.path.isfile('/var/www/22222/htdocs/index.php'): if not os.path.isfile('/var/www/22222/htdocs/index.php'):
Log.debug(self, Log.debug(self,
"Setting packages variable for WO-Dashboard") "Setting packages variable for WO-Dashboard")
packages = \ packages = packages + [[
packages + [["https://github.com/WordOps" "https://github.com/WordOps"
"/wordops-dashboard/" "/wordops-dashboard/"
"releases/download/v{0}/" "releases/download/v{0}/"
"wordops-dashboard.tar.gz" "wordops-dashboard.tar.gz"
.format(WOVar.wo_dashboard), .format(WOVar.wo_dashboard),
"/var/lib/wo/tmp/wo-dashboard.tar.gz", "/var/lib/wo/tmp/wo-dashboard.tar.gz",
"WordOps Dashboard"]] "WordOps Dashboard"]]
else: else:
Log.debug(self, "WordOps dashboard already installed") Log.debug(self, "WordOps dashboard already installed")
Log.info(self, "WordOps dashboard already installed") Log.info(self, "WordOps dashboard already installed")
@@ -444,43 +442,44 @@ class WOStackController(CementBaseController):
# UTILS # UTILS
if pargs.utils: if pargs.utils:
Log.debug(self, "Setting packages variable for utils") Log.debug(self, "Setting packages variable for utils")
packages = packages + [["https://raw.githubusercontent.com" packages = packages + [[
"/rtCamp/eeadmin/master/cache/nginx/" "https://raw.githubusercontent.com"
"clean.php", "/rtCamp/eeadmin/master/cache/nginx/"
"{0}22222/htdocs/cache/" "clean.php",
"nginx/clean.php" "{0}22222/htdocs/cache/"
.format(WOVar.wo_webroot), "nginx/clean.php"
"clean.php"], .format(WOVar.wo_webroot),
["https://raw.github.com/rlerdorf/" "clean.php"],
"opcache-status/master/opcache.php", ["https://raw.github.com/rlerdorf/"
"{0}22222/htdocs/cache/" "opcache-status/master/opcache.php",
"opcache/opcache.php" "{0}22222/htdocs/cache/"
.format(WOVar.wo_webroot), "opcache/opcache.php"
"opcache.php"], .format(WOVar.wo_webroot),
["https://raw.github.com/amnuts/" "opcache.php"],
"opcache-gui/master/index.php", ["https://raw.github.com/amnuts/"
"{0}22222/htdocs/" "opcache-gui/master/index.php",
"cache/opcache/opgui.php" "{0}22222/htdocs/"
.format(WOVar.wo_webroot), "cache/opcache/opgui.php"
"Opgui"], .format(WOVar.wo_webroot),
["https://raw.githubusercontent.com/" "Opgui"],
"mlazarov/ocp/master/ocp.php", ["https://raw.githubusercontent.com/"
"{0}22222/htdocs/cache/" "mlazarov/ocp/master/ocp.php",
"opcache/ocp.php" "{0}22222/htdocs/cache/"
.format(WOVar.wo_webroot), "opcache/ocp.php"
"OCP.php"], .format(WOVar.wo_webroot),
["https://github.com/jokkedk/webgrind/" "OCP.php"],
"archive/master.tar.gz", ["https://github.com/jokkedk/webgrind/"
'/var/lib/wo/tmp/webgrind.tar.gz', "archive/master.tar.gz",
'Webgrind'], '/var/lib/wo/tmp/webgrind.tar.gz',
["https://www.percona.com/" 'Webgrind'],
"get/pt-query-digest", ["https://www.percona.com/"
"/usr/bin/pt-query-advisor", "get/pt-query-digest",
"pt-query-advisor"], "/usr/bin/pt-query-advisor",
["https://github.com/box/Anemometer/" "pt-query-advisor"],
"archive/master.tar.gz", ["https://github.com/box/Anemometer/"
'/var/lib/wo/tmp/anemometer.tar.gz', "archive/master.tar.gz",
'Anemometer']] '/var/lib/wo/tmp/anemometer.tar.gz',
'Anemometer']]
except Exception as e: except Exception as e:
Log.debug(self, "{0}".format(e)) Log.debug(self, "{0}".format(e))
@@ -536,7 +535,7 @@ class WOStackController(CementBaseController):
(not pargs.adminer) and (not pargs.utils) and (not pargs.adminer) and (not pargs.utils) and
(not pargs.redis) and (not pargs.proftpd) and (not pargs.redis) and (not pargs.proftpd) and
(not pargs.extplorer) and (not pargs.clamav) and (not pargs.extplorer) and (not pargs.clamav) and
(not pargs.ufw) and (not pargs.ufw) and (not pargs.ngxblocker) and
(not pargs.phpredisadmin) and (not pargs.sendmail) and (not pargs.phpredisadmin) and (not pargs.sendmail) and
(not pargs.php73)): (not pargs.php73)):
pargs.web = True pargs.web = True
@@ -570,6 +569,7 @@ class WOStackController(CementBaseController):
pargs.fail2ban = True pargs.fail2ban = True
pargs.clamav = True pargs.clamav = True
pargs.ufw = True pargs.ufw = True
pargs.ngxblocker = True
# NGINX # NGINX
if pargs.nginx: if pargs.nginx:
@@ -700,12 +700,14 @@ class WOStackController(CementBaseController):
'{0}22222/htdocs/db/anemometer' '{0}22222/htdocs/db/anemometer'
.format(WOVar.wo_webroot)] .format(WOVar.wo_webroot)]
# netdata
if pargs.netdata: if pargs.netdata:
Log.debug(self, "Removing Netdata") Log.debug(self, "Removing Netdata")
if os.path.isfile('/opt/netdata/usr/' if os.path.isfile('/opt/netdata/usr/'
'libexec/netdata/netdata-uninstaller.sh'): 'libexec/netdata/netdata-uninstaller.sh'):
packages = packages + ['/var/lib/wo/tmp/kickstart.sh'] packages = packages + ['/var/lib/wo/tmp/kickstart.sh']
# wordops dashboard
if pargs.dashboard: if pargs.dashboard:
if (os.path.isfile('{0}22222/htdocs/index.php' if (os.path.isfile('{0}22222/htdocs/index.php'
.format(WOVar.wo_webroot)) or .format(WOVar.wo_webroot)) or
@@ -718,6 +720,16 @@ class WOStackController(CementBaseController):
.format(WOVar.wo_webroot), .format(WOVar.wo_webroot),
'{0}22222/htdocs/index.html' '{0}22222/htdocs/index.html'
.format(WOVar.wo_webroot)] .format(WOVar.wo_webroot)]
# ngxblocker
if pargs.ngxblocker:
if os.path.isfile('/usr/local/sbin/setup-ngxblocker'):
packages = packages + [
'/usr/local/sbin/setup-ngxblocker',
'/usr/local/sbin/install-ngxblocker',
'/usr/local/sbin/update-ngxblocker',
'/etc/nginx/conf.d/globalblacklist.conf',
'/etc/nginx/conf.d/botblocker-nginx-settings.conf',
'/etc/nginx/bots.d']
if (packages) or (apt_packages): if (packages) or (apt_packages):
if (not pargs.force): if (not pargs.force):
@@ -740,14 +752,16 @@ class WOStackController(CementBaseController):
if (set(['/var/lib/wo/tmp/' if (set(['/var/lib/wo/tmp/'
'kickstart.sh']).issubset(set(packages))): 'kickstart.sh']).issubset(set(packages))):
if WOVar.wo_distro == 'Raspbian': if WOVar.wo_distro == 'Raspbian':
WOShellExec.cmd_exec(self, "bash /usr/" WOShellExec.cmd_exec(
"libexec/netdata/" self, "bash /usr/"
"netdata-uninstaller.sh -y -f") "libexec/netdata/"
"netdata-uninstaller.sh -y -f")
else: else:
WOShellExec.cmd_exec(self, "bash /opt/netdata/usr/" WOShellExec.cmd_exec(
"libexec/netdata/" self, "bash /opt/netdata/usr/"
"netdata-uninstaller.sh - y - f", "libexec/netdata/"
errormsg='', log=False) "netdata-uninstaller.sh - y - f",
errormsg='', log=False)
if (packages): if (packages):
Log.wait(self, "Removing packages ") Log.wait(self, "Removing packages ")
@@ -779,7 +793,7 @@ class WOStackController(CementBaseController):
(not pargs.adminer) and (not pargs.utils) and (not pargs.adminer) and (not pargs.utils) and
(not pargs.redis) and (not pargs.proftpd) and (not pargs.redis) and (not pargs.proftpd) and
(not pargs.extplorer) and (not pargs.clamav) and (not pargs.extplorer) and (not pargs.clamav) and
(not pargs.ufw) and (not pargs.ufw) and (not pargs.ngxblocker) and
(not pargs.phpredisadmin) and (not pargs.sendmail) and (not pargs.phpredisadmin) and (not pargs.sendmail) and
(not pargs.php73)): (not pargs.php73)):
pargs.web = True pargs.web = True
@@ -813,6 +827,7 @@ class WOStackController(CementBaseController):
pargs.fail2ban = True pargs.fail2ban = True
pargs.clamav = True pargs.clamav = True
pargs.ufw = True pargs.ufw = True
pargs.ngxblocker = True
# NGINX # NGINX
if pargs.nginx: if pargs.nginx:
@@ -958,6 +973,7 @@ class WOStackController(CementBaseController):
'libexec/netdata/netdata-uninstaller.sh'): 'libexec/netdata/netdata-uninstaller.sh'):
packages = packages + ['/var/lib/wo/tmp/kickstart.sh'] packages = packages + ['/var/lib/wo/tmp/kickstart.sh']
# wordops dashboard
if pargs.dashboard: if pargs.dashboard:
Log.debug(self, "Removing Wo-Dashboard") Log.debug(self, "Removing Wo-Dashboard")
packages = packages + ['{0}22222/htdocs/assets/' packages = packages + ['{0}22222/htdocs/assets/'
@@ -965,6 +981,17 @@ class WOStackController(CementBaseController):
'{0}22222/htdocs/index.php' '{0}22222/htdocs/index.php'
.format(WOVar.wo_webroot)] .format(WOVar.wo_webroot)]
# ngxblocker
if pargs.ngxblocker:
if os.path.isfile('/usr/local/sbin/setup-ngxblocker'):
packages = packages + [
'/usr/local/sbin/setup-ngxblocker',
'/usr/local/sbin/install-ngxblocker',
'/usr/local/sbin/update-ngxblocker',
'/etc/nginx/conf.d/globalblacklist.conf',
'/etc/nginx/conf.d/botblocker-nginx-settings.conf',
'/etc/nginx/bots.d']
if (packages) or (apt_packages): if (packages) or (apt_packages):
if (not pargs.force): if (not pargs.force):
start_purge = input('Are you sure you to want to' start_purge = input('Are you sure you to want to'

View File

@@ -851,7 +851,6 @@ def post_pref(self, apt_packages, packages, upgrade=False):
WOGit.add(self, ["/etc/proftpd"], WOGit.add(self, ["/etc/proftpd"],
msg="Adding ProFTPd into Git") msg="Adding ProFTPd into Git")
if os.path.isfile("/etc/proftpd/proftpd.conf"): if os.path.isfile("/etc/proftpd/proftpd.conf"):
Log.info(self, "Configuring ProFTPd")
Log.debug(self, "Setting up Proftpd configuration") Log.debug(self, "Setting up Proftpd configuration")
WOFileUtils.searchreplace( WOFileUtils.searchreplace(
self, "/etc/proftpd/proftpd.conf", self, "/etc/proftpd/proftpd.conf",

View File

@@ -1,6 +1,5 @@
import os import os
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.aptget import WOAptGet from wo.core.aptget import WOAptGet

View File

@@ -1,7 +1,6 @@
import os import os
import shutil import shutil
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.cli.plugins.stack_pref import post_pref, pre_pref from wo.cli.plugins.stack_pref import post_pref, pre_pref
@@ -10,7 +9,6 @@ from wo.core.download import WODownload
from wo.core.extract import WOExtract from wo.core.extract import WOExtract
from wo.core.fileutils import WOFileUtils from wo.core.fileutils import WOFileUtils
from wo.core.logging import Log from wo.core.logging import Log
from wo.core.services import WOService
from wo.core.shellexec import WOShellExec from wo.core.shellexec import WOShellExec
from wo.core.variables import WOVar from wo.core.variables import WOVar
@@ -102,26 +100,20 @@ class WOStackUpgradeController(CementBaseController):
if pargs.php: if pargs.php:
if WOAptGet.is_installed(self, 'php7.2-fpm'): if WOAptGet.is_installed(self, 'php7.2-fpm'):
if not WOAptGet.is_installed(self, 'php7.3-fpm'): apt_packages = apt_packages + WOVar.wo_php + \
apt_packages = apt_packages + WOVar.wo_php + \ WOVar.wo_php_extra
WOVar.wo_php_extra
else:
apt_packages = apt_packages + WOVar.wo_php
else: else:
Log.info(self, "PHP 7.2 is not installed") Log.info(self, "PHP 7.2 is not installed")
if pargs.php73: if pargs.php73:
if WOAptGet.is_installed(self, 'php7.3-fpm'): if WOAptGet.is_installed(self, 'php7.3-fpm'):
if not WOAptGet.is_installed(self, 'php7.2-fpm'): apt_packages = apt_packages + WOVar.wo_php73 + \
apt_packages = apt_packages + WOVar.wo_php73 + \ WOVar.wo_php_extra
WOVar.wo_php_extra
else:
apt_packages = apt_packages + WOVar.wo_php73
else: else:
Log.info(self, "PHP 7.3 is not installed") Log.info(self, "PHP 7.3 is not installed")
if pargs.mysql: if pargs.mysql:
if WOAptGet.is_installed(self, 'mariadb-server'): if WOShellExec.cmd_exec(self, 'mysqladmin ping'):
apt_packages = apt_packages + ['mariadb-server'] apt_packages = apt_packages + ['mariadb-server']
else: else:
Log.info(self, "MariaDB is not installed") Log.info(self, "MariaDB is not installed")
@@ -172,7 +164,7 @@ class WOStackUpgradeController(CementBaseController):
"/var/lib/wo/tmp/pma.tar.gz", "/var/lib/wo/tmp/pma.tar.gz",
"PHPMyAdmin"]] "PHPMyAdmin"]]
else: else:
Log.error(self, "phpMyAdmin isn't installed") Log.info(self, "phpMyAdmin isn't installed")
if pargs.composer: if pargs.composer:
if os.path.isfile('/usr/local/bin/composer'): if os.path.isfile('/usr/local/bin/composer'):
@@ -180,7 +172,7 @@ class WOStackUpgradeController(CementBaseController):
"/var/lib/wo/tmp/composer-install", "/var/lib/wo/tmp/composer-install",
"Composer"]] "Composer"]]
else: else:
Log.error(self, "Composer isn't installed") Log.info(self, "Composer isn't installed")
if ((not (apt_packages)) and (not(packages))): if ((not (apt_packages)) and (not(packages))):
self.app.args.print_help() self.app.args.print_help()

View File

@@ -1,6 +1,5 @@
import glob import glob
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.cli.plugins.sitedb import getAllsites, updateSiteInfo from wo.cli.plugins.sitedb import getAllsites, updateSiteInfo

View File

@@ -1,7 +1,6 @@
import os import os
import time import time
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose from cement.core.controller import CementBaseController, expose
from wo.core.download import WODownload from wo.core.download import WODownload

View File

@@ -20,4 +20,4 @@ listen.backlog = 32768
catch_workers_output = yes catch_workers_output = yes
{{#openbasedir}}php_admin_value[open_basedir] = "/var/www/:/usr/share/php/:/tmp/:/var/run/nginx-cache/"{{/openbasedir}} {{#openbasedir}}php_admin_value[open_basedir] = "/var/www/:/usr/share/php/:/tmp/:/var/run/nginx-cache/:/dev/urandom:/dev/shm"{{/openbasedir}}

View File

@@ -1,86 +1,86 @@
# NGINX UPSTREAM CONFIGURATION - WO v3.9.8 # NGINX UPSTREAM CONFIGURATION - WO v3.9.8
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE # DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
#------------------------------- #-------------------------------
# PHP 5.6 # PHP 5.6
#------------------------------- #-------------------------------
upstream php { upstream php {
server 127.0.0.1:{{php}}; server 127.0.0.1:{{php}};
} }
upstream debug { upstream debug {
server 127.0.0.1:{{debug}}; server 127.0.0.1:{{debug}};
} }
#------------------------------- #-------------------------------
# PHP 7.0 # PHP 7.0
#------------------------------- #-------------------------------
upstream php7 { upstream php7 {
server 127.0.0.1:{{php7}}; server 127.0.0.1:{{php7}};
} }
upstream debug7 { upstream debug7 {
# Debug Pool # Debug Pool
server 127.0.0.1:{{debug7}}; server 127.0.0.1:{{debug7}};
} }
#------------------------------- #-------------------------------
# PHP 7.2 # PHP 7.2
#------------------------------- #-------------------------------
# PHP 7.2 upstream with load-balancing on two unix sockets # PHP 7.2 upstream with load-balancing on two unix sockets
upstream php72 { upstream php72 {
least_conn; least_conn;
server unix:/var/run/php/php72-fpm.sock; server unix:/var/run/php/php72-fpm.sock;
server unix:/var/run/php/php72-two-fpm.sock; server unix:/var/run/php/php72-two-fpm.sock;
keepalive 5; keepalive 5;
} }
# PHP 7.2 debug # PHP 7.2 debug
upstream debug72 { upstream debug72 {
# Debug Pool # Debug Pool
server 127.0.0.1:9172; server 127.0.0.1:9172;
} }
#------------------------------- #-------------------------------
# PHP 7.3 # PHP 7.3
#------------------------------- #-------------------------------
# PHP 7.3 upstream with load-balancing on two unix sockets # PHP 7.3 upstream with load-balancing on two unix sockets
upstream php73 { upstream php73 {
least_conn; least_conn;
server unix:/var/run/php/php73-fpm.sock; server unix:/var/run/php/php73-fpm.sock;
server unix:/var/run/php/php73-two-fpm.sock; server unix:/var/run/php/php73-two-fpm.sock;
keepalive 5; keepalive 5;
} }
# PHP 7.3 debug # PHP 7.3 debug
upstream debug73 { upstream debug73 {
# Debug Pool # Debug Pool
server 127.0.0.1:9173; server 127.0.0.1:9173;
} }
#------------------------------- #-------------------------------
# Netdata # Netdata
#------------------------------- #-------------------------------
# Netdata Monitoring Upstream # Netdata Monitoring Upstream
upstream netdata { upstream netdata {
server 127.0.0.1:19999; server 127.0.0.1:19999;
keepalive 64; keepalive 64;
} }
#------------------------------- #-------------------------------
# Redis # Redis
#------------------------------- #-------------------------------
# Redis cache upstream # Redis cache upstream
upstream redis { upstream redis {
server 127.0.0.1:6379; server 127.0.0.1:6379;
keepalive 10; keepalive 10;
} }

View File

@@ -47,16 +47,17 @@ class WOAcme:
.format(all_domains, acme_mode, keylenght)): .format(all_domains, acme_mode, keylenght)):
Log.failed(self, "Issuing SSL cert with acme.sh") Log.failed(self, "Issuing SSL cert with acme.sh")
if acmedata['dns'] is True: if acmedata['dns'] is True:
Log.warn( Log.error(
self, "Please make sure your properly " self, "Please make sure your properly "
"set your DNS API credentials for acme.sh") "set your DNS API credentials for acme.sh")
return False
else: else:
Log.error( Log.error(
self, "Your domain is properly configured " self, "Your domain is properly configured "
"but acme.sh was unable to issue certificate.\n" "but acme.sh was unable to issue certificate.\n"
"You can find more informations in " "You can find more informations in "
"/var/log/wo/wordops.log", False) "/var/log/wo/wordops.log")
return False return False
else: else:
Log.valide(self, "Issuing SSL cert with acme.sh") Log.valide(self, "Issuing SSL cert with acme.sh")
return True return True

View File

@@ -13,7 +13,7 @@ class WOVar():
"""Intialization of core variables""" """Intialization of core variables"""
# WordOps version # WordOps version
wo_version = "3.9.9.3" wo_version = "3.9.9.4"
# WordOps packages versions # WordOps packages versions
wo_wp_cli = "2.3.0" wo_wp_cli = "2.3.0"
wo_adminer = "4.7.3" wo_adminer = "4.7.3"

View File

@@ -1,6 +1,6 @@
"""Testing utilities for WordOps""" """Testing utilities for WordOps"""
from wo.cli.main import WOTestApp
from cement.utils.test import * from cement.utils.test import *
from wo.cli.main import WOTestApp
class WOTestCase(CementTestCase): class WOTestCase(CementTestCase):