Skip to content
Snippets Groups Projects
Select Git revision
  • 029996192487a6a371fb690682849b56b5e9ae55
  • master default protected
  • simple-task/7248-eol-check-add-node-22
  • 6877_check_iml_deployment
4 results

check_onehost

Blame
  • valuestore.class.php 19.11 KiB
    <?php
    /**
     * value store for versions for the deployment tool
     * 
     * EXAMPLES:
     * 
     * get versions of a phase 
     *     $oVersion = new valuestore();
     *     $oVersion->setProject("", $this->_aPrjConfig["fileprefix"], $sPhase, $sPlace);
     *     $aVersions=$oVersion->getVersion();
     * 
     * set versions of a host
     *     $oVersion = new valuestore();
     *     $oVersion->setProject("", $$sPackage, $sPhase, $sPlace);
     *     $oVersion->updateVar($sVarname, $sValue)
     *
     * delete
     *     $oVersion = new valuestore();
     * 
     *     to delete values for a single place:
     *     $oVersion->setProject("", $this->_aPrjConfig["fileprefix"], $sPhase, $sPlace);
     *     $aVersions=$oVersion->deleteValues();
     * 
     *     to delete all version items for a whole whole project (packages) in all phases
     *     $oVersion->setProject("", $this->_aPrjConfig["fileprefix"]);
     *     $aVersions=$oVersion->deleteValues("version");
     * 
     * @author hahn
     */
    class valuestore {
    
        public $sProject = false;
        public $sPackage = false;
        public $sPhase = false;
        public $sPlace = false;
        public $sHost = false;
        public $sVariable = false;
        public $sData = false;
        
        protected $_bDebug = true;
    
        /**
         * filename of sqlite database file
         * @var type 
         */
        private $_dbfile = false;
    
        /**
         * database connection
         * @var object
         */
        protected $_oDB = false;
    
        /**
         * TTL vor stored values - 1 day [sec]
         * @var integer
         */
        protected $_iTTL = 86400;
    
        /**
         * create statement for the database
         * @var type 
         */
        private $_sCreate = '
            CREATE TABLE "values" (
              `id` INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL  UNIQUE ,
              `time` DATETIME,
              `project` TEXT,
              `package` TEXT,
              `phase` TEXT,
              `place` TEXT,
              `host` TEXT,
              `variable` TEXT,
              `data` TEXT,
              UNIQUE (project, package, phase, place, host, variable) ON CONFLICT REPLACE
            );'
        ;
        
        // hardcoded
        protected $_allowedPhases=array('preview', 'stage', 'live');
        protected $_allowedPlaces=array('onhold', 'ready2install', 'deployed');
        
        // ----------------------------------------------------------------------
        // CONSTRUCTOR
        // ----------------------------------------------------------------------
        
        /**
         * constructor ... no params
         */
        public function __construct(){
            
            // cache dir is hardcoded to versions directory :-/
            $this->_dbfile = __DIR__ . '/../data/versioncache.db';
            
            $this->_oDB = new PDO("sqlite:" . $this->_dbfile);
            if (!file_exists($this->_dbfile) || !filesize($this->_dbfile)) {
                $this->_createDb();
            }
        }
        /**
         * add a log messsage
         * @global object $oLog
         * @param  string $sMessage  messeage text
         * @param  string $sLevel    warnlevel of the given message
         * @return bool
         */
        private function log($sMessage, $sLevel = "info") {
            global $oCLog;
            if($oCLog){
                return $oCLog->add(basename(__FILE__) . " class " . __CLASS__ . " - " . $sMessage, $sLevel);
            }
            return false;
        }
        
        // ----------------------------------------------------------------------
        // PRIVATE 
        // ----------------------------------------------------------------------
    
        /**
         * create sqlite database - called in constructor if the file does not exist
         */
        private function _createDb() {
            if (file_exists($this->_dbfile)) {
                echo $this->_bDebug ? "removing existing file $this->_dbfile ...<br>\n" : '';
                unlink($this->_dbfile);
            }
            // after deleting the db file we nee to re instantiate
            echo $this->_bDebug ? "create database as file $this->_dbfile ...<br>\n" : '';
            $this->_oDB = new PDO("sqlite:" . $this->_dbfile);
            $this->_makeQuery($this->_sCreate);
            if (!file_exists($this->_dbfile)) {
                $this->_quit(__FUNCTION__ , "ERROR: unable to create sqlite database " . $this->_dbfile);
            }
            return true;
        }
    
        /**
         * execute a sql statement
         * @param string $sSql   sql statement
         * @param array  $aVars  array with values (uses PDO::prepare(); $sSql must contain placeholders :key)
         * @return database object
         */
        private function _makeQuery($sSql, $aVars=false) {
            // $this->_log(__FUNCTION__."($sSql)");
            // echo "DEBUG: executing SQL<pre>$sSql</pre>";
            $this->log("start query");
            if ($aVars && is_array($aVars)){
                $oStatement = $this->_oDB->prepare($sSql);
                $result = $oStatement->execute($aVars);
            } else {
                $result = $this->_oDB->query($sSql);
            }
            if(!$result){
                $this->log('<pre>'.print_r($this->_oDB->errorInfo()).'</pre>', 'error');
            }
            $this->log("end query - ".$sSql);
            return $result;
        }
        
        /**
         * execute a sql statement
         * @param string $sSql sql statement
         * @return array of resultset
         */
        private function _makeSelectQuery($sSql, $aKey=false) {
            // $this->_log(__FUNCTION__."($sSql)");
            // echo "DEBUG: executing select SQL<pre>$sSql</pre>";
            $this->log("start query");
            $oStatement = $this->_oDB->prepare($sSql);
            $oStatement->execute();
            $aReturn=array();
            while ($row = $oStatement->fetch(PDO::FETCH_ASSOC)) {
              if ($aKey && array_key_exists($aKey, $row)){
                $aReturn[] = $row[$aKey];
              } else {
                $aReturn[] = $row;
              }
            }        
            $this->log("end query - ".$sSql);
            return $aReturn;
        }
    
        /**
         * log error and quit. it echoes the error message on screen if debug 
         * is enabled.
         * @param string  $sFunction  name of method that throws the error
         * @param string  $sMessage   error message
         * @return boolean
         */
        private function _quit($sFunction, $sMessage){
            error_log(__CLASS__ . "::$sFunction - $sMessage " . "whereiam: " . print_r($this->whereiam(), 1));
            if ($this->_bDebug){
                echo __CLASS__ . "::$sFunction stopped.<br>\n"
                        . "whereiam: <pre>" . print_r($this->whereiam(), 1)."</pre>"
                        ;
                die($sMessage);
            } else {
                die("ERROR ... wrong usage of class ". __CLASS__);
            }
            return false;
        }
    
        // ----------------------------------------------------------------------
        // PUBLIC GETTER
        // ----------------------------------------------------------------------
        
        
        /**
         * get list of current projects
         * @return type
         */
        public function getProjects(){
            $sSql="select distinct(project) from `values`";
            return $this->_makeSelectQuery($sSql, 'project');
        }
        
        /**
         * get list of current projects
         * @return type
         */
        public function getPackages(){
            $sSql="select distinct(package) from `values`";
            return $this->_makeSelectQuery($sSql, 'package');
        }
        
        /**
         * get phases of the current project; a project must be set be set before
         * @return type
         */
        public function getPhases(){
            if (!$this->sProject && !$this->sPackage){
                $this->_quit(__FUNCTION__ , "you need to set a project first. Use the setProject() method to do so.");
            }
            $sWhere='1=1 '
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND package='"  . $this->sPackage . "' " : "")
                ;
            $sSql="select distinct(phase) from `values` WHERE $sWhere";
            return $this->_makeSelectQuery($sSql,'phase');
        }
        
        /**
         * get places of the current project; a project and must be set be set before
         * @return type
        public function getPlaces(){
            if (!$this->sProject || !$this->sPhase){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project, and phase first. Use the setProject() method to do so.");
            }
            $sWhere='1=1 '
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND phase='"    . $this->sPackage . "' " : "")
                ;
            $sSql="select distinct(phase) from `values` WHERE $sWhere";
            $sSql="select distinct(place) from `values`
                WHERE
                    project='" . $this->sProject . "'
                    AND phase='" . $this->sPhase . "'
                    ";
            return $this->_makeSelectQuery($sSql, 'place');
        }
         */
        
        /**
         * get hosts that have installed a project
         * @return type
         */
        public function getHosts(){
            $sWhere='1=1 '
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND package='"  . $this->sPackage . "' " : "")
                . ($this->sPhase   ? "AND phase='"  . $this->sPhase . "' "   : "")
                . "AND place='deployed' "
                //. "AND host>'' "
                ;
            $sSql="select distinct(host) from `values` WHERE $sWhere";
            return $this->_makeSelectQuery($sSql, 'host');
        }
    
        /**
         * get entries of the current place (project, phase and place can be
         * set before)
         * @see setProject()
         * @param string  $sVariable  variable for filtering column "variable"
         * @return array
         */
        public function getVar($sVariable=''){
            $sWhere='1=1 '
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND package='"  . $this->sPackage . "' " : "")
                . ($this->sPhase   ? "AND phase='"    . $this->sPhase   . "' " : "")
                . ($this->sPlace   ? "AND place='"    . $this->sPlace   . "' " : "")
                . ($this->sHost    ? "AND host='"     . $this->sHost    . "' " : "")
                . ($sVariable      ? "AND variable='" . $sVariable      . "' " : "")
                ;
            $sSql="select * from `values` WHERE $sWhere";
            return $this->_makeSelectQuery($sSql);
        }
        
        /**
         * get versions of the current place (project, phase and place can be
         * set before)
         * @see setProject()
         * @return array
         */
        public function getVersion(){
            $aData=$this->getVar('version');
            
            // get json in subkey host -> data and store keys in host -> _data
            if($aData && is_array($aData) && count($aData)){
                foreach($aData as $iKey=>$aHostinfos){
                    $aJson=json_decode($aHostinfos['data'], 1);
                    $aData[$iKey]['_data']=$aJson;
                }
            }
            return $aData;
        }
        
        /**
         * return currebntly set project, phase, place and host
         * @return array
         */
        public function whereiam(){
            return array(
                'project'=>$this->sProject,
                'package'=>$this->sPackage,
                'phase'=>$this->sPhase,
                'place'=>$this->sPlace,
                'host'=>$this->sHost,
            );
        }
        /**
         * return currebntly set project, phase, place and host
         * @return type
         */
        public function dumpdb(){
            $sSql="select * from `values`";
            return $this->_makeSelectQuery($sSql);
        }
        
        
        // ----------------------------------------------------------------------
        // PUBLIC SETTER
        // ----------------------------------------------------------------------
        
        /**
         * init a "position" before getting or updating deleting a value
         * 
         * @param string  $sProject  project id
         * @param string  $sPackage  package id
         * @param string  $sPhase    phase (preview|stage|live)
         * @param string  $sPlace    place (onhold|ready2install|deployed)
         * @param string  $sHost     hostname (for place deployed)
         * @return type string
         */
        public function setProject($sProject, $sPackage, $sPhase=false, $sPlace=false, $sHost=false){
            $this->sProject=preg_replace('/[^a-z\-\_0-9]/', '' ,$sProject);
            $this->setPackage($sPackage, $sPhase, $sPlace, $sHost);
            return $this->sProject;
        }
    
        /**
         * set a package (and more granular items)
         * @see setProject()
         * 
         * @param string  $sPackage  package id
         * @param string  $sPhase    phase (preview|stage|live)
         * @param string  $sPlace    place (onhold|ready2install|deployed)
         * @param string  $sHost     hostname (for place deployed)
         * @return type string
         */
        public function setPackage($sPackage, $sPhase, $sPlace=false, $sHost=false){
            $this->sPackage=preg_replace('/[^a-z\-\_0-9]/', '' ,$sPackage);
            $this->setPhase($sPhase, $sPlace, $sHost);
            return $this->sPackage;
        }
        
        /**
         * set a phase (and more granular items)
         * @see setProject()
         * 
         * @param string  $sPhase    phase (preview|stage|live)
         * @param string  $sPlace    place (onhold|ready2install|deployed)
         * @param string  $sHost     hostname (for place deployed)
         * @return type string
         */
        public function setPhase($sPhase, $sPlace=false, $sHost=false){
            if (!$this->sProject && !$this->sPackage){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project. Use the setProject() method to do so.");
                return false;
            }
            if ($sPhase && array_search($sPhase, $this->_allowedPhases)===false){
                $this->_quit(__FUNCTION__ , "ERROR: you set a wrong phase [$sPhase]");
            }
            $this->sPhase=$sPhase;
            $this->setPlace($sPlace, $sHost);
            return $this->sPhase;
        }
    
        /**
         * set a place (and host)
         * @see setProject()
         * 
         * @param string  $sPlace    place (onhold|ready2install|deployed)
         * @param string  $sHost     hostname (for place deployed)
         * @return type string
         */
        public function setPlace($sPlace, $sHost=false){
            if ((!$this->sProject && !$this->sPackage)){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project and phase. Use the setProject() method to do so.");
                return false;
            }
            if ($sPlace && !$this->sPhase){
                $this->_quit(__FUNCTION__ , "ERROR: you cannot set place [$sPlace] with leaving phase empty.");
            }
            if ($sPlace && array_search($sPlace, $this->_allowedPlaces)===false){
                $this->_quit(__FUNCTION__ , "ERROR: you set a wrong place [$sPlace]");
            }
            $this->sPlace=$sPlace;
            $this->setHost($sHost);
            return $this->sPlace;
        }
        
        /**
         * set a host for place "deployed"
         * @see setProject()
         * 
         * @param string  $sHost     hostname
         * @return type string
         */
        public function setHost($sHost=false){
            if ((!$this->sProject && !$this->sPackage)){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project, phase and place. Use the setProject() method to do so.");
                return false;
            }
            if($sHost && $this->sPlace!=='deployed'){
                $this->_quit(__FUNCTION__ , "ERROR: a host can be set on place [deployed] only.");
            }
            /*
            if(!$sHost && $this->sPlace==='deployed'){
                $this->_quit(__FUNCTION__ , "ERROR: on place [deployed] a host MUST be set.");
            }
             */
            $this->sHost=preg_replace('/[^a-z\.\-0-9]/', '', $sHost);
            return $this->sHost;
        }
        
        // ----------------------------------------------------------------------
        // DATABASE FUNCTIONS
        // ----------------------------------------------------------------------
        
        /**
         * cleanup value store
         * @param integer  $iTtl  optional: max age in seconds of items to keep; 0 to delete all; default is 1 day
         * @return boolean
         */
        public function cleanup($iTtl=false){
            if ($iTtl===false){
                $iTtl=$this->_iTTL;
            }
            $sTtlDate=date("Y-m-d H:i:s", date("U") - (int)$iTtl );
            $sSql="DELETE FROM `values` WHERE `time` < '$sTtlDate' "
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND package='"  . $this->sPackage . "' " : "")
                . ($this->sPhase   ? "AND phase='"    . $this->sPhase   . "' " : "")
                . ($this->sPlace   ? "AND place='"    . $this->sPlace   . "' " : "")
                . ($this->sHost    ? "AND host='"     . $this->sHost    . "' " : "")
                ;
            // die("$iTtl ... $sSql ... ABORT");
            $this->_makeQuery($sSql);
            $this->_makeQuery("vacuum;");
            return true;
        }
        
        /**
         * delete values from value store. You need to call setProject() to set
         * project or package and optional phase, place, host. Then call this delete
         * method.
         * @param string $sVariable  optional: limit deletion to a given variable
         * @return boolean
         */
        public function deleteValues($sVariable){
            if ((!$this->sProject && !$this->sPackage) ){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project, phase and place. use the setProject() method to do so.");
            }
            $sWhere='1=1 '
                . ($this->sProject ? "AND project='"  . $this->sProject . "' " : "")
                . ($this->sPackage ? "AND package='"  . $this->sPackage . "' " : "")
                . ($this->sPhase   ? "AND phase='"    . $this->sPhase   . "' " : "")
                . ($this->sPlace   ? "AND place='"    . $this->sPlace   . "' " : "")
                . ($this->sHost    ? "AND host='"     . $this->sHost    . "' " : "")
                . ($sVariable      ? "AND variable='" . $sVariable      . "' " : "")
                ;
            $sSql="DELETE FROM `values` WHERE $sWhere";
            // echo $sSql; 
            // return true;
            return $this->_makeQuery($sSql);
        }
        
        /**
         * update a version
         * @return boolean
         */
        public function updateVar($sVarname,$sValue){
            if ((!$this->sProject && !$this->sPackage) || !$this->sPhase || !$this->sPlace ){
                $this->_quit(__FUNCTION__ , "ERROR: you need to set a project, phase and place. use the setProject() method to do so.");
            }
    
            $this->cleanup();
            $sSql="
            INSERT into `values` (`time`, `project`, `package`, `phase`, `place`, `host`, `variable`, `data` )
            VALUES (
                '" . date("Y-m-d H:i:s") . "',
                '" . $this->sProject . "',
                '" . $this->sPackage . "',
                '" . $this->sPhase . "',
                '" . $this->sPlace . "',
                '" . $this->sHost . "',
                :variable,
                :value
            );
            ";
            return $this->_makeQuery(
                    $sSql,
                    array(
                        'variable'=>$sVarname,
                        'value'=>$sValue,
                    )
            );
        }
        /**
         * update a version value
         * @param type $sVersioninfos
         * @return boolean
         */
        public function updateVersion($sVersioninfos){
            return $this->updateVar('version', $sVersioninfos);
        }
        
    }