Compare commits

...

2 Commits

Author SHA1 Message Date
Eric Espie
2cc02d0cef N°9454 - Make MTT compatible with the dry run 2026-06-05 10:01:40 +02:00
Eric Espie
f63b88f31a N°9454 - Make MTT compatible with the dry run 2026-06-05 10:01:37 +02:00
13 changed files with 63 additions and 45 deletions

View File

@@ -22,7 +22,6 @@ use Combodo\iTop\Application\EventRegister\ApplicationEvents;
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Setup\ModuleDependency\Module;
use Combodo\iTop\Setup\ModuleDiscovery\ModuleFileReader;
require_once APPROOT.'core/modulehandler.class.inc.php';
@@ -4660,12 +4659,15 @@ abstract class MetaModel
* @throws \CoreException
* @throws \MySQLException
*/
public static function DBExists($bMustBeComplete = true)
public static function DBExists($bMustBeComplete = true, ?string $sDBName = null)
{
if (!CMDBSource::IsDB(self::$m_sDBName)) {
if (is_null($sDBName)) {
$sDBName = self::$m_sDBName;
}
if (!CMDBSource::IsDB($sDBName)) {
return false;
}
CMDBSource::SelectDB(self::$m_sDBName);
CMDBSource::SelectDB($sDBName);
$aFound = [];
$aMissing = [];

View File

@@ -103,6 +103,7 @@ class DataFeatureRemovalController extends Controller
'extensions_not_uninstallable' => '[]',
'copy_setup_files' => 1,
'return_button_label' => '',
'target_env' => ITOP_DEFAULT_ENV,
];
$aHiddenInputs = [];

View File

@@ -290,9 +290,9 @@ class MFCompiler
} else {
$oConfig = null;
}
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::EnterMaintenanceMode($oConfig);
}
// if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
// SetupUtils::EnterMaintenanceMode($oConfig);
// }
if ($bUseSymbolicLinks || $bSkipTempDir) {
// Skip the creation of a temporary dictionary, not compatible with symbolic links
$sTempTargetDir = $sFinalTargetDir;
@@ -313,9 +313,9 @@ class MFCompiler
// Cleanup the temporary directory
SetupUtils::rrmdir($sTempTargetDir);
}
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::ExitMaintenanceMode();
}
// if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
// SetupUtils::ExitMaintenanceMode();
// }
throw $e;
}
@@ -323,9 +323,9 @@ class MFCompiler
// Move the results to the target directory
SetupUtils::movedir($sTempTargetDir, $sFinalTargetDir);
}
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::ExitMaintenanceMode();
}
// if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
// SetupUtils::ExitMaintenanceMode();
// }
// Reset the opcache since otherwise the PHP "model" files may still be cached !!
// In case of bad luck (this happens **sometimes** - see N. 550), we may analyze the database structure

View File

