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: 15: 16: 17:
18: class Padocc
19: {
20:
21: 22: 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: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48:
49: public function getEnvAndExtParameters ($sXmlProject)
50: {
51: $aEnv = Target::getAvailableEnvsList($sXmlProject);
52: return $aEnv;
53: }
54:
55: 56: 57: 58: 59: 60: 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: 129: 130: 131: 132: 133: 134: 135: 136: 137:
138: public function runWOSupervisor (
139: $sXmlProjectPath,
140: $sEnvName,
141: $sExecutionID,
142: array $aExternalProperties,
143: $sRollbackID
144: ) {
145:
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: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 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: