From 0688405f860ed2f805e517a934585f5f33df0806 Mon Sep 17 00:00:00 2001 From: Anne-Catherine <57360138+accognet@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:29:09 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B07348=20-=20Enable=20to=20param=20maximum?= =?UTF-8?q?=20depth=20of=20impact=20analysis=20in=20function=20Ticket::Upd?= =?UTF-8?q?ateImpactedItems=20(#633)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2.x/itop-tickets/main.itop-tickets.php | 20 ++++++- .../src/BaseTestCase/ItopDataTestCase.php | 33 +++++++++++ .../itop-tickets/UpdateImpactedItemsTest.php | 55 ++++++++++++++++++- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/datamodels/2.x/itop-tickets/main.itop-tickets.php b/datamodels/2.x/itop-tickets/main.itop-tickets.php index 90ade80ac..d3262162f 100755 --- a/datamodels/2.x/itop-tickets/main.itop-tickets.php +++ b/datamodels/2.x/itop-tickets/main.itop-tickets.php @@ -132,7 +132,23 @@ class ResponseTicketTTR extends ResponseTicketSLT implements iMetricComputer class _Ticket extends cmdbAbstractObject { + /** + * used to limit the depth of analysis in the UpdateImpactedItems function + * @return int + */ + public function GetImpactAnalysisMaxDepth() + { + return 10; + } + /** + * @param int $iMaxDepth maximum depth of impact analysis + * + * @return void + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + */ public function UpdateImpactedItems() { require_once(APPROOT.'core/displayablegraph.class.inc.php'); @@ -188,7 +204,7 @@ class _Ticket extends cmdbAbstractObject } // Merge the directly impacted items with the "new" ones added by the "context" queries $aGraphObjects = array(); - $oRawGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded); + $oRawGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, $this->GetImpactAnalysisMaxDepth(), true /* bEnableRedundancy */, $aExcluded); $oIterator = new RelationTypeIterator($oRawGraph, 'Node'); foreach ($oIterator as $oNode) { @@ -200,7 +216,7 @@ class _Ticket extends cmdbAbstractObject } if (count($aDefaultContexts) > 0) { - $oAnnotatedGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded, $aDefaultContexts); + $oAnnotatedGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, $this->GetImpactAnalysisMaxDepth(), true /* bEnableRedundancy */, $aExcluded, $aDefaultContexts); $oIterator = new RelationTypeIterator($oAnnotatedGraph, 'Node'); foreach ($oIterator as $oNode) { diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php index cde0f101a..8502e52fd 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php @@ -1199,6 +1199,27 @@ abstract class ItopDataTestCase extends ItopTestCase return $sId; } + /** + * Create an Application Solution in database + * + * @param int $iNum + * @param string $sRedundancy + * + * @throws Exception + */ + protected function GivenApplicationSolutionInDB($iNum, $sRedundancy = '1'): string + { + $sName = 'ApplicationSolution_'.$iNum; + $sId = $this->GivenObjectInDB('ApplicationSolution', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId(), + 'redundancy' => $sRedundancy, + ]); + $this->debug("Created $sName ($sId) redundancy $sRedundancy"); + + return $sId; + } + protected function GivenServerInDB($iNum, $iRackUnit = null): string { $sName = 'Server_'.$iNum; @@ -1255,6 +1276,18 @@ abstract class ItopDataTestCase extends ItopTestCase return $sId; } + protected function GivenLnkApplicationSolutionToFunctionalCIInDB($sApplicationSolutionId, $sCIId): string + { + $sClass = 'lnkApplicationSolutionToFunctionalCI'; + $sId = $this->GivenObjectInDB($sClass, [ + 'applicationsolution_id' => $sApplicationSolutionId, + 'functionalci_id' => $sCIId, + ]); + $this->debug("Created $sClass::$sId linking ApplicationSolution $sApplicationSolutionId and CI $sCIId"); + + return $sId; + } + protected function GivenVirtualMachineInDB($iNum, $sVirtualHostId): string { $sName = 'VirtualMachine_'.$iNum; diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php index a764f3e46..6dc32a17b 100644 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/itop-tickets/UpdateImpactedItemsTest.php @@ -75,6 +75,8 @@ class UpdateImpactedItemsTest extends ItopDataTestCase ]); } + + public function testImpactShouldBePropagatedInOneWayOnly() { /** @@ -117,6 +119,48 @@ class UpdateImpactedItemsTest extends ItopDataTestCase ]); } + public function testImpactShouldBePropagatedRecursivelyUpToMaxDepth() + { + /** + * ApplicationSolution_0 +----> ApplicationSolution_1 +----> ApplicationSolution_2 +-----> ..... +----> ApplicationSolution_12 + */ + $this->GivenCITreeInDB(<< ApplicationSolution_1 + ApplicationSolution_1 <-> ApplicationSolution_2 + ApplicationSolution_2 <-> ApplicationSolution_3 + ApplicationSolution_3 <-> ApplicationSolution_4 + ApplicationSolution_4 <-> ApplicationSolution_5 + ApplicationSolution_5 <-> ApplicationSolution_6 + ApplicationSolution_6 <-> ApplicationSolution_7 + ApplicationSolution_7 <-> ApplicationSolution_8 + ApplicationSolution_8 <-> ApplicationSolution_9 + ApplicationSolution_9 <-> ApplicationSolution_10 + ApplicationSolution_10 <-> ApplicationSolution_11 + ApplicationSolution_11 <-> ApplicationSolution_12 + ApplicationSolution_12 <-> ApplicationSolution_13 + EOF); + $oTicket = $this->GivenTicketWithCIsOrPersons([ + 'ApplicationSolution_0' => 'manual' + ]); + + $oTicket->UpdateImpactedItems(); // impact analysis + + // By default Max depth is 10. Can be changed by overriding _Ticket::GetImpactAnalysisMaxDepth + $this->assertCIsOrPersonsListEquals($oTicket, [ + 'ApplicationSolution_0' => 'manual', + 'ApplicationSolution_1' => 'computed', + 'ApplicationSolution_2' => 'computed', + 'ApplicationSolution_3' => 'computed', + 'ApplicationSolution_4' => 'computed', + 'ApplicationSolution_5' => 'computed', + 'ApplicationSolution_6' => 'computed', + 'ApplicationSolution_7' => 'computed', + 'ApplicationSolution_8' => 'computed', + 'ApplicationSolution_9' => 'computed', + 'ApplicationSolution_10' => 'computed', + ]); + } + public function testImpactShouldNotBeFurtherPropagatedWhenCINotAllowed() { /** @@ -445,7 +489,12 @@ class UpdateImpactedItemsTest extends ItopDataTestCase list($sCI, $sPerson) = explode('<->', $sLine); $sPersonId = $this->GivenCIOrPersonInDB(trim($sPerson)); $sCIId = $this->GivenCIOrPersonInDB(trim($sCI)); - $this->GivenLnkContactToFunctionalCIInDB($sPersonId, $sCIId); + if (str_starts_with(trim($sPerson),'ApplicationSolution')) + { + $this->GivenLnkApplicationSolutionToFunctionalCIInDB($sPersonId, $sCIId); + } else { + $this->GivenLnkContactToFunctionalCIInDB($sPersonId, $sCIId); + } return; } list($sCIParent, $sChildren) = explode('->', $sLine); @@ -482,6 +531,9 @@ class UpdateImpactedItemsTest extends ItopDataTestCase case 'VirtualMachine': $sCIId = $this->GivenVirtualMachineInDB($sRef, $aChildrenIdsByClass['Farm']); break; + case 'ApplicationSolution': + $sCIId = $this->GivenApplicationSolutionInDB($sRef); + break; default: throw new Exception("Unhandled class $sClass"); } @@ -525,3 +577,4 @@ class UpdateImpactedItemsTest extends ItopDataTestCase $this->ResetMetaModelQueyCacheGetObject(); } } +