diff --git a/.devilbox/www/config.php b/.devilbox/www/config.php index 441e0456..9c9960c4 100644 --- a/.devilbox/www/config.php +++ b/.devilbox/www/config.php @@ -14,7 +14,7 @@ putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1'); $DEVILBOX_VERSION = 'v0.15'; -$DEVILBOX_DATE = '2018-11-03'; +$DEVILBOX_DATE = '2018-12-15'; $DEVILBOX_API_PAGE = 'devilbox-api/status.json'; // diff --git a/.devilbox/www/htdocs/db_memcd.php b/.devilbox/www/htdocs/db_memcd.php index 028049a0..f9e24f24 100644 --- a/.devilbox/www/htdocs/db_memcd.php +++ b/.devilbox/www/htdocs/db_memcd.php @@ -25,6 +25,8 @@ Key + Size + TTL Value @@ -32,7 +34,9 @@ getKeys() as $data): ?> - + + + diff --git a/.devilbox/www/htdocs/db_redis.php b/.devilbox/www/htdocs/db_redis.php index 5c07cf92..532de888 100644 --- a/.devilbox/www/htdocs/db_redis.php +++ b/.devilbox/www/htdocs/db_redis.php @@ -1,5 +1,12 @@ authPage(); ?> +flushDB($_GET['redisdb']); + loadClass('Helper')->redirect('/db_redis.php'); +} +?> @@ -15,6 +22,27 @@

+ getKeys()); ?> + +
+
+
+
+ + +
   + +
+
+
+
+ +
@@ -22,29 +50,43 @@

Redis container is not running.

- - - - - - - - getKeys() as $db_name => $keys): ?> - - + - - $val): ?> - - - - + + + + + + + + - + + + + + + + + + - + + +

No keys set.

