Compare commits

...

3 Commits

Author SHA1 Message Date
odain
b35ffb0fe9 add some error handling to have full stacktrace 2024-09-11 15:36:50 +02:00
odain
1e319f3943 add a test to reproduct the hub extension deploy issue 2024-09-11 15:36:24 +02:00
odain
cd41eda29d adapt hub code to use another env thant production 2024-09-11 15:35:17 +02:00
5 changed files with 165 additions and 31 deletions

View File

@@ -36,6 +36,7 @@ require_once(APPROOT.'core/dict.class.inc.php');
require_once(APPROOT.'setup/xmldataloader.class.inc.php'); require_once(APPROOT.'setup/xmldataloader.class.inc.php');
require_once(__DIR__.'/hubruntimeenvironment.class.inc.php'); require_once(__DIR__.'/hubruntimeenvironment.class.inc.php');
/** /**
* Overload of DBBackup to handle logging * Overload of DBBackup to handle logging
*/ */
@@ -166,7 +167,7 @@ try
$sLanguage = utils::ReadParam('language', ''); $sLanguage = utils::ReadParam('language', '');
if ($sLanguage!='') if ($sLanguage!='')
{ {
foreach (glob(APPROOT.'env-production/dictionaries/*.dict.php') as $sFilePath) foreach (glob(APPROOT.'env-'. utils::GetCurrentEnvironment(). '/dictionaries/*.dict.php') as $sFilePath)
{ {
require_once ($sFilePath); require_once ($sFilePath);
} }
@@ -256,6 +257,7 @@ try
break; break;
case 'compile': case 'compile':
SetupLog::Info('Deployment starts...'); SetupLog::Info('Deployment starts...');
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data'); $sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
if (!file_exists(APPROOT.'data/hub/compile_authent') || $sAuthent !== file_get_contents(APPROOT.'data/hub/compile_authent')) if (!file_exists(APPROOT.'data/hub/compile_authent') || $sAuthent !== file_get_contents(APPROOT.'data/hub/compile_authent'))
@@ -266,13 +268,13 @@ try
$aSelectedExtensionCodes = utils::ReadParam('extension_codes', array()); $aSelectedExtensionCodes = utils::ReadParam('extension_codes', array());
$aSelectedExtensionDirs = utils::ReadParam('extension_dirs', array()); $aSelectedExtensionDirs = utils::ReadParam('extension_dirs', array());
$oRuntimeEnv = new HubRunTimeEnvironment('production', false); // use a temp environment: production-build $oRuntimeEnv = new HubRunTimeEnvironment(utils::GetCurrentEnvironment(), false); // use a temp environment: production-build
$oRuntimeEnv->MoveSelectedExtensions(APPROOT.'/data/downloaded-extensions/', $aSelectedExtensionDirs); $oRuntimeEnv->MoveSelectedExtensions(APPROOT.'/data/downloaded-extensions/', $aSelectedExtensionDirs);
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE); $oConfig = new Config(APPCONF.utils::GetCurrentEnvironment().'/'.ITOP_CONFIG_FILE);
if ($oConfig->Get('demo_mode')) throw new Exception('Sorry the installation of extensions is not allowed in demo mode'); 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 $aSelectModules = $oRuntimeEnv->CompileFrom(utils::GetCurrentEnvironment(), false); // WARNING symlinks does not seem to be compatible with manual Commit
$oRuntimeEnv->UpdateIncludes($oConfig); $oRuntimeEnv->UpdateIncludes($oConfig);
@@ -295,7 +297,7 @@ try
case 'move_to_production': case 'move_to_production':
// Second step: update the schema and the data // Second step: update the schema and the data
// Everything happening below is based on env-production // Everything happening below is based on env-production
$oRuntimeEnv = new RunTimeEnvironment('production', true); $oRuntimeEnv = new RunTimeEnvironment(utils::GetCurrentEnvironment(), true);
try try
{ {
@@ -307,7 +309,7 @@ try
} }
unlink(APPROOT.'data/hub/compile_authent'); unlink(APPROOT.'data/hub/compile_authent');
// Load the "production" config file to clone & update it // Load the "production" config file to clone & update it
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE); $oConfig = new Config(APPCONF.utils::GetCurrentEnvironment().'/'.ITOP_CONFIG_FILE);
SetupUtils::EnterReadOnlyMode($oConfig); SetupUtils::EnterReadOnlyMode($oConfig);
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */); $oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
@@ -375,7 +377,7 @@ try
unlink(APPROOT.'data/hub/compile_authent'); unlink(APPROOT.'data/hub/compile_authent');
} }
// Note: at this point, the dictionnary is not necessarily loaded // Note: at this point, the dictionnary is not necessarily loaded
SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage()); SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted'), null, [$e->getMessage(), $e->getTraceAsString()]);
SetupLog::Error('Debug trace: '.$e->getTraceAsString()); SetupLog::Error('Debug trace: '.$e->getTraceAsString());
ReportError($e->getMessage(), $e->getCode()); ReportError($e->getMessage(), $e->getCode());
} }
@@ -391,7 +393,7 @@ try
} }
catch (Exception $e) catch (Exception $e)
{ {
SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage()); SetupLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted'), null, [$e->getMessage(), $e->getTraceAsString()]);
SetupLog::Error('Debug trace: '.$e->getTraceAsString()); SetupLog::Error('Debug trace: '.$e->getTraceAsString());
utils::PopArchiveMode(); utils::PopArchiveMode();

View File

@@ -20,7 +20,7 @@ function DisplayStatus(WebPage $oPage)
if (is_dir($sPath)) { if (is_dir($sPath)) {
$aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory $aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory
} }
$oExtensionsMap = new iTopExtensionsMap('production', true, $aExtraDirs); $oExtensionsMap = new iTopExtensionsMap(utils::GetCurrentEnvironment(), true, $aExtraDirs);
$oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig());
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) { foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) {
@@ -156,7 +156,7 @@ function DoInstall(WebPage $oPage)
if (is_dir($sPath)) { if (is_dir($sPath)) {
$aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory $aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory
} }
$oExtensionsMap = new iTopExtensionsMap('production', true, $aExtraDirs); $oExtensionsMap = new iTopExtensionsMap(utils::GetCurrentEnvironment(), true, $aExtraDirs);
$oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig());
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) { foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) {

View File

@@ -27,7 +27,11 @@ require_once(APPROOT.'core/metamodel.class.php');
IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST); IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST);
utils::InitTimeZone(); utils::InitTimeZone();
set_error_handler(function ($errno, $errstr) {
$e = new \Exception("");
\SetupLog::Error("Catching", null, [$e->getMessage(), $e->getTraceAsString()]);
echo $e->getMessage() . '<BR>' .$e->getTraceAsString();
}, E_WARNING);
/** /**
* @param string $sPagePath full path (if symlink, it will be resolved) * @param string $sPagePath full path (if symlink, it will be resolved)

View File

@@ -0,0 +1,128 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Hub;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\UI\Base\iUIBlockFactory;
use Combodo\iTop\Service\InterfaceDiscovery\InterfaceDiscovery;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class HubSetupTest extends ItopDataTestCase {
const USE_TRANSACTION = false;
public function setUp() : void {
parent::setUp();
$this->RequireOnceItopFile("application/utils.inc.php");
$this->RequireOnceItopFile("core/log.class.inc.php");
$this->RequireOnceItopFile("setup/runtimeenv.class.inc.php");
$this->RequireOnceItopFile("setup/backup.class.inc.php");
$this->RequireOnceItopFile("core/mutex.class.inc.php");
$this->RequireOnceItopFile("core/dict.class.inc.php");
$this->RequireOnceItopFile("setup/xmldataloader.class.inc.php");
$this->RequireOnceItopFile("datamodels/2.x/itop-hub-connector/hubruntimeenvironment.class.inc.php");
}
public function testSetupViaHub() {
$sEnvironment = 'test';
$_REQUEST['switch_env']=$sEnvironment;
Session::Set('itop_env', $sEnvironment);
require_once (APPROOT.'/application/startup.inc.php');
require_once (APPROOT.'/application/loginwebpage.class.inc.php');
/*$aSelectedExtensionCodes = ['molkobain-datacenter-view'];
$aSelectedExtensionDirs = $aSelectedExtensionCodes;
ini_set('display_errors', 1);
$oRuntimeEnv = new \HubRunTimeEnvironment($sEnvironment, false); // use a temp environment: production-build
$oRuntimeEnv->MoveSelectedExtensions(APPROOT.'/data/downloaded-extensions/', $aSelectedExtensionDirs);
$oConfig = new \Config(APPCONF."$sEnvironment/".ITOP_CONFIG_FILE);
$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();*/
/*$sPath = APPROOT.'data/downloaded-extensions/';
$aExtraDirs = array();
if (is_dir($sPath)) {
$aExtraDirs[] = $sPath; // Also read the extra downloaded-modules directory
}
$oExtensionsMap = new \iTopExtensionsMap($sEnvironment, true, $aExtraDirs);*/
//InterfaceDiscovery::GetInstance()->FindItopClasses(iUIBlockFactory::class);
$sPassword = "abCDEF12345@";
/** @var User oUser */
$this->oUser = $this->CreateContactlessUser('login' . uniqid(),
ItopDataTestCase::$aURP_Profiles['Administrator'],
$sPassword
);
$sLogin = $this->oUser->Get('login');
$aPostFields = [
'auth_user' => $sLogin,
'auth_pwd' => $sPassword,
];
//$oConfig = new \Config();
$sConfigPath = APPCONF . "$sEnvironment/config-itop.php"; //$oConfig->GetLoadedFile();
@chmod($sConfigPath, 0770);
//$oConfig->WriteToFile($sConfigPath);
//@chmod($sConfigPath, 0440);
$sOutput = $this->CallItopUrl("/pages/exec.php?exec_module=itop-hub-connector&exec_page=ajax.php&switch_env=$sEnvironment&exec_env=$sEnvironment&maintenance=1",
[
'auth_user' => $sLogin,
'auth_pwd' => $sPassword,
'operation' => "compile",
'extension_codes[]' => "molkobain-datacenter-view",
'extension_dirs[]' => "molkobain-datacenter-view",
'authent' => '14b5da9d092f84044187421419a0347e7317bc8cd2b486fdda631be06b959269',
]);
/*$sOutput = $this->CallItopUrl("/pages/exec.php?exec_module=itop-hub-connector&exec_page=land.php&switch_env=$sEnvironment&exec_env=$sEnvironment&operation=install",
$aPostFields);*/
//var_dump($sOutput);
$aRes = json_decode($sOutput, true);
$this->assertNotNull($aRes, "output should be a json without any warning:" . PHP_EOL . $sOutput);
}
protected function CallItopUrl($sUri, ?array $aPostFields = null, $bXDebugEnabled = false)
{
$ch = curl_init();
if ($bXDebugEnabled) {
curl_setopt($ch, CURLOPT_COOKIE, 'XDEBUG_SESSION=phpstorm');
}
$sUrl = \MetaModel::GetConfig()->Get('app_root_url')."/$sUri";
var_dump($sUrl);
curl_setopt($ch, CURLOPT_URL, $sUrl);
curl_setopt($ch, CURLOPT_POST, 1);// set post data to true
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$sOutput = curl_exec($ch);
//echo "$sUrl error code:".curl_error($ch);
curl_close($ch);
return $sOutput;
}
}