/** * {@inheritdoc} * @see AbstractUpdate::__construct() */ public function __construct(\SplFileInfo $fileInfo, \ArrayObject $collection) { parent::__construct($fileInfo, $collection); $timestamp = (new DateTime())->getTimestamp(); $this->temporary = "{$this->origin}_temporary_{$timestamp}"; $this->backup = "{$this->origin}_backup_{$timestamp}"; }
/** * UpdateCrypto * * {@inheritdoc} */ public function __construct(SplFileInfo $fileInfo, ArrayObject $collection) { parent::__construct($fileInfo, $collection); $this->source = \Scalr::getContainer()->crypto(MCRYPT_TRIPLEDES, MCRYPT_MODE_CFB, null, 24, 8); $this->globals = \Scalr::getContainer()->crypto(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB, null, mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB)); $this->target = \Scalr::getContainer()->crypto; }
/** * Applies update * * @param AbstractUpdate $upd Update to apply * * @return bool Returns true if update is successful, false otherwise * * @throws Exception\UpgradeException */ protected function applyUpdate(AbstractUpdate $upd) { if (!isset($this->attempts[$upd->getUuidHex()])) { $this->attempts[$upd->getUuidHex()] = 1; } else { $this->attempts[$upd->getUuidHex()]++; } if ($this->attempts[$upd->getUuidHex()] > self::MAX_ATTEMPTS) { throw new Exception\UpgradeException(sprintf('"%s" Failed due to infinity loop. Max number of attempts (%d) reached!', $upd->getName(), self::MAX_ATTEMPTS)); } $refuseReason = $upd->isRefused(); if (false !== $refuseReason) { if ($this->opt->verbosity) { $this->console->notice('%s is ignored. %s', $upd->getName(), (string) $refuseReason); } return true; } if ($upd->getStatus() == AbstractUpgradeEntity::STATUS_OK) { //Upgrade file is updated. $upd->updateAppears(); if (isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC && $this->opt->uuid == $upd->getUuidHex()) { //User has requested re-execution of update $upd->setStatus(AbstractUpgradeEntity::STATUS_PENDING); $upd->updateHash(); $upd->getEntity()->save(); } else { //Compare checksum if ($upd->getEntity()->hash == $upd->getHash()) { //file modified time could be the issue $upd->updateApplied(); $upd->getEntity()->save(); if (!empty($this->opt->verbosity) || isset($this->opt->cmd) && $this->opt->cmd == self::CMD_RUN_SPECIFIC && $this->opt->uuid == $upd->getUuidHex()) { $this->console->warning('Ingnoring %s because of having complete status.', $upd->getName()); } return true; } else { //We should ignore changes in the script and update hash $upd->updateHash(); $upd->getEntity()->save(); return true; } } } $this->console->success('%s...', $upd->description ?: $upd->getName()); //Checks updates this upgrade depends upon if (!empty($upd->depends)) { foreach ($upd->depends as $uuid) { $uuidhex = AbstractUpdate::castUuid($uuid); if (!empty($this->updates[$uuidhex])) { $update = $this->updates[$uuidhex]; if ($update->getStatus() == AbstractUpgradeEntity::STATUS_OK) { //Relative update has already been successfully applied. continue; } } else { if (isset($this->stateBefore[$uuidhex])) { /* @var $upgradeEntity \Scalr\Upgrade\Entity\AbstractUpgradeEntity */ $upgradeEntity = $this->stateBefore[$uuidhex]; if ($upgradeEntity->status == AbstractUpgradeEntity::STATUS_OK) { //Relative update has already been applied continue; } else { //Relative update needs to be applied before dependant. $this->console->warning('"%s" has been declined as it depends on incomplete update "%s" which has status "%s". ' . 'Desired class "%s" does not exist in the expected folder.', $upd->getName(), $uuid, $upgradeEntity->getStatusName(), $upgradeEntity->getUpdateClassName()); return false; } } else { //Relative update has not been delivered yet. $this->console->warning('"%s" has been postponed as it depends on "%s" which has not been delivered yet.', $upd->getName(), $uuid); return false; } } if ($update->getStatus() == AbstractUpgradeEntity::STATUS_FAILED && isset($this->recurrences[$update->getUuidHex()])) { //Recurrence of the failed status. We don't need to report about it again. $this->console->warning('"%s" has been declined because of failure dependent update "%s".', $upd->getName(), $uuid); return false; } //Relative update has not been applied or it has incomplete status. //We need to apply it first. if ($this->applyUpdate($update) === false) { $this->console->warning('"%s" has been declined. Could not apply related update "%s".', $upd->getName(), $update->getName()); return false; } } } //Checks if update class implements SequenceInterface $stages = $upd instanceof SequenceInterface ? range(1, $upd->getNumberStages()) : array(1); $skip = 0; foreach ($stages as $stage) { //Checks if update is applied if ($upd->isApplied($stage)) { $upd->console->warning('Skips over the stage %d of update %s because it has already been applied.', $stage, $upd->getName()); $skip++; continue; } //Validates environment before applying if (!$upd->validateBefore($stage)) { $this->console->error('Error. Stage %d of update %s could not be applied because of invalid environment! validateBefore(%d) returned false.', $stage, $upd->getName(), $stage); return false; } //Applies the update try { $upd->run($stage); } catch (\Exception $e) { //We should avoid repetition when another update depends on failed. $this->recurrences[$upd->getUuidHex()] = true; $upd->setStatus(AbstractUpgradeEntity::STATUS_FAILED); $upd->console->error('Error. Stage %d of update %s failed! %s', $stage, $upd->getName(), $e->getMessage()); $upd->getEntity()->save(); $upd->getEntity()->createFailureMessage($upd->console->getLog()); return false; } } $this->console->success("%s - OK", $upd->description ?: $upd->getName()); $upd->setStatus(AbstractUpgradeEntity::STATUS_OK); $upd->updateHash(); $upd->updateApplied(); $upd->getEntity()->save(); return true; }