mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 00:02:17 +02:00
N°8981: prepare hub connector test cover
sdk test enhancement : add call itop api fix ci ci: fix broken tests ci: cover hub setup on compile and launch steps code style ci: fix ModuleDiscoveryTest redundant class + add logs to investigate ci setup issues ci: fix log during setup tests
This commit is contained in:
@@ -24,129 +24,13 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\WebPage\JsonPage;
|
||||
use Combodo\iTop\HubConnector\Controller\HubController;
|
||||
|
||||
require_once(APPROOT.'application/utils.inc.php');
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
IssueLog::Enable(APPROOT.'log/error.log');
|
||||
|
||||
require_once(APPROOT.'setup/runtimeenv.class.inc.php');
|
||||
require_once(APPROOT.'setup/backup.class.inc.php');
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
require_once(APPROOT.'core/dict.class.inc.php');
|
||||
require_once(APPROOT.'setup/xmldataloader.class.inc.php');
|
||||
require_once(__DIR__.'/hubruntimeenvironment.class.inc.php');
|
||||
|
||||
/**
|
||||
* Overload of DBBackup to handle logging
|
||||
*/
|
||||
class DBBackupWithErrorReporting extends DBBackup
|
||||
{
|
||||
protected $aInfos = [];
|
||||
|
||||
protected $aErrors = [];
|
||||
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
$aInfos[] = $sMsg;
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
IssueLog::Error($sMsg);
|
||||
$aErrors[] = $sMsg;
|
||||
}
|
||||
|
||||
public function GetInfos()
|
||||
{
|
||||
return $this->aInfos;
|
||||
}
|
||||
|
||||
public function GetErrors()
|
||||
{
|
||||
return $this->aErrors;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $sTargetFile
|
||||
* @throws Exception
|
||||
* @return DBBackupWithErrorReporting
|
||||
*/
|
||||
function DoBackup($sTargetFile)
|
||||
{
|
||||
// Make sure the target directory exists
|
||||
$sBackupDir = dirname($sTargetFile);
|
||||
SetupUtils::builddir($sBackupDir);
|
||||
|
||||
$oBackup = new DBBackupWithErrorReporting();
|
||||
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
||||
$sSourceConfigFile = APPCONF.utils::GetCurrentEnvironment().'/'.ITOP_CONFIG_FILE;
|
||||
|
||||
$oMutex = new iTopMutex('backup.'.utils::GetCurrentEnvironment());
|
||||
$oMutex->Lock();
|
||||
try {
|
||||
$oBackup->CreateCompressedBackup($sTargetFile, $sSourceConfigFile);
|
||||
} catch (Exception $e) {
|
||||
$oMutex->Unlock();
|
||||
throw $e;
|
||||
}
|
||||
$oMutex->Unlock();
|
||||
return $oBackup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the status of the current ajax execution (as a JSON structure)
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param bool $bSuccess
|
||||
* @param number $iErrorCode
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportStatus($sMessage, $bSuccess, $iErrorCode = 0, $aMoreFields = [])
|
||||
{
|
||||
// Do not use AjaxPage during setup phases, because it uses InterfaceDiscovery in Twig compilation
|
||||
$oPage = new JsonPage();
|
||||
$aResult = [
|
||||
'code' => $iErrorCode,
|
||||
'message' => $sMessage,
|
||||
'fields' => $aMoreFields,
|
||||
];
|
||||
$oPage->SetData($aResult);
|
||||
$oPage->SetOutputDataOnly(true);
|
||||
$oPage->output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to output the status of a successful execution
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportSuccess($sMessage, $aMoreFields = [])
|
||||
{
|
||||
ReportStatus($sMessage, true, 0, $aMoreFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to output the status of a failed execution
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param number $iErrorCode
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportError($sMessage, $iErrorCode, $aMoreFields = [])
|
||||
{
|
||||
if ($iErrorCode == 0) {
|
||||
// 0 means no error, so change it if no meaningful error code is supplied
|
||||
$iErrorCode = -1;
|
||||
}
|
||||
ReportStatus($sMessage, false, $iErrorCode, $aMoreFields);
|
||||
}
|
||||
require_once(__DIR__.'/src/Controller/HubController.php');
|
||||
|
||||
try {
|
||||
SetupUtils::ExitMaintenanceMode(false); // Reset maintenance mode in case of problem
|
||||
@@ -183,7 +67,7 @@ try {
|
||||
foreach ($aChecks as $oCheckResult) {
|
||||
if ($oCheckResult->iSeverity == CheckResult::ERROR) {
|
||||
$bFailed = true;
|
||||
ReportError($oCheckResult->sLabel, -2);
|
||||
HubController::GetInstance()->ReportError($oCheckResult->sLabel, -2);
|
||||
}
|
||||
}
|
||||
if (!$bFailed) {
|
||||
@@ -191,160 +75,27 @@ try {
|
||||
$fFreeSpace = SetupUtils::CheckDiskSpace($sDBBackupPath);
|
||||
if ($fFreeSpace !== false) {
|
||||
$sMessage = Dict::Format('iTopHub:BackupFreeDiskSpaceIn', SetupUtils::HumanReadableSize($fFreeSpace), dirname($sDBBackupPath));
|
||||
ReportSuccess($sMessage);
|
||||
HubController::GetInstance()->ReportSuccess($sMessage);
|
||||
} else {
|
||||
ReportError(Dict::S('iTopHub:FailedToCheckFreeDiskSpace'), -1);
|
||||
HubController::GetInstance()->ReportError(Dict::S('iTopHub:FailedToCheckFreeDiskSpace'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'do_backup':
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
try {
|
||||
if (MetaModel::GetConfig()->Get('demo_mode')) {
|
||||
throw new Exception('Sorry the installation of extensions is not allowed in demo mode');
|
||||
}
|
||||
SetupLog::Info('Backup starts...');
|
||||
set_time_limit(0);
|
||||
$sBackupPath = APPROOT.'/data/backups/manual/backup-';
|
||||
$iSuffix = 1;
|
||||
$sSuffix = '';
|
||||
// Generate a unique name...
|
||||
do {
|
||||
$sBackupFile = $sBackupPath.date('Y-m-d-His').$sSuffix;
|
||||
$sSuffix = '-'.$iSuffix;
|
||||
$iSuffix++ ;
|
||||
} while (file_exists($sBackupFile));
|
||||
|
||||
$oBackup = DoBackup($sBackupFile);
|
||||
$aErrors = $oBackup->GetErrors();
|
||||
if (count($aErrors) > 0) {
|
||||
SetupLog::Error('Backup failed.');
|
||||
SetupLog::Error(implode("\n", $aErrors));
|
||||
ReportError(Dict::S('iTopHub:BackupFailed'), -1, $aErrors);
|
||||
} else {
|
||||
SetupLog::Info('Backup successfully completed.');
|
||||
ReportSuccess(Dict::S('iTopHub:BackupOk'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
SetupLog::Error($e->getMessage());
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
HubController::GetInstance()->LaunchBackup();
|
||||
break;
|
||||
|
||||
case 'compile':
|
||||
SetupLog::Info('Deployment starts...');
|
||||
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
|
||||
if (!file_exists(utils::GetDataPath().'hub/compile_authent') || $sAuthent !== file_get_contents(utils::GetDataPath().'hub/compile_authent')) {
|
||||
throw new SecurityException(Dict::S('iTopHub:FailAuthent'));
|
||||
}
|
||||
// First step: prepare the datamodel, if it fails, roll-back
|
||||
$aSelectedExtensionCodes = utils::ReadParam('extension_codes', []);
|
||||
$aSelectedExtensionDirs = utils::ReadParam('extension_dirs', []);
|
||||
|
||||
$oRuntimeEnv = new HubRunTimeEnvironment('production', false); // use a temp environment: production-build
|
||||
$oRuntimeEnv->MoveSelectedExtensions(APPROOT.'/data/downloaded-extensions/', $aSelectedExtensionDirs);
|
||||
|
||||
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE);
|
||||
if ($oConfig->Get('demo_mode')) {
|
||||
throw new Exception('Sorry the installation of extensions is not allowed in demo mode');
|
||||
}
|
||||
|
||||
$aSelectModules = $oRuntimeEnv->CompileFrom('production', false); // WARNING symlinks does not seem to be compatible with manual Commit
|
||||
|
||||
$oRuntimeEnv->UpdateIncludes($oConfig);
|
||||
|
||||
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
|
||||
|
||||
// Safety check: check the inter dependencies, will throw an exception in case of inconsistency
|
||||
$oRuntimeEnv->AnalyzeInstallation($oConfig, $oRuntimeEnv->GetBuildDir(), true);
|
||||
|
||||
$oRuntimeEnv->CheckMetaModel(); // Will throw an exception if a problem is detected
|
||||
|
||||
// Everything seems Ok so far, commit in env-production!
|
||||
$oRuntimeEnv->WriteConfigFileSafe($oConfig);
|
||||
$oRuntimeEnv->Commit();
|
||||
|
||||
// Report the success in a way that will be detected by the ajax caller
|
||||
SetupLog::Info('Compilation completed...');
|
||||
ReportSuccess('Ok'); // No access to Dict::S here
|
||||
HubController::GetInstance()->LaunchCompile();
|
||||
break;
|
||||
|
||||
case 'move_to_production':
|
||||
// Second step: update the schema and the data
|
||||
// Everything happening below is based on env-production
|
||||
$oRuntimeEnv = new RunTimeEnvironment('production', true);
|
||||
|
||||
try {
|
||||
SetupLog::Info('Move to production starts...');
|
||||
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
|
||||
if (!file_exists(utils::GetDataPath().'hub/compile_authent') || $sAuthent !== file_get_contents(utils::GetDataPath().'hub/compile_authent')) {
|
||||
throw new SecurityException(Dict::S('iTopHub:FailAuthent'));
|
||||
}
|
||||
unlink(utils::GetDataPath().'hub/compile_authent');
|
||||
// Load the "production" config file to clone & update it
|
||||
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE);
|
||||
SetupUtils::EnterReadOnlyMode($oConfig);
|
||||
|
||||
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
|
||||
|
||||
$aAvailableModules = $oRuntimeEnv->AnalyzeInstallation($oConfig, $oRuntimeEnv->GetBuildDir(), true);
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, 'BeforeDatabaseCreation');
|
||||
|
||||
$oRuntimeEnv->CreateDatabaseStructure($oConfig, 'upgrade');
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, 'AfterDatabaseCreation');
|
||||
|
||||
$oRuntimeEnv->UpdatePredefinedObjects();
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, 'AfterDatabaseSetup');
|
||||
|
||||
$oRuntimeEnv->LoadData($aAvailableModules, false /* no sample data*/);
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, 'AfterDataLoad');
|
||||
|
||||
// Record the installation so that the "about box" knows about the installed modules
|
||||
$sDataModelVersion = $oRuntimeEnv->GetCurrentDataModelVersion();
|
||||
|
||||
$oExtensionsMap = new iTopExtensionsMap();
|
||||
|
||||
// Default choices = as before
|
||||
$oExtensionsMap->LoadChoicesFromDatabase($oConfig);
|
||||
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) {
|
||||
// Plus all "remote" extensions
|
||||
if ($oExtension->sSource == iTopExtension::SOURCE_REMOTE) {
|
||||
$oExtensionsMap->MarkAsChosen($oExtension->sCode);
|
||||
}
|
||||
}
|
||||
$aSelectedExtensionCodes = [];
|
||||
foreach ($oExtensionsMap->GetChoices() as $oExtension) {
|
||||
$aSelectedExtensionCodes[] = $oExtension->sCode;
|
||||
}
|
||||
$aSelectedExtensions = $oExtensionsMap->GetChoices();
|
||||
$oRuntimeEnv->RecordInstallation($oConfig, $sDataModelVersion, $aAvailableModules, $aSelectedExtensionCodes, 'Done by the iTop Hub Connector');
|
||||
|
||||
// Report the success in a way that will be detected by the ajax caller
|
||||
SetupLog::Info('Deployment successfully completed.');
|
||||
ReportSuccess(Dict::S('iTopHub:CompiledOK'));
|
||||
} catch (Exception $e) {
|
||||
if (file_exists(utils::GetDataPath().'hub/compile_authent')) {
|
||||
unlink(utils::GetDataPath().'hub/compile_authent');
|
||||
}
|
||||
// Note: at this point, the dictionnary is not necessarily loaded
|
||||
SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage());
|
||||
SetupLog::Error('Debug trace: '.$e->getTraceAsString());
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
} finally {
|
||||
SetupUtils::ExitReadOnlyMode();
|
||||
}
|
||||
HubController::GetInstance()->LaunchDeploy();
|
||||
break;
|
||||
|
||||
default:
|
||||
ReportError("Invalid operation: '$sOperation'", -1);
|
||||
HubController::GetInstance()->ReportError("Invalid operation: '$sOperation'", -1);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage());
|
||||
@@ -352,5 +103,5 @@ try {
|
||||
|
||||
utils::PopArchiveMode();
|
||||
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
HubController::GetInstance()->ReportError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user