@@ -15,7 +15,7 @@ class DryRemovalRuntimeEnvironment extends RunTimeEnvironment
*
* @param string $sSourceEnv: environment from which setup is inspired to simulate extension removal and usee CompileFrom...
*/
public function __construct($sSourceEnv = 'production', array $aExtensionCodesToRemove = [])
public function __construct($sSourceEnv = ITOP_DEFAULT_ENV, array $aExtensionCodesToRemove = [])
{
parent::__construct($sSourceEnv, false);
$this->aExtensionsToRemoveByCode = $aExtensionCodesToRemove;

View File

@@ -396,9 +396,11 @@ class RunTimeEnvironment
$sBuildConfigFile = APPCONF.$this->sBuildEnv.'/'.ITOP_CONFIG_FILE;
// Write the config file
@chmod($sBuildConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others
if (is_file($sBuildConfigFile)) {
chmod($sBuildConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others
}
$oConfig->WriteToFile($sBuildConfigFile);
@chmod($sBuildConfigFile, 0440); // Read-only for owner and group, nothing for others
chmod($sBuildConfigFile, 0440); // Read-only for owner and group, nothing for others
}
/**
@@ -1331,11 +1333,11 @@ class RunTimeEnvironment
public function DataToCleanupAudit()
{
$oSetupAudit = new SetupAudit(ITOP_DEFAULT_ENV, $this->sBuildEnv);
$oSetupAudit = new SetupAudit($this->GetFinalEnv(), $this->GetBuildEnv());
//Make sure the MetaModel is started before analysing for issues
$sConfFile = utils::GetConfigFilePath(ITOP_DEFAULT_ENV);
MetaModel::Startup($sConfFile, false, false); // Start on production environment
$sConfFile = utils::GetConfigFilePath($this->GetFinalEnv());
MetaModel::Startup($sConfFile, false, false); // Start on environment
$oSetupAudit->RunDataAudit(true);
$iCount = $oSetupAudit->GetDataToCleanupCount();
@@ -1471,7 +1473,7 @@ class RunTimeEnvironment
SetupUtils::tidydir($sBuildPath);
}
$oExtensionsMap = new iTopExtensionsMap(ITOP_DEFAULT_ENV, $aDirsToScan);
$oExtensionsMap = new iTopExtensionsMap($this->GetFinalEnv(), $aDirsToScan);
// Removed modules are stored as static for FindModules()
$oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes);
@@ -1572,7 +1574,7 @@ class RunTimeEnvironment
public function EnterReadOnlyMode(Config $oConfig)
{
if ($this->GetFinalEnv() != 'production') {
if ($this->GetFinalEnv() != ITOP_DEFAULT_ENV) {
return;
}
@@ -1592,7 +1594,7 @@ class RunTimeEnvironment
public function ExitReadOnlyMode()
{
if ($this->GetFinalEnv() != 'production') {
if ($this->GetFinalEnv() != ITOP_DEFAULT_ENV) {
return;
}

View File

@@ -42,7 +42,7 @@ abstract class StepSequencer
public function __construct(Parameters $oParams, ?RunTimeEnvironment $oRunTimeEnvironment = null, string $sSourceDesc = 'Setup')
{
if (is_null($oRunTimeEnvironment)) {
$sEnvironment = $oParams->Get('target_env', 'production');
$sEnvironment = $oParams->Get('target_env', ITOP_DEFAULT_ENV);
$this->oRunTimeEnvironment = new RunTimeEnvironment($sEnvironment, false);
} else {
$this->oRunTimeEnvironment = $oRunTimeEnvironment;
@@ -171,12 +171,13 @@ abstract class StepSequencer
protected function GetConfig()
{
if (! is_null($this->oTestConfig)) {
// For unit tests
return $this->oTestConfig;
}
// Caching config here is a bad idea, the first config loaded does not contain module settings
$sTargetEnvironment = $this->oRunTimeEnvironment->GetBuildEnv();
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
$sBuildEnvironment = $this->oRunTimeEnvironment->GetBuildEnv();
$sConfigFile = APPCONF.$sBuildEnvironment.'/'.ITOP_CONFIG_FILE;
try {
if (file_exists($sConfigFile)) {
$oConfig = new Config($sConfigFile);

View File

@@ -158,7 +158,7 @@ class SetupUtils
if (utils::IsModeCLI()) {
$aWritableDirs = ['log', 'data'];
} else {
$aWritableDirs = ['log', 'env-production', 'env-production-build', 'conf', 'data'];
$aWritableDirs = ['log', 'env-production', 'env-production-build', 'env-test', 'env-test-build', 'conf', 'data'];
}
$aWritableDirsErrors = self::CheckWritableDirs($aWritableDirs);
$aResult = array_merge($aResult, $aWritableDirsErrors);
@@ -527,11 +527,15 @@ class SetupUtils
*
* @since 3.0.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
*/
public static function CheckBackupPrerequisites($sDBBackupPath, $sMySQLBinDir = null)
public static function CheckBackupPrerequisites($sDBBackupPath, $sMySQLBinDir = null, string $sEnvironment = ITOP_DEFAULT_ENV)
{
$aResult = [];
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - CheckBackupPrerequisites');
if ($sEnvironment !== ITOP_DEFAULT_ENV) {
$aResult[] = new CheckResult(CheckResult::ERROR, "Can only backup ".ITOP_DEFAULT_ENV." environment");
}
// zip extension
//
if (!extension_loaded('phar')) {
@@ -1592,13 +1596,13 @@ JS
if (is_dir($oWizard->GetParameter('copy_extensions_from'))) {
$aDirsToScan[] = $oWizard->GetParameter('copy_extensions_from');
}
$sExtraDir = utils::GetDataPath().'production-modules/';
$sExtraDir = utils::GetDataPath().$oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV).'-modules/';
if (is_dir($sExtraDir)) {
$aDirsToScan[] = $sExtraDir;
}
$oProductionEnv = new RunTimeEnvironment();
$oProductionEnv = new RunTimeEnvironment($oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV));
$aRemovedExtensionCodes = json_decode($oWizard->GetParameter('removed_extensions'), true) ?? [];
$oExtensionsMap = new iTopExtensionsMap(ITOP_DEFAULT_ENV, $aDirsToScan);
$oExtensionsMap = new iTopExtensionsMap($oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV), $aDirsToScan);
$oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes);
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);
@@ -1615,9 +1619,12 @@ JS
}
/**
* Get version of production application
*
* @param WizardController $oWizard
*
* @return array|bool
* @throws \CoreException
*/
public static function GetApplicationVersion($oWizard)
{

View File

@@ -56,7 +56,7 @@ class InstallationFileService
public function GetProductionEnv(): RunTimeEnvironment
{
if (is_null($this->oProductionEnv)) {
$this->oProductionEnv = new RunTimeEnvironment();
$this->oProductionEnv = new RunTimeEnvironment($this->sTargetEnvironment);
}
return $this->oProductionEnv;
}
@@ -258,8 +258,9 @@ class InstallationFileService
public function ProcessDefaultModules(): void
{
$sProductionModuleDir = APPROOT.'data/'.$this->sTargetEnvironment.'-modules/';
$oConfig = new Config(APPCONF.$this->sTargetEnvironment.'/'.ITOP_CONFIG_FILE);
$aAvailableModules = $this->GetProductionEnv()->AnalyzeInstallation(MetaModel::GetConfig(), $this->GetExtraDirs());
$aAvailableModules = $this->GetProductionEnv()->AnalyzeInstallation($oConfig, $this->GetExtraDirs());
$this->aAutoSelectModules = [];
foreach ($aAvailableModules as $sModuleId => $aModule) {

View File

@@ -73,7 +73,7 @@ abstract class AbstractWizStepInstall extends WizardStep
'datamodel_version' => $this->oWizard->GetParameter('datamodel_version'), //TODO: let the installer compute this automatically...
'previous_configuration_file' => $sPreviousConfigurationFile,
'extensions_dir' => $this->oWizard->GetParameter('extensions_dir', 'extensions'),
'target_env' => 'production',
'target_env' => $this->oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV),
'workspace_dir' => '',
'database' => [
'server' => $this->oWizard->GetParameter('db_server'),

View File

@@ -102,17 +102,19 @@ JS);
*/
public function PostFormDisplay(SetupPage $oPage)
{
$sApplicationUrl = utils::GetAbsoluteUrlModulePage('combodo-data-feature-removal', 'index.php');
$sEnvironment = $this->oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV);
$sApplicationUrl = utils::GetAbsoluteUrlModulePage('combodo-data-feature-removal', 'index.php', ['switch_env' => $sEnvironment], $sEnvironment);
$aParams = [
'selected_modules' => '[]',
'selected_extensions' => '[]',
'display_choices' => '[]',
'display_choices' => '',
'added_extensions' => '[]',
'removed_extensions' => '[]',
'extensions_not_uninstallable' => '[]',
'copy_setup_files' => 1,
'return_button_label' => '',
'target_env' => ITOP_DEFAULT_ENV,
];
$aHiddenInputs = '';
foreach ($aParams as $sParamName => $defaultValue) {
@@ -122,7 +124,6 @@ JS);
<input type="hidden" name="$sParamName" value="$sElements"/>
INPUT;
}
$sUID = Session::Get('setup_token');
$oPage->add(
<<<HTML

View File

@@ -17,6 +17,7 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\WebPage\WebPage;
/**
@@ -95,7 +96,7 @@ class WizStepDone extends WizardStep
// Load the data model only, in order to load env-production/core/main.php to get the XML parameters (needed by GetModuleSettings below)
// But main.php may also contain classes (defined without any module), and thus requiring the full data model
// to be loaded to prevent "class not found" errors...
$oProductionEnv = new RunTimeEnvironment(ITOP_DEFAULT_ENV);
$oProductionEnv = new RunTimeEnvironment($this->oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV));
$oProductionEnv->InitDataModel($oConfig, true);
$sIframeUrl = $oConfig->GetModuleSetting('itop-hub-connector', 'setup_url', '');

View File

@@ -7,10 +7,12 @@
class WizStepLandingBeforeAudit extends WizStepModulesChoice
{
private RunTimeEnvironment $oRuntimeEnv;
public function __construct(WizardController $oWizard, $sCurrentState)
{
$oProductionEnv = new RunTimeEnvironment();
$sBuildConfigFile = APPCONF.$oProductionEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE;
$this->oRuntimeEnv = new RunTimeEnvironment($oWizard->GetParameter('target_env'));
$sBuildConfigFile = APPCONF.$this->oRuntimeEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE;
$this->oConfig = new Config($sBuildConfigFile);
$oWizard->SetParameter('previous_version_dir', APPROOT);
@@ -40,8 +42,8 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
*/
public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState
{
$oProductionEnv = new RunTimeEnvironment();
$sBuildConfigFile = APPCONF.$oProductionEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE;
// Change the rights to production config file !
$sBuildConfigFile = APPCONF.ITOP_DEFAULT_ENV.'/'.ITOP_CONFIG_FILE;
@chmod($sBuildConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others
$oConfig = new Config($sBuildConfigFile);

View File

@@ -58,10 +58,10 @@ class WizStepModulesChoice extends AbstractWizStepInstall
$this->oExtensionsMap = new iTopExtensionsMap();
$sPreviousSourceDir = $this->oWizard->GetParameter('previous_version_dir', '');
$sConfigPath = null;
if (($sPreviousSourceDir !== '') && is_readable($sPreviousSourceDir.'/conf/production/config-itop.php')) {
$sConfigPath = $sPreviousSourceDir.'/conf/production/config-itop.php';
} elseif (is_readable(utils::GetConfigFilePath(ITOP_DEFAULT_ENV))) {
$sConfigPath = utils::GetConfigFilePath(ITOP_DEFAULT_ENV);
if (($sPreviousSourceDir !== '') && is_readable($sPreviousSourceDir.'/conf/'.ITOP_DEFAULT_ENV.'/config-itop.php')) {
$sConfigPath = $sPreviousSourceDir.'/conf/'.ITOP_DEFAULT_ENV.'/config-itop.php';
} elseif (is_readable(utils::GetConfigFilePath($this->oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV)))) {
$sConfigPath = utils::GetConfigFilePath($this->oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV));
}
// only called if the config file exists : we are updating a previous installation !