From 05cdb4c3c1eaeabd3228366e6a33599574c2da45 Mon Sep 17 00:00:00 2001 From: cytopia Date: Mon, 22 May 2017 23:20:20 +0200 Subject: [PATCH] REL-0.10 Adding MongoDB --- .devilbox/www/config.php | 8 +- .devilbox/www/htdocs/db_mongo.php | 50 ++++ .devilbox/www/htdocs/index.php | 64 ++++- .devilbox/www/htdocs/info_mongo.php | 48 ++++ .devilbox/www/include/lib/Html.php | 14 ++ .devilbox/www/include/lib/container/Mongo.php | 224 ++++++++++++++++++ .tests/.lib.sh | 2 +- docker-compose.yml | 34 ++- 8 files changed, 439 insertions(+), 5 deletions(-) create mode 100644 .devilbox/www/htdocs/db_mongo.php create mode 100644 .devilbox/www/htdocs/info_mongo.php create mode 100644 .devilbox/www/include/lib/container/Mongo.php diff --git a/.devilbox/www/config.php b/.devilbox/www/config.php index 89330365..f87ff523 100644 --- a/.devilbox/www/config.php +++ b/.devilbox/www/config.php @@ -10,7 +10,7 @@ error_reporting(-1); putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1'); -$DEVILBOX_VERSION = 'v0.9'; +$DEVILBOX_VERSION = 'v0.10'; $DEVILBOX_DATE = '2017-05-20'; $DEVILBOX_API_PAGE = 'devilbox-api/status.json'; @@ -41,6 +41,7 @@ $MYSQL_HOST_NAME = 'mysql'; $PGSQL_HOST_NAME = 'pgsql'; $REDIS_HOST_NAME = 'redis'; $MEMCD_HOST_NAME = 'memcd'; +$MONGO_HOST_NAME = 'mongo'; // @@ -132,6 +133,11 @@ function loadClass($class) { $_LOADED_LIBS[$class] = \devilbox\Memcd::getInstance($GLOBALS['MEMCD_HOST_NAME']); break; + case 'Mongo': + loadFile($class, $cnt_dir); + $_LOADED_LIBS[$class] = \devilbox\Mongo::getInstance($GLOBALS['MONGO_HOST_NAME']); + break; + // Get optional docker classes default: // Redis diff --git a/.devilbox/www/htdocs/db_mongo.php b/.devilbox/www/htdocs/db_mongo.php new file mode 100644 index 00000000..1fa6517b --- /dev/null +++ b/.devilbox/www/htdocs/db_mongo.php @@ -0,0 +1,50 @@ + + + + + getHead(); ?> + + + + getNavbar(); ?> + +
+ +

MongoDB Databases

+
+
+ +
+
+ + isAvailable()): ?> +

MongoDB container is not running.

