Merge branch 'support/3.2' into develop

# Conflicts:
#	setup/applicationinstaller.class.inc.php
This commit is contained in:
odain
2024-04-09 10:13:45 +02:00
15 changed files with 1077 additions and 208 deletions

View File

@@ -228,7 +228,7 @@ class ApplicationInstaller
case 'copy':
$aPreinstall = $this->oParams->Get('preinstall');
$aCopies = $aPreinstall['copies'];
$aCopies = $aPreinstall['copies'] ?? [];
self::DoCopy($aCopies);
$sReport = "Copying...";
@@ -911,6 +911,7 @@ class ApplicationInstaller
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
// Perform here additional DB setup... profiles, etc...

View File

@@ -139,7 +139,7 @@ class RunTimeEnvironment
/**
* Analyzes the current installation and the possibilities
*
* @param Config $oConfig Defines the target environment (DB)
* @param null|Config $oConfig Defines the target environment (DB)
* @param mixed $modulesPath Either a single string or an array of absolute paths
* @param bool $bAbortOnMissingDependency ...
* @param array $aModulesToLoad List of modules to search for, defaults to all if omitted
@@ -226,13 +226,15 @@ class RunTimeEnvironment
try
{
$aSelectInstall = array();
if (! is_null($oConfig)) {
CMDBSource::InitFromConfig($oConfig);
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->Get('db_subname')."priv_module_install");
}
}
catch (MySQLException $e)
{
// No database or erroneous information
$aSelectInstall = array();
}
// Build the list of installed module (get the latest installation)

View File

@@ -818,7 +818,7 @@ class SetupUtils
{
if (!is_dir($sDest))
{
mkdir($sDest);
mkdir($sDest, 0777 /* Default */, true);
}
$aFiles = scandir($sSource);
if(sizeof($aFiles) > 0 )

View File