+
DBKeyValue
- + getKeys(); ?> + + $keys): ?> +
+ Database:      + Items: +
DBKeyExpiresTypeValue
s + + + +
diff --git a/.devilbox/www/include/lib/container/Memcd.php b/.devilbox/www/include/lib/container/Memcd.php index bf4e7eb1..87ef85b4 100644 --- a/.devilbox/www/include/lib/container/Memcd.php +++ b/.devilbox/www/include/lib/container/Memcd.php @@ -43,7 +43,7 @@ class Memcd extends BaseClass implements BaseInterface if (empty($list)) { $memcd->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); - $memcd->setOption(\Memcached::OPT_BINARY_PROTOCOL, false); + $memcd->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); $memcd->addServer($hostname, 11211); } @@ -67,13 +67,15 @@ class Memcd extends BaseClass implements BaseInterface $this->_connect_errno = 3; return; } - - $memcd->set('devilbox-version', $GLOBALS['DEVILBOX_VERSION'].' ('.$GLOBALS['DEVILBOX_DATE'].')'); + $memcd->getDelayed(array('devilbox-version')); + if (!$memcd->fetchAll()) { + $memcd->set('devilbox-version', $GLOBALS['DEVILBOX_VERSION'].' ('.$GLOBALS['DEVILBOX_DATE'].')'); + } $this->_memcached = $memcd; } else { $ret = 0; - loadClass('Helper')->exec('echo "stats" | nc 127.0.0.1 11211', $ret); + loadClass('Helper')->exec('printf "stats\nquit\n" | nc '.$hostname.' 11211', $ret); if ($ret == 0) { $this->_memcached = true; } @@ -104,16 +106,55 @@ class Memcd extends BaseClass implements BaseInterface public function getKeys() { $store = array(); + + // CLI seems to only sometimes get the results, so we will just loop a bit + // It's a very quick operation anyway. + $cli_retries = 100; + + // Memcached >= 1.5 + for ($i=0; $i<$cli_retries; $i++) { + + $output = array(); + exec('printf "stats cachedump 1 0\nquit\n" | nc memcd 11211 | grep -E \'^ITEM\'', $output); + foreach ($output as $line) { + $matches = array(); + preg_match('/(^ITEM)\s*(.+?)\s*\[([0-9]+\s*b);\s*([0-9]+\s*s)\s*\]/', $line, $matches); + $key = $matches[2]; + $store[] = array( + 'key' => $key, + 'val' => $this->_memcached->get($key), + 'ttl' => $matches[4], + 'size' => $matches[3], + ); + } + // If we actually got a result, we can break here + if (count($store)) { + return $store; + } + } + + // This will only work for Memcached < 1.5 if (class_exists('Memcached')) { if ($this->_memcached) { + + // Ensure we retrieve data not in binary + $this->_memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, false); + if (!($keys = $this->_memcached->getAllKeys())) { $keys = array(); } - $this->_memcached->getDelayed($keys); - $store = $this->_memcached->fetchAll(); - if (!is_array($store)) { - $store = array(); + $this->_memcached->getDelayed($keys, true); + $data = $this->_memcached->fetchAll(); + if (is_array($data)) { + for ($i=0; $size=count($data), $i<$size; $i++) { + $store[$i]['key'] = $data[$i]['key']; + $store[$i]['val'] = $data[$i]['value']; + $store[$i]['ttl'] = '?'; + $store[$i]['size'] = strlen($data[$i]['value']); + } } + // Revert Memcachd protocol + $this->_memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); } } return $store; @@ -128,14 +169,14 @@ class Memcd extends BaseClass implements BaseInterface } } else { $ret = 0; - $output = loadClass('Helper')->exec('echo "stats" | nc 127.0.0.1 11211 | sed "s/^STAT[[:space:]]*//g" | grep -v "END"', $ret); + $output = loadClass('Helper')->exec('printf "stats\nquit\n" | nc memcd 11211 | sed "s/^STAT[[:space:]]*//g" | grep -v "END"', $ret); if ($ret == 0) { $output = explode("\n", $output); foreach ($output as $line) { $tmp = explode(' ', $line); $key = isset($tmp[0]) ? $tmp[0] : ''; $val = isset($tmp[1]) ? $tmp[1] : ''; - $stats['127.0.0.1'][$key] = $val; + $stats['memcd'][$key] = $val; } } } @@ -167,51 +208,13 @@ class Memcd extends BaseClass implements BaseInterface return $this->_can_connect[$hostname]; } - if (class_exists('Memcached')) { - // Silence errors and try to connect - //error_reporting(-1); - $memcd = new \Memcached(); - $memcd->resetServerList(); - - - if (!$memcd->addServer($hostname, 11211)) { - $memcd->quit(); - $err = 'Failed to connect to Memcached host on '.$hostname; - $this->_can_connect[$hostname] = false; - $this->_can_connect_err[$hostname] = $err; - return false; - } - - $stats = $memcd->getStats(); - if (!isset($stats[$hostname.':11211'])) { - $err = 'Failed to connect to Memcached host on '.$hostname; - $this->_can_connect[$hostname] = false; - } - else if (!isset($stats[$hostname.':11211']['pid'])) { - $err = 'Failed to connect to Memcached host on '.$hostname; - $this->_can_connect[$hostname] = false; - } - else if ($stats[$hostname.':11211']['pid'] < 1) { - $err = 'Failed to connect to Memcached host on '.$hostname; - $this->_can_connect[$hostname] = false; - } - else { - $this->_can_connect[$hostname] = true; - } - - $memcd->quit(); - - $this->_can_connect_err[$hostname] = $err; + $ret = 0; + loadClass('Helper')->exec('printf "stats\nquit\n" | nc '.$hostname.' 11211', $ret); + if ($ret == 0) { + $this->_can_connect[$hostname] = true; } else { - - $ret = 0; - loadClass('Helper')->exec('echo "stats" | nc '.$hostname.' 11211', $ret); - if ($ret == 0) { - $this->_can_connect[$hostname] = true; - } else { - $err = 'Failed to connect to Memcached host on '.$hostname; - $this->_can_connect[$hostname] = false; - } + $err = 'Failed to connect to Memcached host on '.$hostname; + $this->_can_connect[$hostname] = false; } return $this->_can_connect[$hostname]; @@ -249,7 +252,7 @@ class Memcd extends BaseClass implements BaseInterface } } } else { - $version = loadClass('Helper')->exec('echo "version" | nc 127.0.0.1 11211 | grep -oE "[0-9.-]+"', $ret); + $version = loadClass('Helper')->exec('printf "version\nquit\n" | nc memcd 11211 | grep -oE "[0-9.-]+"', $ret); $this->_version = $version; } return $this->_version; diff --git a/.devilbox/www/include/lib/container/Mongo.php b/.devilbox/www/include/lib/container/Mongo.php index a78b241d..0b941d29 100644 --- a/.devilbox/www/include/lib/container/Mongo.php +++ b/.devilbox/www/include/lib/container/Mongo.php @@ -91,10 +91,9 @@ class Mongo extends BaseClass implements BaseInterface */ private function command($command) { - $cmd = new \MongoDB\Driver\Command($command); - if ($this->_mongo) { try { + $cmd = new \MongoDB\Driver\Command($command); $cursor = $this->_mongo->executeCommand('admin', $cmd); return $cursor->toArray(); } catch(\MongoDB\Driver\Exception $e) { diff --git a/.devilbox/www/include/lib/container/Redis.php b/.devilbox/www/include/lib/container/Redis.php index e2f142b5..0a0f1bf5 100644 --- a/.devilbox/www/include/lib/container/Redis.php +++ b/.devilbox/www/include/lib/container/Redis.php @@ -70,6 +70,17 @@ class Redis extends BaseClass implements BaseInterface * Select functions * *********************************************************************************/ + public function flushDB($db) + { + if ($this->_redis) { + if ( !$this->_redis->select($db) ) { + return FALSE; + } + return $this->_redis->flushDb(); + } else { + return FALSE; + } + } public function getInfo() { @@ -101,7 +112,35 @@ class Redis extends BaseClass implements BaseInterface $this->_redis->select($db); $keys = $this->_redis->keys('*'); foreach ($keys as $key) { - $store[$db][$key] = $this->_redis->get($key); + + switch($this->_redis->type($key)) { + case \Redis::REDIS_STRING: + $dtype = 'string'; + break; + case \Redis::REDIS_SET: + $dtype = 'set'; + break; + case \Redis::REDIS_LIST: + $dtype = 'list'; + break; + case \Redis::REDIS_ZSET: + $dtype = 'zset'; + break; + case \Redis::REDIS_HASH: + $dtype = 'hash'; + break; + case \Redis::REDIS_NOT_FOUND: + $dtype = 'other'; + break; + default: + $dtype = 'unknown'; + } + $store[$db][] = array( + 'name' => $key, + 'val' => $this->_redis->get($key), + 'type' => $dtype, + 'ttl' => $this->_redis->ttl($key) + ); } } } diff --git a/.tests/intra-tests/homepage.sh b/.tests/intra-tests/homepage.sh index 0b1bf733..f029a7ac 100755 --- a/.tests/intra-tests/homepage.sh +++ b/.tests/intra-tests/homepage.sh @@ -17,9 +17,11 @@ printf "[TEST] dvlbox-ok" TEST_OK="$( curl -sS localhost/index.php | grep -c 'dvlbox-ok' || true )" if [ "${TEST_OK}" != "${NUM_OK}" ]; then # 2nd Try + sleep 1 TEST_OK="$( curl -sS localhost/index.php | grep -c 'dvlbox-ok' || true )" if [ "${TEST_OK}" != "${NUM_OK}" ]; then # 3rd Try + sleep 1 TEST_OK="$( curl -sS localhost/index.php | grep -c 'dvlbox-ok' || true )" if [ "${TEST_OK}" != "${NUM_OK}" ]; then printf "\r[FAIL] dvlbox-ok\n" @@ -45,9 +47,11 @@ printf "[TEST] dvlbox-err" TEST_ERR="$( curl -sS localhost/index.php | grep -c 'dvlbox-err' || true )" if [ "${TEST_ERR}" != "${NUM_ERR}" ]; then # 2nd Try + sleep 1 TEST_ERR="$( curl -sS localhost/index.php | grep -c 'dvlbox-err' || true )" if [ "${TEST_ERR}" != "${NUM_ERR}" ]; then # 3rd Try + sleep 1 TEST_ERR="$( curl -sS localhost/index.php | grep -c 'dvlbox-err' || true )" if [ "${TEST_ERR}" != "${NUM_ERR}" ]; then printf "\r[FAIL] dvlbox-err\n" diff --git a/.tests/intra-tests/memcached.sh b/.tests/intra-tests/memcached.sh new file mode 100755 index 00000000..4196e9eb --- /dev/null +++ b/.tests/intra-tests/memcached.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + + +printf "[TEST] devilbox-version key in Memcached" +# 1st Try +if ! curl -sS localhost/db_memcd.php | grep -q 'devilbox-version'; then + sleep 1 + if ! curl -sS localhost/db_memcd.php | grep -q 'devilbox-version'; then + sleep 1 + if ! curl -sS localhost/db_memcd.php | grep -q 'devilbox-version'; then + printf "\r[FAIL] devilbox-version key in Memcached\n" + curl -sS localhost/db_memcd.php || true + exit 1 + else + printf "\r[OK] devilbox-version key in Memcached (3 rounds)\n" + fi + else + printf "\r[OK] devilbox-version key in Memcached (2 rounds)\n" + fi +else + printf "\r[OK] devilbox-version key in Memcached (1 round)\n" +fi diff --git a/.tests/intra-tests/redis.sh b/.tests/intra-tests/redis.sh new file mode 100755 index 00000000..4ce521a5 --- /dev/null +++ b/.tests/intra-tests/redis.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + + +printf "[TEST] devilbox-version key in Redis" +# 1st Try +if ! curl -sS localhost/db_redis.php | grep -q 'devilbox-version'; then + sleep 1 + if ! curl -sS localhost/db_redis.php | grep -q 'devilbox-version'; then + sleep 1 + if ! curl -sS localhost/db_redis.php | grep -q 'devilbox-version'; then + printf "\r[FAIL] devilbox-version key in Redis\n" + curl -sS localhost/db_redis.php || true + exit 1 + else + printf "\r[OK] devilbox-version key in Redis (3 rounds)\n" + fi + else + printf "\r[OK] devilbox-version key in Redis (2 rounds)\n" + fi +else + printf "\r[OK] devilbox-version key in Redis (1 round)\n" +fi diff --git a/.travis.yml b/.travis.yml index 8434a6f6..8efbeb0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -124,19 +124,22 @@ env: ### Installation ### install: + # Update Debian/Ubuntu package index + - if [ "${S1}" != "DOCUMENTATION" ]; then + until sudo apt-get update -qq; do sleep 1; done + fi + # Install dependencies for documentation - if [ "${S1}" = "DOCUMENTATION" ]; then - max=100; i=0; while [ $i -lt $max ]; do if pip install sphinx; then break; else i=$((i+1)); fi done; - max=100; i=0; while [ $i -lt $max ]; do if pip install sphinx-autobuild; then break; else i=$((i+1)); fi done; - max=100; i=0; while [ $i -lt $max ]; do if pip install recommonmark; then break; else i=$((i+1)); fi done; - max=100; i=0; while [ $i -lt $max ]; do if pip install sphinx_rtd_theme; then break; else i=$((i+1)); fi done; + until pip install sphinx; do sleep 1; done; + until pip install sphinx-autobuild; do sleep 1; done; + until pip install recommonmark; do sleep 1; done; + until pip install sphinx_rtd_theme; do sleep 1; done; fi # Determine latest Docker version in apt - - set -e; - DOCKER_APT=""; + - DOCKER_APT=""; if [ "${S1}" = "DOCKER" ]; then - max=100; i=0; while [ $i -lt $max ]; do if sudo apt-get update -qq; then break; else i=$((i+1)); fi; done; DOCKER_APT="$( curl -sS https://raw.githubusercontent.com/cytopia/tools/master/docker-apt-versions | sh -s "${V1}" )"; fi; if [ -n "${DOCKER_APT}" ]; then @@ -145,8 +148,7 @@ install: echo "${DOCKER_APT}"; # Determine latest Docker Compose version - - set -e; - if [ "${S2}" = "COMPOSE" ]; then + - if [ "${S2}" = "COMPOSE" ]; then COMPOSE_VERSION="$( curl -sS https://raw.githubusercontent.com/cytopia/tools/master/docker-compose-versions | sh -s "${V2}" )"; else COMPOSE_VERSION="$( curl -sS https://raw.githubusercontent.com/cytopia/tools/master/docker-compose-versions | sh -s 1 )"; @@ -154,17 +156,9 @@ install: echo "${COMPOSE_VERSION}"; # Install Docker and Docker Compose - - set -e; - if [ "${S1}" != "DOCUMENTATION" ]; then - max=100; i=0; while [ $i -lt $max ]; do - if sudo apt-get update -qq; then break; else i=$((i+1)); fi; - done; - max=100; i=0; while [ $i -lt $max ]; do - if sudo apt-get -y -qq -o Dpkg::Options::="--force-confnew" install docker-ce${DOCKER_APT}; then break; else i=$((i+1)); fi; - done; - max=100; i=0; while [ $i -lt $max ]; do - if curl -L --retry 100 --retry-max-time 0 https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose; then break; else i=$((i+1)); fi; - done; + - if [ "${S1}" != "DOCUMENTATION" ]; then + until sudo apt-get -y -qq -o Dpkg::Options::="--force-confnew" install docker-ce${DOCKER_APT}; do sleep 1; done; + until curl -L -sS --retry 100 --retry-max-time 0 https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose; do sleep 1; done; chmod +x docker-compose; sudo mv -f docker-compose /usr/local/bin; fi diff --git a/docker-compose.yml b/docker-compose.yml index a52070ea..dfde3948 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -95,7 +95,7 @@ services: # PHP / HHVM # ------------------------------------------------------------ php: - image: devilbox/php-fpm:${PHP_SERVER:-7.2}-work-0.52 + image: devilbox/php-fpm:${PHP_SERVER:-7.2}-work-0.54 ## ## All .env variables