Overview

Namespaces

  • GAubry
    • ErrorHandler
    • Helpers
    • Logger
    • Shell
  • Himedia
    • Padocc
      • DB
      • Minifier
      • Numbering
      • Properties
      • Task
        • Base
        • Extended
  • None
  • Psr
    • Log

Classes

  • AttributeProperties
  • Deployment
  • DeploymentStatus
  • DIContainer
  • Padocc
  • Task

Interfaces

  • DIContainerInterface
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: namespace Himedia\Padocc;
  4: 
  5: use GAubry\Helpers\Helpers;
  6: use GAubry\Logger\ColoredIndentedLogger;
  7: use GAubry\Shell\ShellAdapter;
  8: use Himedia\Padocc\DB\DeploymentMapper;
  9: use Himedia\Padocc\DB\PDOAdapter;
 10: use Himedia\Padocc\Task\Base\Project;
 11: use Himedia\Padocc\Task\Base\Target;
 12: 
 13: /**
 14:  * API
 15:  *
 16:  * @package Himedia\Padocc
 17:  */
 18: class Padocc
 19: {
 20: 
 21:     /**
 22:      * @var array
 23:      */
 24:     private $aConfig;
 25: 
 26:     private $oDeploymentMapper;
 27: 
 28:     public function __construct (array $aConfig)
 29:     {
 30:         $this->aConfig = $aConfig;
 31:         $oDB = PDOAdapter::getInstance($this->aConfig['Himedia\Padocc']['db']);
 32:         $this->oDeploymentMapper = new DeploymentMapper($oDB);
 33:     }
 34: 
 35:     /**
 36:      * Return environments and external properties of specified project.
 37:      *
 38:      * Example: array(
 39:      *     'dev' => array(),
 40:      *     'qa' => array(
 41:      *         'ref' => "Branch or tag to deploy",
 42:      *         …
 43:      *     )
 44:      * )
 45:      *
 46:      * @param string $sXmlProject XML project path or XML data
 47:      * @return array environments and external properties of specified project.
 48:      */
 49:     public function getEnvAndExtParameters ($sXmlProject)
 50:     {
 51:         $aEnv = Target::getAvailableEnvsList($sXmlProject);
 52:         return $aEnv;
 53:     }
 54: 
 55:     /**
 56:      * Return triplet containing DB record of specified exec_id, content of execution log, and errors.
 57:      *
 58:      * @param $sExecId
 59:      * @return array triplet containing DB record of specified exec_id, content of execution log, and errors.
 60:      * @throws \RuntimeException if info log or error log not found
 61:      */
 62:     public function getStatus ($sExecId)
 63:     {
 64:         $aFilter = array(
 65:             array(
 66:                 array('exec_id' => $sExecId)
 67:             )
 68:         );
 69:         $aResult = $this->oDeploymentMapper->select($aFilter);
 70:         $aRecord = $aResult[0];
 71: 
 72:         if ($aRecord['status'] == DeploymentStatus::QUEUED) {
 73:             $sInfoLog = '';
 74:             $sErrorLog = '';
 75:         } else {
 76:             $sInfoLogPath = sprintf($this->aConfig['Himedia\Padocc']['info_log_path_pattern'], $sExecId);
 77:             if (! file_exists($sInfoLogPath)) {
 78:                 throw new \RuntimeException("File not found: '$sInfoLogPath'!");
 79:             }
 80:             $sInfoLog = file_get_contents($sInfoLogPath);
 81: 
 82:             $sErrorLogPath = sprintf($this->aConfig['Himedia\Padocc']['error_log_path_pattern'], $sExecId);
 83:             if (! file_exists($sErrorLogPath)) {
 84:                 throw new \RuntimeException("File not found: '$sErrorLogPath'!");
 85:             }
 86:             $sErrorLog = file_get_contents($sErrorLogPath);
 87:         }
 88: 
 89:         return array(
 90:             'record'    => $aRecord,
 91:             'info-log'  => $sInfoLog,
 92:             'error-log' => $sErrorLog
 93:         );
 94:     }
 95: 
 96:     public function getQueueAndRunning ()
 97:     {
 98:         $aFilter = array(
 99:             array(
100:                 array('status' => DeploymentStatus::QUEUED),
101:                 array('status' => DeploymentStatus::IN_PROGRESS)
102:             )
103:         );
104:         $aResult = $this->oDeploymentMapper->select($aFilter, array('exec_id ASC'));
105:         return $aResult;
106:     }
107: 
108:     public function getLatestDeployments ($sProjectName, $sEnvName)
109:     {
110:         $aFilter = array(
111:             array(
112:                 array('status' => DeploymentStatus::SUCCESSFUL),
113:                 array('status' => DeploymentStatus::WARNING),
114:                 array('status' => DeploymentStatus::FAILED)
115:             )
116:         );
117:         if (! empty($sProjectName)) {
118:             $aFilter[] = array(array('project_name' => $sProjectName));
119:         }
120:         if (! empty($sEnvName)) {
121:             $aFilter[] = array(array('env_name' => $sEnvName));
122:         }
123:         $aResult = $this->oDeploymentMapper->select($aFilter, array('exec_id ASC'));
124:         return $aResult;
125:     }
126: 
127:     /**
128:      * Exécute le déploiement sans supervisor et sans trace en DB.
129:      *
130:      * @param string $sXmlProjectPath chemin vers le XML de configuration du projet
131:      * @param string $sEnvName
132:      * @param string $sExecutionID au format YYYYMMDDHHMMSS_xxxxx, où x est un nombre aléatoire,
133:      * par exemple '20111026142342_07502'
134:      * @param array $aExternalProperties tableau associatif nom/valeur des propriétés externes.
135:      * @param string $sRollbackID identifiant de déploiement sur lequel effectuer un rollback,
136:      * par exemple '20111026142342_07502'
137:      */
138:     public function runWOSupervisor (
139:         $sXmlProjectPath,
140:         $sEnvName,
141:         $sExecutionID,
142:         array $aExternalProperties,
143:         $sRollbackID
144:     ) {
145:         // Build dependency injection container
146:         $oLogger      = new ColoredIndentedLogger($this->aConfig['GAubry\Logger\ColoredIndentedLogger']);
147:         $oShell       = new ShellAdapter($oLogger, $this->aConfig['GAubry\Shell']);
148:         $oDIContainer = new DIContainer();
149:         $oDIContainer
150:             ->setLogger($oLogger)
151:             ->setShellAdapter($oShell)
152:             ->setPropertiesAdapter(new Properties\Adapter($oShell, $this->aConfig['Himedia\Padocc']))
153:             ->setNumberingAdapter(new Numbering\Adapter())
154:             ->setConfig($this->aConfig['Himedia\Padocc']);
155: 
156:         $oDeployment = new Deployment($oDIContainer);
157:         $oDeployment->run($sXmlProjectPath, $sEnvName, $sExecutionID, $aExternalProperties, $sRollbackID);
158:     }
159: 
160:     public function enqueue ($sXmlProjectPath, $sEnvName, array $aExternalProperties)
161:     {
162:         $sExecId = date('YmdHis') . sprintf('_%05d', rand(0, 99999));
163:         $oProject = Project::getSXEProject($sXmlProjectPath);
164:         $sProjectName = (string)$oProject['name'];
165:         $aParameters = array(
166:             'exec_id' => $sExecId,
167:             'xml_path' => $sXmlProjectPath,
168:             'project_name' => $sProjectName,
169:             'env_name' => $sEnvName,
170:             'external_properties' => json_encode($aExternalProperties),
171:             'status' => DeploymentStatus::QUEUED,
172:             'nb_warnings' => 0,
173:             'date_queue' => date('Y-m-d H:i:s'),
174:             'is_rollbackable' => 0
175:         );
176:         $this->oDeploymentMapper->insert($aParameters);
177:         return $sExecId;
178:     }
179: 
180:     public function dequeue ()
181:     {
182:         $aFilter = array(
183:             array(
184:                 array('status' => DeploymentStatus::QUEUED)
185:             )
186:         );
187:         $aResult = $this->oDeploymentMapper->select($aFilter, array('exec_id ASC'), 1);
188: 
189:         if (count($aResult) > 0) {
190:             $aOldestQueued = $aResult[0];
191:             var_dump($aOldestQueued);
192: 
193:             $sExecId = $this->run(
194:                 $aOldestQueued['xml_path'],
195:                 $aOldestQueued['env_name'],
196:                 $aOldestQueued['exec_id'],
197:                 json_decode($aOldestQueued['external_properties'], true),
198:                 ''
199:             );
200:         } else {
201:             $sExecId = '';
202:         }
203:         return $sExecId;
204:     }
205: 
206:     /**
207:      * Exécute le déploiement avec supervisor et avec trace en DB.
208:      *
209:      * @param string $sXmlProjectPath chemin vers le XML de configuration du projet
210:      * @param string $sEnvName
211:      * @param string $sExecId au format YYYYMMDDHHMMSS_xxxxx, où x est un nombre aléatoire,
212:      * par exemple '20111026142342_07502'. Si vide, en génère un.
213:      * @param array $aExternalProperties tableau associatif nom/valeur des propriétés externes.
214:      * @param string $sRollbackID identifiant de déploiement sur lequel effectuer un rollback,
215:      * par exemple '20111026142342_07502'
216:      * @return string $sExecutionID
217:      * @throws \RuntimeException if Supervisor log result are unexpected.
218:      */
219:     public function run ($sXmlProjectPath, $sEnvName, $sExecId, array $aExternalProperties, $sRollbackID)
220:     {
221:         $aFilter = array(
222:             array(
223:                 array('exec_id' => $sExecId)
224:             )
225:         );
226:         $aResult = $this->oDeploymentMapper->select($aFilter);
227:         $bAlreadyInDB = (count($aResult) === 1);
228: 
229:         if (empty($sExecId)) {
230:             $sExecId = date('YmdHis') . sprintf('_%05d', rand(0, 99999));
231:         }
232:         $oProject = Project::getSXEProject($sXmlProjectPath);
233:         $sProjectName = (string)$oProject['name'];
234:         $aParameters = array(
235:             'exec_id' => $sExecId,
236:             'xml_path' => $sXmlProjectPath,
237:             'project_name' => $sProjectName,
238:             'env_name' => $sEnvName,
239:             'external_properties' => json_encode($aExternalProperties),
240:             'status' => DeploymentStatus::IN_PROGRESS,
241:             'nb_warnings' => 0,
242:             'date_start' => date('Y-m-d H:i:s'),
243:             'is_rollbackable' => 0
244:         );
245:         if ($bAlreadyInDB) {
246:             $this->oDeploymentMapper->update($aParameters);
247:         } else {
248:             $this->oDeploymentMapper->insert($aParameters);
249:         }
250: 
251:         $sSupervisorBin = $this->aConfig['Himedia\Padocc']['dir']['vendor'] . '/bin/supervisor.sh';
252:         $sSupervisorParams = '--conf=' . $this->aConfig['Himedia\Padocc']['supervisor_config'] . ' '
253:                            . "--exec-id=$sExecId";
254:         $sPadoccBin = $this->aConfig['Himedia\Padocc']['dir']['src'] . '/padocc.php';
255:         $sPadoccParams = "--action=deploy-wos --xml=$sXmlProjectPath --env=$sEnvName --exec-id=$sExecId";
256:         foreach ($aExternalProperties as $sName => $sValue) {
257:             $sPadoccParams .= " -p $sName='$sValue'";
258:         }
259:         $sCmd = "$sSupervisorBin $sSupervisorParams $sPadoccBin \"$sPadoccParams\"";
260:         var_dump($sCmd);
261: 
262:         $handle = popen($sCmd, 'r');
263:         while (! feof($handle)) {
264:             set_time_limit(100);
265:             $results = fgets($handle, 256);
266:             if (strlen($results) > 0) {
267:                 echo $results;
268:             }
269:         }
270: 
271:         $sInfoLogPath = sprintf($this->aConfig['Himedia\Padocc']['info_log_path_pattern'], $sExecId);
272:         $aResult = Helpers::exec("tail -n1 '$sInfoLogPath'");
273:         if (preg_match(
274:             '/^[0-9 :-]{22}cs;\[SUPERVISOR\] (OK|ERROR|WARNING \(#(\d+)\))\s*$/',
275:             $aResult[0],
276:             $aMatches
277:         ) !== 1) {
278:             throw new \RuntimeException("Supervisor log result unexpected! Log file: '$sInfoLogPath'.");
279:         } elseif ($aMatches[1] == 'OK') {
280:             $sStatus = DeploymentStatus::SUCCESSFUL;
281:             $iNbWarnings = 0;
282:         } elseif ($aMatches[1] == 'ERROR') {
283:             $sStatus = DeploymentStatus::FAILED;
284:             $iNbWarnings = 0;
285:         } else {
286:             $sStatus = DeploymentStatus::WARNING;
287:             $iNbWarnings = $aMatches[2];
288:         }
289:         $aParameters = array(
290:             'exec_id' => $sExecId,
291:             'status' => $sStatus,
292:             'nb_warnings' => $iNbWarnings,
293:             'date_end' => date('Y-m-d H:i:s')
294:         );
295:         $this->oDeploymentMapper->update($aParameters);
296:         return $sExecId;
297:     }
298: }
299: 
Platform for Automatized Deployments with pOwerful Concise Configuration API documentation generated by ApiGen 2.8.0