@@ -0,0 +1,244 @@
<?php
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/setup/setuppage.class.inc.php');
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
class InstallationFileService {
private $sTargetEnvironment;
private $sInstallationPath;
private $aSelectedModules;
private $aSelectedExtensions;
private $aUnSelectedModules;
private $aAutoSelectModules;
private $bInstallationOptionalChoicesChecked;
/**
* @param string $sInstallationPath
* @param string $sTargetEnvironment
* @param array $aSelectedExtensions
* @param bool $bInstallationOptionalChoicesChecked : this option is used only when no extensions are selected (ie empty $aSelectedExtensions)
*/
public function __construct(string $sInstallationPath, string $sTargetEnvironment='production', array $aSelectedExtensions = [], bool $bInstallationOptionalChoicesChecked=true) {
$this->sInstallationPath = $sInstallationPath;
$this->aSelectedModules = [];
$this->aUnSelectedModules = [];
$this->sTargetEnvironment = $sTargetEnvironment;
$this->aSelectedExtensions = $aSelectedExtensions;
$this->bInstallationOptionalChoicesChecked = $bInstallationOptionalChoicesChecked;
}
public function GetSelectedModules(): array {
return $this->aSelectedModules;
}
public function GetUnSelectedModules(): array {
return $this->aUnSelectedModules;
}
public function Init(): void {
clearstatcache();
$this->ProcessDefaultModules();
$this->ProcessInstallationChoices();
$this->ProcessAutoSelectModules();
}
public function ProcessInstallationChoices(): void {
$oXMLParameters = new XMLParameters($this->sInstallationPath);
$aSteps = $oXMLParameters->Get('steps', []);
if (! is_array($aSteps)) {
return;
}
foreach ($aSteps as $aStepInfo) {
$aOptions = $aStepInfo["options"] ?? null;
if (! is_null($aOptions) && is_array($aOptions)) {
foreach ($aOptions as $aChoiceInfo) {
$this->ProcessSelectedChoice($aChoiceInfo, $this->bInstallationOptionalChoicesChecked);
}
}
$aOptions = $aStepInfo["alternatives"] ?? null;
if (! is_null($aOptions) && is_array($aOptions)) {
foreach ($aOptions as $aChoiceInfo) {
$this->ProcessSelectedChoice($aChoiceInfo, false);
}
}
}
foreach ($this->aSelectedModules as $sModuleId => $sVal){
if (array_key_exists($sModuleId, $this->aUnSelectedModules)){
unset($this->aUnSelectedModules[$sModuleId]);
}
}
}
private function ProcessUnSelectedChoice($aChoiceInfo) {
if (!is_array($aChoiceInfo)) {
return;
}
$aCurrentModules = $aChoiceInfo["modules"] ?? [];
foreach ($aCurrentModules as $sModuleId){
$this->aUnSelectedModules[$sModuleId] = true;
}
$aAlternatives = $aChoiceInfo["alternatives"] ?? null;
if (!is_null($aAlternatives) && is_array($aAlternatives)) {
foreach ($aAlternatives as $aSubChoiceInfo) {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
if (array_key_exists('sub_options', $aChoiceInfo)) {
if (array_key_exists('options', $aChoiceInfo['sub_options'])) {
$aSubOptions = $aChoiceInfo['sub_options']['options'];
if (!is_null($aSubOptions) && is_array($aSubOptions)) {
foreach ($aSubOptions as $aSubChoiceInfo) {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
}
if (array_key_exists('alternatives', $aChoiceInfo['sub_options'])) {
$aSubAlternatives = $aChoiceInfo['sub_options']['alternatives'];
if (!is_null($aSubAlternatives) && is_array($aSubAlternatives)) {
foreach ($aSubAlternatives as $aSubChoiceInfo) {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
}
}
}
private function ProcessSelectedChoice($aChoiceInfo, bool $bAllChecked) {
if (!is_array($aChoiceInfo)) {
return;
}
$sDefault = $aChoiceInfo["default"] ?? "false";
$sMandatory = $aChoiceInfo["mandatory"] ?? "false";
$aCurrentModules = $aChoiceInfo["modules"] ?? [];
if (0 === count($this->aSelectedExtensions)){
$bSelected = $bAllChecked || $sDefault === "true" || $sMandatory === "true";
} else {
$sExtensionCode = $aChoiceInfo["extension_code"] ?? null;
$bSelected = $sMandatory === "true" ||
(null !== $sExtensionCode && in_array($sExtensionCode, $this->aSelectedExtensions));
}
foreach ($aCurrentModules as $sModuleId){
if ($bSelected) {
$this->aSelectedModules[$sModuleId] = true;
} else {
$this->aUnSelectedModules[$sModuleId] = true;
}
}
$aAlternatives = $aChoiceInfo["alternatives"] ?? null;
if (!is_null($aAlternatives) && is_array($aAlternatives)) {
foreach ($aAlternatives as $aSubChoiceInfo) {
if ($bSelected) {
$this->ProcessSelectedChoice($aSubChoiceInfo, $bAllChecked);
} else {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
}
if (array_key_exists('sub_options', $aChoiceInfo)) {
if (array_key_exists('options', $aChoiceInfo['sub_options'])) {
$aSubOptions = $aChoiceInfo['sub_options']['options'];
if (!is_null($aSubOptions) && is_array($aSubOptions)) {
foreach ($aSubOptions as $aSubChoiceInfo) {
if ($bSelected) {
$this->ProcessSelectedChoice($aSubChoiceInfo, $bAllChecked);
} else {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
}
}
if (array_key_exists('alternatives', $aChoiceInfo['sub_options'])) {
$aSubAlternatives = $aChoiceInfo['sub_options']['alternatives'];
if (!is_null($aSubAlternatives) && is_array($aSubAlternatives)) {
foreach ($aSubAlternatives as $aSubChoiceInfo) {
if ($bSelected) {
$this->ProcessSelectedChoice($aSubChoiceInfo, false);
} else {
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
}
}
}
}
}
}
private function GetExtraDirs() : array {
$aSearchDirs = [];
$aDirs = [
'/datamodels/1.x',
'/datamodels/2.x',
'data/' . $this->sTargetEnvironment . '-modules',
'extensions',
];
foreach ($aDirs as $sRelativeDir){
$sDirPath = APPROOT.$sRelativeDir;
if (is_dir($sDirPath))
{
$aSearchDirs[] = $sDirPath;
}
}
return $aSearchDirs;
}
public function ProcessDefaultModules() : void {
$sProductionModuleDir = APPROOT.'data/' . $this->sTargetEnvironment . '-modules/';
$oProductionEnv = new RunTimeEnvironment();
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), $this->GetExtraDirs(), false, null);
$this->aAutoSelectModules = [];
foreach ($aAvailableModules as $sModuleId => $aModule) {
if (($sModuleId != ROOT_MODULE)) {
if (isset($aModule['auto_select'])) {
$this->aAutoSelectModules[$sModuleId] = $aModule;
continue;
}
if (($aModule['category'] == 'authentication') || (!$aModule['visible'])) {
$this->aSelectedModules[$sModuleId] = true;
continue;
}
$bIsExtra = (array_key_exists('root_dir', $aModule) && (strpos($aModule['root_dir'],
$sProductionModuleDir) !== false)); // Some modules (root, datamodel) have no 'root_dir'
if ($bIsExtra) {
// Modules in data/production-modules/ are considered as mandatory and always installed
$this->aSelectedModules[$sModuleId] = true;
}
}
}
}
public function ProcessAutoSelectModules() : void {
foreach($this->aAutoSelectModules as $sModuleId => $aModule)
{
try {
$bSelected = false;
SetupInfo::SetSelectedModules($this->aSelectedModules);
eval('$bSelected = ('.$aModule['auto_select'].');');
if ($bSelected)
{
// Modules in data/production-modules/ are considered as mandatory and always installed
$this->aSelectedModules[$sModuleId] = true;
}
}
catch (Exception $e) {
}
}
}
}

View File

@@ -3,3 +3,23 @@
This script allows to install and update iTop via CLI.
For more information, see the official Wiki : [Automated installation [iTop Documentation]](https://www.itophub.io/wiki/page?id=latest:advancedtopics:automatic_install)
#install-itop.sh
You can install your iTop by only using config-itop.php settings and run either
- a non-ITIL iTop fresh installation (use itil-fresh-install.xml to have ITIL modules instead)
```
./install-itop.sh ./xml_setup/fresh-install.xml
```
- a non-ITIL iTop upgrade (use itil-upgrade.xml to have ITIL modules instead)
```
./install-itop.sh ./xml_setup/upgrade.xml
```
- a specific iTop installation by providing both xml setup file
in below example file provided is the one generated by iTop during last setup.
```
./install-itop.sh ../../log/install-2024-04-03.xml
```

View File

@@ -0,0 +1,50 @@
#! /bin/bash
CLI_NAME=$(basename $0)
DIR=$(dirname $0)
ITOP_DIR="$DIR/../.."
HELP="Syntax: $CLI_NAME XML_SETUP [INSTALLATION_XML]"
function HELP {
echo $HELP
exit 1
}
if [ $# -lt 1 ]
then
echo "Missing parameters passed."
HELP
fi
if [ $# -gt 2 ]
then
echo "Too much parameters passed ($#) : $*."
HELP
fi
XML_SETUP=$1
if [ ! -f $XML_SETUP ]
then
echo "XML_SETUP file ($XML_SETUP) not found."
HELP
fi
if [ $# -eq 2 ]
then
INSTALLATION_XML=$2
if [ ! -f $INSTALLATION_XML ]
then
echo "INSTALLATION_XML file ($INSTALLATION_XML) not found."
HELP
fi
else
INSTALLATION_XML="$ITOP_DIR/datamodels/2.x/installation.xml"
fi
echo "$CLI_NAME: Using XML_SETUP ($XML_SETUP) and INSTALLATION_XML ($INSTALLATION_XML) files during unattended itop installation."
rm -rf $ITOP_DIR/data/.maintenance;
echo php $DIR/unattended-install.php --use_itop_config --installation_xml="$INSTALLATION_XML" --param-file="$XML_SETUP"
php $DIR/unattended-install.php --use_itop_config --installation_xml="$INSTALLATION_XML" --param-file="$XML_SETUP"

View File

@@ -1,17 +1,29 @@
<?php
$bBypassMaintenance = true;
require_once(dirname(__FILE__, 3) . '/approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'sources/Application/WebPage/CLIPage.php');
require_once(APPROOT.'/core/config.class.inc.php');
require_once(APPROOT.'/core/log.class.inc.php');
require_once(APPROOT.'/core/kpi.class.inc.php');
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
require_once(APPROOT.'/setup/setuppage.class.inc.php');
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
require_once(APPROOT.'/setup/applicationinstaller.class.inc.php');
require_once(dirname(__FILE__, 3) . '/approot.inc.php');
require_once(__DIR__ . '/InstallationFileService.php');
function PrintUsageAndExit()
{
echo <<<EOF
Usage: php unattended-install.php --param-file=<path_to_response_file> [--installation_xml=<path_to_installation_xml>] [--use_itop_config]
Options:
--param-file=<path_to_response_file> Path to the file (XML) to use for the unattended installation. That file (generated by the setup into log directory) must contain the following sections:
- target_env: the target environment (production, test, dev)
- database: the database settings (server, user, pwd, name, prefix)
- selected_modules: the list of modules to install
--response_file DEPRECATED: use `--param-file` instead
--installation_xml=<path_to_installation_xml> Use an installation.xml file to compute the modules to install depending on the selected extensions listed in the param file
--use_itop_config Use the iTop configuration file to get the database settings, otherwise use the database settings from the parameters file
Advanced options:
--check-consistency=1 Check the data model consistency after the installation (default: 0)
--clean=1 In case of a first installation, cleanup the environment before proceeding: delete the configuration file, the cache directory, the target directory, the database (default: 0)
--install=0 Set to 0 to perform a dry-run (default: 1)
EOF;
exit(-1);
}
/////////////////////////////////////////////////
if (! utils::IsModeCLI())
{
@@ -19,17 +31,22 @@ if (! utils::IsModeCLI())
exit(-1);
}
$sParamFile = utils::ReadParam('response_file', 'null', true /* CLI allowed */, 'raw_data');
if ($sParamFile === 'null') {
echo "No `--response_file` param specified, using default value !\n";
$sParamFile = 'default-params.xml';
if (in_array('--help', $argv)) {
PrintUsageAndExit();
}
$bCheckConsistency = (utils::ReadParam('check_consistency', '0', true /* CLI allowed */) == '1');
$sParamFile = utils::ReadParam('param-file', null, true /* CLI allowed */, 'raw_data') ?? utils::ReadParam('response_file', null, true /* CLI allowed */, 'raw_data');
if (is_null($sParamFile)) {
echo "Missing mandatory argument `--param-file`.\n";
PrintUsageAndExit();
}
$bCheckConsistency = (utils::ReadParam('check-consistency', '0', true /* CLI allowed */) == '1');
if (false === file_exists($sParamFile)) {
echo "Param file `$sParamFile` doesn't exist ! Exiting...";
echo "Param file `$sParamFile` doesn't exist! Exiting...\n";
exit(-1);
}
$oParams = new XMLParameters($sParamFile);
$sMode = $oParams->Get('mode');
@@ -40,8 +57,73 @@ if ($sTargetEnvironment == '')
$sTargetEnvironment = 'production';
}
$sXmlSetupBaseName = basename($sParamFile);
$sInstallationXmlPath = utils::ReadParam('installation_xml', null, true /* CLI allowed */, 'raw_data');
if (! is_null($sInstallationXmlPath) && is_file($sInstallationXmlPath)) {
$sInstallationBaseName = basename($sInstallationXmlPath);
$aSelectedExtensionsFromXmlSetup = $oParams->Get('selected_extensions', []);
if (count($aSelectedExtensionsFromXmlSetup) !== 0) {
$sMsg = "Modules to install computed based on $sInstallationBaseName file and installation choices (listed in section `selected_extensions` of $sXmlSetupBaseName file)";
echo "$sMsg:\n".implode(',', $aSelectedExtensionsFromXmlSetup)."\n\n";
SetupLog::Info($sMsg, null, $aSelectedExtensionsFromXmlSetup);
} else {
$sMsg = "Modules to install computed based on default installation choices inside $sInstallationBaseName (no choice specified in section `selected_extensions` of $sXmlSetupBaseName file).";
echo "$sMsg\n\n";
SetupLog::Info($sMsg);
}
$oInstallationFileService = new InstallationFileService($sInstallationXmlPath, $sTargetEnvironment, $aSelectedExtensionsFromXmlSetup);
$oInstallationFileService->Init();
$aComputedModules = $oInstallationFileService->GetSelectedModules();
$aSelectedModules = array_keys($aComputedModules);
$oParams->Set('selected_modules', $aSelectedModules);
$sMsg = "Modules to install computed";
} else {
$aSelectedModules = $oParams->Get('selected_modules', []);
$sMsg = "Modules to install listed in $sXmlSetupBaseName (selected_modules section)";
}
sort($aSelectedModules);
echo "$sMsg:\n".implode(',', $aSelectedModules)."\n\n";
SetupLog::Info($sMsg, null, $aSelectedModules);
// Configuration file
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
$bUseItopConfig = in_array('--use_itop_config', $argv);
if ($bUseItopConfig && file_exists($sConfigFile)){
//unattended run based on db settings coming from itop configuration
copy($sConfigFile, "$sConfigFile.backup");
$oConfig = new Config($sConfigFile);
$aDBXmlSettings = $oParams->Get('database', array());
$aDBXmlSettings ['server'] = $oConfig->Get('db_host');
$aDBXmlSettings ['user'] = $oConfig->Get('db_user');
$aDBXmlSettings ['pwd'] = $oConfig->Get('db_pwd');
$aDBXmlSettings ['name'] = $oConfig->Get('db_name');
$aDBXmlSettings ['prefix'] = $oConfig->Get('db_subname');
$aDBXmlSettings ['db_tls_enabled'] = $oConfig->Get('db_tls.enabled');
//cannot be null or infinite loop triggered!
$aDBXmlSettings ['db_tls_ca'] = $oConfig->Get('db_tls.ca') ?? "";
$oParams->Set('database', $aDBXmlSettings);
$aFields = [
'url' => 'app_root_url',
'source_dir' => 'source_dir',
'graphviz_path' => 'graphviz_path',
];
foreach($aFields as $sSetupField => $sConfField){
$oParams->Set($sSetupField, $oConfig->Get($sConfField));
}
$oParams->Set('mysql_bindir', $oConfig->GetModuleSetting('itop-backup', 'mysql_bindir', ""));
$oParams->Set('language', $oConfig->GetDefaultLanguage());
} else {
//unattended run based on db settings coming from response_file (XML file)
$aDBXmlSettings = $oParams->Get('database', array());
}
$sDBServer = $aDBXmlSettings['server'];
$sDBUser = $aDBXmlSettings['user'];
$sDBPwd = $aDBXmlSettings['pwd'];
@@ -57,8 +139,6 @@ if ($sMode == 'install')
{
echo "Cleanup mode detected.\n";
// Configuration file
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
if (file_exists($sConfigFile))
{
echo "Trying to delete the configuration file: '$sConfigFile'.\n";
@@ -200,7 +280,7 @@ if ($bHasErrors)
$sLogMsg = "Encountered stopper issues. Aborting...";
echo "$sLogMsg\n";
SetupLog::Error($sLogMsg);
die;
exit(-1);
}
$bFoundIssues = false;
@@ -296,6 +376,13 @@ if (!$bFoundIssues)
// last line: used to check the install
// the only way to track issues in case of Fatal error or even parsing error!
$sLogMsg = "installed!";
if ($bUseItopConfig && is_file("$sConfigFile.backup"))
{
echo "\nuse config file provided by backup in $sConfigFile.";
copy("$sConfigFile.backup", $sConfigFile);
}
SetupLog::Info($sLogMsg);
echo "\n$sLogMsg";
exit(0);
@@ -303,5 +390,5 @@ if (!$bFoundIssues)
$sLogMsg = "installation failed!";
SetupLog::Error($sLogMsg);
echo "\n$sLogMsg";
echo "\n$sLogMsg\n";
exit(-1);

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<installation>
<mode>install</mode>
<preinstall>
</preinstall>
<source_dir>datamodels/2.x/</source_dir>
<datamodel_version>2.7.0</datamodel_version>
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
<extensions_dir>extensions</extensions_dir>
<target_env>production</target_env>
<workspace_dir></workspace_dir>
<database>
<server></server>
<user></user>
<pwd></pwd>
<name></name>
<db_tls_enabled></db_tls_enabled>
<db_tls_ca></db_tls_ca>
<prefix></prefix>
</database>
<url></url>
<graphviz_path>/usr/bin/dot</graphviz_path>
<admin_account>
<user></user>
<pwd></pwd>
<language></language>
</admin_account>
<language></language>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
<sample_data>1</sample_data>
<old_addon></old_addon>
<options type="array"/>
<mysql_bindir></mysql_bindir>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
</installation>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<installation>
<mode>install</mode>
<preinstall>
</preinstall>
<source_dir>datamodels/2.x/</source_dir>
<datamodel_version>2.7.0</datamodel_version>
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
<extensions_dir>extensions</extensions_dir>
<target_env>production</target_env>
<workspace_dir></workspace_dir>
<database>
<server></server>
<user></user>
<pwd></pwd>
<name></name>
<db_tls_enabled></db_tls_enabled>
<db_tls_ca></db_tls_ca>
<prefix></prefix>
</database>
<url></url>
<graphviz_path>/usr/bin/dot</graphviz_path>
<admin_account>
<user></user>
<pwd></pwd>
<language></language>
</admin_account>
<language></language>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
<sample_data>1</sample_data>
<old_addon></old_addon>
<options type="array"/>
<mysql_bindir></mysql_bindir>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
<item>itop-config-mgmt-datacenter</item>
<item>itop-config-mgmt-end-user</item>
<item>itop-config-mgmt-storage</item>
<item>itop-config-mgmt-virtualization</item>
<item>itop-service-mgmt-enterprise</item>
<item>itop-ticket-mgmt-itil</item>
<item>itop-ticket-mgmt-itil-user-request</item>
<item>itop-ticket-mgmt-itil-incident</item>
<item>itop-ticket-mgmt-itil-enhanced-portal</item>
<item>itop-change-mgmt-itil</item>
<item>itop-config-mgmt-core</item>
<item>itop-kown-error-mgmt</item>
</selected_extensions>
</installation>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<installation>
<mode>upgrade</mode>
<preinstall>
</preinstall>
<source_dir>datamodels/2.x/</source_dir>
<datamodel_version>2.7.0</datamodel_version>
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
<extensions_dir>extensions</extensions_dir>
<target_env>production</target_env>
<workspace_dir></workspace_dir>
<database>
<server></server>
<user></user>
<pwd></pwd>
<name></name>
<db_tls_enabled></db_tls_enabled>
<db_tls_ca></db_tls_ca>
<prefix></prefix>
</database>
<url></url>
<graphviz_path>/usr/bin/dot</graphviz_path>
<admin_account>
<user></user>
<pwd></pwd>
<language></language>
</admin_account>
<language></language>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
<sample_data>1</sample_data>
<old_addon></old_addon>
<options type="array"/>
<mysql_bindir></mysql_bindir>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
<item>itop-config-mgmt-datacenter</item>
<item>itop-config-mgmt-end-user</item>
<item>itop-config-mgmt-storage</item>
<item>itop-config-mgmt-virtualization</item>
<item>itop-service-mgmt-enterprise</item>
<item>itop-ticket-mgmt-itil</item>
<item>itop-ticket-mgmt-itil-user-request</item>
<item>itop-ticket-mgmt-itil-incident</item>
<item>itop-ticket-mgmt-itil-enhanced-portal</item>
<item>itop-change-mgmt-itil</item>
<item>itop-config-mgmt-core</item>
<item>itop-kown-error-mgmt</item>
</selected_extensions>
</installation>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<installation>
<mode>upgrade</mode>
<preinstall>
</preinstall>
<source_dir>datamodels/2.x/</source_dir>
<datamodel_version>2.7.0</datamodel_version>
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
<extensions_dir>extensions</extensions_dir>
<target_env>production</target_env>
<workspace_dir></workspace_dir>
<database>
<server></server>
<user></user>
<pwd></pwd>
<name></name>
<db_tls_enabled></db_tls_enabled>
<db_tls_ca></db_tls_ca>
<prefix></prefix>
</database>
<url></url>
<graphviz_path>/usr/bin/dot</graphviz_path>
<admin_account>
<user></user>
<pwd></pwd>
<language></language>
</admin_account>
<language></language>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
<sample_data>1</sample_data>
<old_addon></old_addon>
<options type="array"/>
<mysql_bindir></mysql_bindir>
<selected_modules type="array">
</selected_modules>
<selected_extensions type="array">
</selected_extensions>
</installation>

View File

@@ -5,7 +5,7 @@ php_version=8.2-apache
db_version=5.7
[itop]
itop_setup=tests/setup_params/default-params.xml
;itop_setup=tests/setup_params/default-params.xml
itop_backup=tests/backups/backup-itop.tar.gz
[phpunit]

View File

@@ -0,0 +1,315 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Setup\UnattendedInstall;
use PHPUnit\Framework\TestCase;
class InstallationFileServiceTest extends TestCase {
protected function setUp(): void {
parent::setUp();
require_once(dirname(__FILE__, 6) . '/setup/unattended-install/InstallationFileService.php');
$this->sFolderToCleanup = null;
\ModuleDiscovery::ResetCache();
}
protected function tearDown(): void {
parent::tearDown();
$sModuleId = "itop-problem-mgmt";
$this->RecurseMoveDir(APPROOT."data/production-modules/$sModuleId", APPROOT . "datamodels/2.x/$sModuleId");
}
public function GetDefaultModulesProvider() {
return [
'all checked' => [ true ],
'only defaut + mandatory' => [ false ],
];
}
/**
* @dataProvider GetDefaultModulesProvider
*/
public function testProcessInstallationChoices($bInstallationOptionalChoicesChecked=false) {
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
$this->assertTrue(is_file($sPath));
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], $bInstallationOptionalChoicesChecked);
$oInstallationFileService->ProcessInstallationChoices();
$aExpectedModules = [
"itop-config-mgmt",
"itop-attachments",
"itop-profiles-itil",
"itop-welcome-itil",
"itop-tickets",
"itop-files-information",
"combodo-db-tools",
"itop-core-update",
"itop-hub-connector",
"itop-oauth-client",
"itop-datacenter-mgmt",
"itop-endusers-devices",
"itop-storage-mgmt",
"itop-virtualization-mgmt",
"itop-service-mgmt",
"itop-request-mgmt",
"itop-portal",
"itop-portal-base",
"itop-change-mgmt",
];
$aExpectedUnselectedModules = [
'itop-change-mgmt-itil',
'itop-incident-mgmt-itil',
'itop-request-mgmt-itil',
'itop-service-mgmt-provider',
];
if ($bInstallationOptionalChoicesChecked){
$aExpectedModules []= "itop-problem-mgmt";
$aExpectedModules []= "itop-knownerror-mgmt";
} else {
$aExpectedUnselectedModules []= "itop-problem-mgmt";
$aExpectedUnselectedModules []= "itop-knownerror-mgmt";
}
sort($aExpectedModules);
$aModules = array_keys($oInstallationFileService->GetSelectedModules());
sort($aModules);
$this->assertEquals($aExpectedModules, $aModules);
$aUnselectedModules = array_keys($oInstallationFileService->GetUnSelectedModules());
sort($aExpectedUnselectedModules);
sort($aUnselectedModules);
$this->assertEquals($aExpectedUnselectedModules, $aUnselectedModules);
}
/**
* @dataProvider GetDefaultModulesProvider
*/
public function testGetAllSelectedModules($bInstallationOptionalChoicesChecked=false) {
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], $bInstallationOptionalChoicesChecked);
$oInstallationFileService->Init();
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
$aExpectedInstallationModules = [
"itop-config-mgmt",
"itop-attachments",
"itop-profiles-itil",
"itop-welcome-itil",
"itop-tickets",
"itop-files-information",
"combodo-db-tools",
"itop-core-update",
"itop-hub-connector",
"itop-oauth-client",
"itop-datacenter-mgmt",
"itop-endusers-devices",
"itop-storage-mgmt",
"itop-virtualization-mgmt",
"itop-service-mgmt",
"itop-request-mgmt",
"itop-portal",
"itop-portal-base",
"itop-change-mgmt",
];
if ($bInstallationOptionalChoicesChecked){
$aExpectedInstallationModules []= "itop-problem-mgmt";
$aExpectedInstallationModules []= "itop-knownerror-mgmt";
}
$aExpectedAuthenticationModules = [
'authent-cas',
'authent-external',
'authent-ldap',
'authent-local',
];
$aUnvisibleModules = [
'itop-backup',
'itop-config',
'itop-sla-computation',
];
$aAutoSelectedModules = [
'itop-bridge-virtualization-storage',
];
$this->checkModuleList("installation.xml choices", $aExpectedInstallationModules, $aSelectedModules);
$this->checkModuleList("authentication category", $aExpectedAuthenticationModules, $aSelectedModules);
$this->checkModuleList("unvisible", $aUnvisibleModules, $aSelectedModules);
$this->checkModuleList("auto-select", $aAutoSelectedModules, $aSelectedModules);
$this->assertEquals([], $aSelectedModules, "there should be no more modules remaining apart from below lists");
}
private function GetSelectedItilExtensions(bool $coreExtensionIncluded, bool $bKnownMgtIncluded) : array {
$aExtensions = [
'itop-config-mgmt-datacenter',
'itop-config-mgmt-end-user',
'itop-config-mgmt-storage',
'itop-config-mgmt-virtualization',
'itop-service-mgmt-enterprise',
'itop-ticket-mgmt-itil',
'itop-ticket-mgmt-itil-user-request',
'itop-ticket-mgmt-itil-incident',
'itop-ticket-mgmt-itil-enhanced-portal',
'itop-change-mgmt-itil',
];
if ($coreExtensionIncluded){
$aExtensions[]= 'itop-config-mgmt-core';
}
if ($bKnownMgtIncluded){
$aExtensions[]= 'itop-kown-error-mgmt';
}
return $aExtensions;
}
public function ItilExtensionProvider() {
return [
'all itil extensions + INCLUDING known-error-mgt' => [
'aSelectedExtensions' => $this->GetSelectedItilExtensions(true, true),
'bKnownMgtSelected' => true,
],
'all itil extensions WITHOUT known-error-mgt' => [
'aSelectedExtensions' => $this->GetSelectedItilExtensions(true, false),
'bKnownMgtSelected' => false,
],
'all itil extensions WITHOUT core mandatory ones + INCLUDING known-error-mgt' => [
'aSelectedExtensions' => $this->GetSelectedItilExtensions(false, true),
'bKnownMgtSelected' => true,
],
'all itil extensions WITHOUT core mandatory ones and WITHOUT known-error-mgt' => [
'aSelectedExtensions' => $this->GetSelectedItilExtensions(false, false),
'bKnownMgtSelected' => false,
],
];
}
/**
* @dataProvider ItilExtensionProvider
*/
public function testGetAllSelectedModules_withItilExtensions(array $aSelectedExtensions, bool $bKnownMgtSelected) {
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
$oInstallationFileService = new \InstallationFileService($sPath, 'production', $aSelectedExtensions);
$oInstallationFileService->Init();
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
$aExpectedInstallationModules = [
"itop-config-mgmt",
"itop-attachments",
"itop-profiles-itil",
"itop-welcome-itil",
"itop-tickets",
"itop-files-information",
"combodo-db-tools",
"itop-core-update",
"itop-hub-connector",
"itop-oauth-client",
"itop-datacenter-mgmt",
"itop-endusers-devices",
"itop-storage-mgmt",
"itop-virtualization-mgmt",
"itop-service-mgmt",
"itop-request-mgmt-itil",
"itop-incident-mgmt-itil",
"itop-portal",
"itop-portal-base",
"itop-change-mgmt-itil",
"itop-full-itil",
];
if ($bKnownMgtSelected){
$aExpectedInstallationModules []= "itop-knownerror-mgmt";
}
$aExpectedAuthenticationModules = [
'authent-cas',
'authent-external',
'authent-ldap',
'authent-local',
];
$aUnvisibleModules = [
'itop-backup',
'itop-config',
'itop-sla-computation',
];
$aAutoSelectedModules = [
'itop-bridge-virtualization-storage',
];
$this->checkModuleList("installation.xml choices", $aExpectedInstallationModules, $aSelectedModules);
$this->checkModuleList("authentication category", $aExpectedAuthenticationModules, $aSelectedModules);
$this->checkModuleList("unvisible", $aUnvisibleModules, $aSelectedModules);
$this->checkModuleList("auto-select", $aAutoSelectedModules, $aSelectedModules);
$this->assertEquals([], $aSelectedModules, "there should be no more modules remaining apart from below lists");
}
private function checkModuleList(string $sModuleCategory, array $aExpectedModuleList, array &$aSelectedModules) {
$aMissingModules = [];
foreach ($aExpectedModuleList as $sModuleId){
if (! array_key_exists($sModuleId, $aSelectedModules)){
$aMissingModules[]=$sModuleId;
} else {
unset($aSelectedModules[$sModuleId]);
}
}
$this->assertEquals([], $aMissingModules, "$sModuleCategory modules are missing");
}
public function ProductionModulesProvider() {
return [
'module autoload as located in production-modules' => [ true ],
'module not loaded' => [ false ],
];
}
/**
* @dataProvider ProductionModulesProvider
*/
public function testGetAllSelectedModules_ProductionModules(bool $bModuleInProductionModulesFolder) {
$sModuleId = "itop-problem-mgmt";
if ($bModuleInProductionModulesFolder){
if (! is_dir(APPROOT."data/production-modules")){
@mkdir(APPROOT."data/production-modules");
}
$this->RecurseMoveDir(APPROOT . "datamodels/2.x/$sModuleId", APPROOT."data/production-modules/$sModuleId");
}
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], false);
$oInstallationFileService->Init();
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
$this->assertEquals($bModuleInProductionModulesFolder, array_key_exists($sModuleId, $aSelectedModules));
}
private function RecurseMoveDir($sFromDir, $sToDir) {
if (! is_dir($sFromDir)){
return;
}
if (! is_dir($sToDir)){
@mkdir($sToDir);
}
foreach (glob("$sFromDir/*") as $sPath){
$sToPath = $sToDir.'/'.basename($sPath);
if (is_file($sPath)){
@rename($sPath, $sToPath);
} else {
$this->RecurseMoveDir($sPath, $sToPath);
}
}
@rmdir($sFromDir);
}
}

View File

@@ -63,9 +63,12 @@ class UnattendedInstallTest extends ItopDataTestCase
}
public function testCallUnattendedInstallFromCLI() {
$cliPath = realpath(APPROOT."/setup/unattended-install/unattended-install.php");
$res = exec("php ".$cliPath);
$sCliPath = realpath(APPROOT."/setup/unattended-install/unattended-install.php");
exec(sprintf("%s %s", PHP_BINARY, $sCliPath), $aOutput, $iCode);
$this->assertEquals("Param file `default-params.xml` doesn't exist ! Exiting...", $res);
$sOutput = implode('\n', $aOutput);
var_dump($sOutput);
$this->assertStringContainsString("Missing mandatory argument `--param-file`", $sOutput);
$this->assertEquals(255, $iCode);
}
}

View File

@@ -29,49 +29,8 @@
</admin_account>
<language>EN US</language>
<selected_modules type="array">
<item>authent-cas</item>
<item>authent-external</item>
<item>authent-ldap</item>
<item>authent-local</item>
<item>itop-backup</item>
<item>itop-config</item>
<item>itop-files-information</item>
<item>itop-portal-base</item>
<item>itop-profiles-itil</item>
<item>itop-sla-computation</item>
<item>itop-welcome-itil</item>
<item>itop-structure</item>
<item>itop-config-mgmt</item>
<item>itop-attachments</item>
<item>itop-tickets</item>
<item>combodo-db-tools</item>
<item>itop-core-update</item>
<item>itop-hub-connector</item>
<item>itop-datacenter-mgmt</item>
<item>itop-endusers-devices</item>
<item>itop-storage-mgmt</item>
<item>itop-virtualization-mgmt</item>
<item>itop-bridge-virtualization-storage</item>
<item>itop-service-mgmt</item>
<item>itop-bridge-cmdb-ticket</item>
<item>itop-bridge-cmdb-services</item>
<item>itop-request-mgmt</item>
<item>itop-portal</item>
<item>itop-change-mgmt</item>
<item>itop-knownerror-mgmt</item>
<item>itop-faq-light</item>
</selected_modules>
<selected_extensions type="array">
<item>itop-config-mgmt-core</item>
<item>itop-config-mgmt-datacenter</item>
<item>itop-config-mgmt-end-user</item>
<item>itop-config-mgmt-storage</item>
<item>itop-config-mgmt-virtualization</item>
<item>itop-service-mgmt-enterprise</item>
<item>itop-ticket-mgmt-simple-ticket</item>
<item>itop-ticket-mgmt-simple-ticket-enhanced-portal</item>
<item>itop-change-mgmt-simple</item>
<item>itop-kown-error-mgmt</item>
</selected_extensions>
<sample_data>1</sample_data>
<old_addon></old_addon>