+ + + + + + + + + + + getDatabases() as $db): ?> + + + + + + + +
NameSizeEmpty
MB
+ + +
+
+ +
+ + getFooter(); ?> + + diff --git a/.devilbox/www/htdocs/index.php b/.devilbox/www/htdocs/index.php index 90fef793..ffb1616a 100644 --- a/.devilbox/www/htdocs/index.php +++ b/.devilbox/www/htdocs/index.php @@ -18,6 +18,7 @@ $avail_mysql = loadClass('Mysql')->isAvailable(); $avail_pgsql = loadClass('Pgsql')->isAvailable(); $avail_redis = loadClass('Redis')->isAvailable(); $avail_memcd = loadClass('Memcd')->isAvailable(); +$avail_mongo = loadClass('Mongo')->isAvailable(); /************************************************************* @@ -150,6 +151,32 @@ if ($avail_memcd) { ); } +// ---- MONGO ---- +if ($avail_mongo) { + $host = $GLOBALS['MONGO_HOST_NAME']; + $succ = loadClass('Mongo')->canConnect($error, $host); + $connection['MongoDB'][$host] = array( + 'error' => $error, + 'host' => $host, + 'succ' => $succ + ); + $host = loadClass('Mongo')->getIpAddress(); + $succ = loadClass('Mongo')->canConnect($error, $host); + $connection['MongoDB'][$host] = array( + 'error' => $error, + 'host' => $host, + 'succ' => $succ + ); + $host = '127.0.0.1'; + $succ = loadClass('Mongo')->canConnect($error, $host); + $connection['MongoDB'][$host] = array( + 'error' => $error, + 'host' => $host, + 'succ' => $succ + ); +} + + // ---- BIND (required)---- $host = $GLOBALS['DNS_HOST_NAME']; $succ = loadClass('Dns')->canConnect($error, $host); @@ -288,7 +315,7 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); getCirle('memcd'); ?>
- getCirle('mongodb'); ?> + getCirle('mongo'); ?>
@@ -516,6 +543,13 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); getIpAddress(); ?> + + + mongo + + getIpAddress(); ?> + + bind @@ -585,6 +619,13 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); 11211 + + + mongo + getEnv('LOCAL_LISTEN_ADDR').loadClass('Helper')->getEnv('HOST_PORT_MONGO');?> + 27017 + + bind @@ -656,6 +697,13 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); - + + + mongo + getEnv('HOST_PATH_MONGO_DATADIR'); ?> + /data/db + + bind @@ -724,6 +772,13 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); - + + + mongo + - + - + + bind @@ -792,6 +847,13 @@ $HEALTH_PERCENT = 100 - ceil(100 * $HEALTH_FAILS / $HEALTH_TOTAL); /var/log/memcached + + + mongo + - + - + + bind diff --git a/.devilbox/www/htdocs/info_mongo.php b/.devilbox/www/htdocs/info_mongo.php new file mode 100644 index 00000000..942475f4 --- /dev/null +++ b/.devilbox/www/htdocs/info_mongo.php @@ -0,0 +1,48 @@ + + + + + getHead(); ?> + + + + getNavbar(); ?> + +
+ +

MongoDB Info

+
+
+ +
+
+ + isAvailable()): ?> +

MongoDB container is not running.

+ + + + + + + + + + getInfo() as $key => $val): ?> + + + + + + +
VariableValue
+ + +
+
+ +
+ + getFooter(); ?> + + diff --git a/.devilbox/www/include/lib/Html.php b/.devilbox/www/include/lib/Html.php index 1914933a..ec18ff9d 100644 --- a/.devilbox/www/include/lib/Html.php +++ b/.devilbox/www/include/lib/Html.php @@ -34,6 +34,10 @@ class Html 'name' => 'PgSQL DB', 'path' => '/db_pgsql.php' ), + array( + 'name' => 'MongoDB DB', + 'path' => '/db_mongo.php' + ), array( 'name' => 'Redis DB', 'path' => '/db_redis.php' @@ -63,6 +67,10 @@ class Html 'name' => 'PgSQL Info', 'path' => '/info_pgsql.php' ), + array( + 'name' => 'MongoDB Info', + 'path' => '/info_mongo.php' + ), array( 'name' => 'Redis Info', 'path' => '/info_redis.php' @@ -271,6 +279,12 @@ HTML; $available = loadClass('Memcd')->isAvailable(); $name = loadClass('Memcd')->getName(); break; + case 'mongo': + $class = 'bg-danger'; + $version = loadClass('Mongo')->getVersion(); + $available = loadClass('Mongo')->isAvailable(); + $name = loadClass('Mongo')->getName(); + break; default: $available = false; $version = ''; diff --git a/.devilbox/www/include/lib/container/Mongo.php b/.devilbox/www/include/lib/container/Mongo.php new file mode 100644 index 00000000..5f74f930 --- /dev/null +++ b/.devilbox/www/include/lib/container/Mongo.php @@ -0,0 +1,224 @@ +isAvailable()) { + return; + } + + + $mongo = new \MongoDB\Driver\Manager('mongodb://'.$hostname); + + // MongoDB uses lazy loading of server list + // so just execute an arbitrary command in order + // to make it populate the server list + $command = new \MongoDB\Driver\Command(array('ping' => 1)); + + try { + $mongo->executeCommand('admin', $command); + } catch (\MongoDB\Driver\Exception\ConnectionTimeoutException $e) { + $this->_connect_error = $e; + $this->_connect_errno = 1; + return; + } + + // retrieve server list + $servers = $mongo->getServers(); + + if (!isset($servers[0])) { + $this->_connect_error = 'Failed to connect to MongoDB host on '.$hostname.' (No host info available)'; + $this->_connect_errno = 2; + return; + } else if ($servers[0]->getHost() != $hostname) { + $this->_connect_error = 'Failed to connect to MongoDB host on '.$hostname.' (servername does not match: '.$servers[0]->getHost().')'; + $this->_connect_errno = 3; + return; + } + $this->_mongo = $mongo; + } + + + + + /********************************************************************************* + * + * Select functions + * + *********************************************************************************/ + + + private function command($command) + { + $cmd = new \MongoDB\Driver\Command($command); + + if ($this->_mongo) { + try { + $cursor = $this->_mongo->executeCommand('admin', $cmd); + return $cursor->toArray(); + } catch(\MongoDB\Driver\Exception $e) { + loadClass('Logger')->error($e->getMessage().'. Could not execute MongoDB command: '.print_r($command, true)); + } + } + + return array(); + } + + private function query($query) + { + } + + + /** + * Get all MongoDB Databases. + * @return mixed[] Array of databases + */ + public function getDatabases() + { + $databases = array(); + $tmp = $this->command(array('listDatabases' => true)); + if (isset($tmp[0])) { + foreach ($tmp[0]->databases as $db) { + $databases[] = array( + 'name' => $db->name, + 'size' => $db->sizeOnDisk, + 'empty' => $db->empty + ); + } + } + + + return $databases; + } + + + + public function getInfo() + { + $info = array(); + $tmp = $this->command(array('serverStatus' => true)); + + if (isset($tmp[0])) { + $info = $tmp[0]; + } + return $info; + } + + + /********************************************************************************* + * + * Interface required functions + * + *********************************************************************************/ + + + private $_can_connect = array(); + private $_can_connect_err = array(); + + private $_name = null; + private $_version = null; + + public function canConnect(&$err, $hostname, $data = array()) + { + $err = false; + + // Return if already cached + if (isset($this->_can_connect[$hostname])) { + // Assume error for unset error message + $err = isset($this->_can_connect_err[$hostname]) ? $this->_can_connect_err[$hostname] : true; + return $this->_can_connect[$hostname]; + } + + $manager = new \MongoDB\Driver\Manager('mongodb://'.$hostname); + + // MongoDB uses lazy loading of server list + // so just execute an arbitrary command in order + // to make it populate the server list + $command = new \MongoDB\Driver\Command(array('ping' => 1)); + $manager->executeCommand('admin', $command); + + // retrieve server list + $servers = $manager->getServers(); + + if (!isset($servers[0])) { + $err = 'Failed to connect to MongoDB host on '.$hostname.' (No host info available)'; + $this->_can_connect[$hostname] = false; + } else if ($servers[0]->getHost() != $hostname) { + $err = 'Failed to connect to MongoDB host on '.$hostname.' (servername does not match: '.$servers[0]->getHost().')'; + $this->_can_connect[$hostname] = false; + } + else { + $this->_can_connect[$hostname] = true; + } + + $this->_can_connect_err[$hostname] = $err; + return $this->_can_connect[$hostname]; + } + + + public function getName($default = 'MongoDB') + { + return $default; + } + + public function getVersion() + { + // Return if already cached + if ($this->_version !== null) { + return $this->_version; + } + + // Return empty if not available + if (!$this->isAvailable()) { + $this->_version = ''; + return $this->_version; + } + + if ($this->_mongo) { + $info = $this->getInfo(); + if (!isset($info->version)) { + loadClass('Logger')->error('Could not get MongoDB version'); + $this->_version = ''; + } else { + $this->_version = $info->version; + } + } + return $this->_version; + } +} diff --git a/.tests/.lib.sh b/.tests/.lib.sh index fe3b1d1f..e38534c4 100644 --- a/.tests/.lib.sh +++ b/.tests/.lib.sh @@ -383,7 +383,7 @@ devilbox_test() { ### Variables ### _ret=0 # Final exit code - _oks=17 # Require this many [OK]'s on the page + _oks=20 # Require this many [OK]'s on the page diff --git a/docker-compose.yml b/docker-compose.yml index 7c35c526..7fc42299 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -62,7 +62,7 @@ services: # ---------------------------------------- php: #image: cytopia/${PHP_SERVER:-php-fpm-7.0}:latest - image: cytopia/${PHP_SERVER:-php-fpm-7.0}:0.9 + image: cytopia/${PHP_SERVER:-php-fpm-7.0}:release-0.10 restart: always # Manually build via `docker-compose build` @@ -109,7 +109,7 @@ services: ## ## Enable 127.0.0.1 Port-forwarding ## - - FORWARD_PORTS_TO_LOCALHOST=3306:mysql:3306,5432:pgsql:5432,6379:redis:6379,11211:memcd:11211 + - FORWARD_PORTS_TO_LOCALHOST=3306:mysql:3306,5432:pgsql:5432,6379:redis:6379,11211:memcd:11211,27017:mongo:27017 ## ## Additional variables to announce to intranet/php-container @@ -122,10 +122,12 @@ services: - HOST_PORT_PGSQL - HOST_PORT_REDIS - HOST_PORT_MEMCD + - HOST_PORT_MONGO # Data dir paths - HOST_PATH_HTTPD_DATADIR - HOST_PATH_MYSQL_DATADIR - HOST_PATH_PGSQL_DATADIR + - HOST_PATH_MONGO_DATADIR # Database credentials - PGSQL_ROOT_USER - PGSQL_ROOT_PASSWORD @@ -137,6 +139,7 @@ services: - MYSQL_SERVER - REDIS_SERVER - MEMCD_SERVER + - MONGO_SERVER networks: app_net: @@ -415,6 +418,33 @@ services: - httpd + # ---------------------------------------- + # Mongo + # ---------------------------------------- + mongo: + image: mongo:${MONGO_SERVER:-latest} + + ports: + # [local-machine:]local-port:docker-port + - "${LOCAL_LISTEN_ADDR}${HOST_PORT_MONGO}:27017" + + networks: + app_net: + ipv4_address: 172.16.238.16 + + volumes: + # ---- Format: ---- + # HOST-DIRECTORY : DOCKER-DIRECTORY + + # Mount MySQL Data directory + - ${HOST_PATH_MONGO_DATADIR}:/data/db + + depends_on: + - bind + - php + - httpd + + ################################################################################ # NETWORK ################################################################################