From 7d6bfac59b7a43e6eaff416cc7ecc88c42a5dbfd Mon Sep 17 00:00:00 2001 From: Clark Andrianasolo Date: Mon, 9 Dec 2024 17:11:51 +0100 Subject: [PATCH] Fixes #26022: Status should not be on error when there is technique compilator error on disable techniques --- .../ncf/TechniqueCompilationCache.scala | 158 ++++++++++++++++-- .../ncf/TestTechniqueCompilationCache.scala | 46 ++++- .../bootstrap/liftweb/RudderConfig.scala | 15 +- .../rudder/web/comet/AsyncDeployment.scala | 3 +- .../web/components/TechniqueEditForm.scala | 29 ++-- .../TestMigrateJsonTechniquesToYaml.scala | 17 +- 6 files changed, 223 insertions(+), 45 deletions(-) diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueCompilationCache.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueCompilationCache.scala index 1613b8a5f07..9df05aded13 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueCompilationCache.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueCompilationCache.scala @@ -37,10 +37,14 @@ package com.normation.rudder.ncf +import com.normation.cfclerk.domain.TechniqueName import com.normation.errors.IOResult import com.normation.inventory.domain.Version import com.normation.rudder.batch.UpdateCompilationStatus import com.normation.rudder.domain.logger.StatusLoggerPure +import com.normation.rudder.domain.policies.ActiveTechnique +import com.normation.rudder.repository.FullActiveTechnique +import com.normation.rudder.repository.RoDirectiveRepository import net.liftweb.common.SimpleActor import zio.* import zio.syntax.* @@ -71,12 +75,30 @@ object EditorTechniqueCompilationResult { case class EditorTechniqueError( id: BundleName, version: Version, + status: TechniqueActiveStatus, name: String, errorMessage: String ) sealed trait CompilationStatus -case object CompilationStatusAllSuccess extends CompilationStatus +object CompilationStatus { + def fromErrors(errors: Chunk[EditorTechniqueError]): CompilationStatus = { + NonEmptyChunk.fromChunk(errors) match { + case None => CompilationStatusAllSuccess + case Some(value) => CompilationStatusErrors(value) + } + } + + def ignoreDisabledTechniques(status: CompilationStatus): CompilationStatus = { + status match { + case CompilationStatusErrors(techniquesInError) => + fromErrors(techniquesInError.collect { case e @ EditorTechniqueError(_, _, TechniqueActiveStatus.Enabled, _, _) => e }) + case CompilationStatusAllSuccess => + CompilationStatusAllSuccess + } + } +} +case object CompilationStatusAllSuccess extends CompilationStatus case class CompilationStatusErrors(techniquesInError: NonEmptyChunk[EditorTechniqueError]) extends CompilationStatus { def ++(other: CompilationStatusErrors): CompilationStatusErrors = CompilationStatusErrors( this.techniquesInError ++ other.techniquesInError @@ -92,6 +114,23 @@ trait ReadEditorTechniqueCompilationResult { } +sealed trait TechniqueActiveStatus +object TechniqueActiveStatus { + case object Enabled extends TechniqueActiveStatus + case object Disabled extends TechniqueActiveStatus +} + +/** + * Get attribute from the configuration techniques + */ +trait ReadEditorTechniqueActiveStatus { + + def getActiveStatus(id: BundleName): IOResult[Option[TechniqueActiveStatus]] + + def getActiveStatuses(): IOResult[Map[BundleName, TechniqueActiveStatus]] + +} + /** * Update technique compilation status from technique compilation output and technique info */ @@ -101,6 +140,12 @@ trait TechniqueCompilationStatusSyncService { */ def syncOne(result: EditorTechniqueCompilationResult): IOResult[Unit] + /* + * Given the identifier of technique, only update its known status and sync with the UI. + * Status applies to part of the id : only BundleName, so any version could be updated + */ + def syncTechniqueActiveStatus(bundleName: BundleName): IOResult[Unit] + def unsyncOne(id: (BundleName, Version)): IOResult[Unit] /** @@ -146,6 +191,35 @@ class TechniqueCompilationStatusService( } +/** + * Service to gather technique attributes using the directive reposistory : + * it knows about active techniques and their status + */ +class TechniqueActiveStatusService(directiveRepo: RoDirectiveRepository) extends ReadEditorTechniqueActiveStatus { + + override def getActiveStatus(id: BundleName): IOResult[Option[TechniqueActiveStatus]] = { + directiveRepo.getActiveTechnique(TechniqueName(id.value)).map(_.map(techniqueActiveStatus(_))) + } + override def getActiveStatuses(): IOResult[Map[BundleName, TechniqueActiveStatus]] = { + directiveRepo.getFullDirectiveLibrary().map(_.activeTechniques.map(t => techniqueId(t) -> techniqueActiveStatus(t)).toMap) + } + + private def techniqueId(technique: FullActiveTechnique): BundleName = BundleName(technique.techniqueName.value) + + private def techniqueActiveStatus(technique: ActiveTechnique): TechniqueActiveStatus = { + technique.isEnabled match { + case true => TechniqueActiveStatus.Enabled + case false => TechniqueActiveStatus.Disabled + } + } + private def techniqueActiveStatus(technique: FullActiveTechnique): TechniqueActiveStatus = { + technique.isEnabled match { + case true => TechniqueActiveStatus.Enabled + case false => TechniqueActiveStatus.Disabled + } + } +} + /** * Technique compilation output needs to be saved in a cache (frequent reads, we don't want to get files on the FS every time). * @@ -157,9 +231,10 @@ class TechniqueCompilationStatusService( * when technique library is reloaded */ class TechniqueCompilationErrorsActorSync( - actor: SimpleActor[UpdateCompilationStatus], - reader: ReadEditorTechniqueCompilationResult, - errorBase: Ref[Map[(BundleName, Version), EditorTechniqueError]] + actor: SimpleActor[UpdateCompilationStatus], + reader: ReadEditorTechniqueCompilationResult, + attributesReader: ReadEditorTechniqueActiveStatus, + errorBase: Ref[Map[(BundleName, Version), EditorTechniqueError]] ) extends TechniqueCompilationStatusSyncService { /* @@ -167,8 +242,17 @@ class TechniqueCompilationErrorsActorSync( */ def syncOne(result: EditorTechniqueCompilationResult): IOResult[Unit] = { for { - status <- updateOneStatus(result) - _ <- syncStatusWithUi(status) + activeStatus <- getActiveStatusOrDisabled(result.id) + status <- updateOneStatus(result, activeStatus) + _ <- syncStatusWithUi(status) + } yield () + } + + def syncTechniqueActiveStatus(bundleName: BundleName): IOResult[Unit] = { + for { + activeStatus <- getActiveStatusOrDisabled(bundleName) + status <- updateOneActiveStatus(bundleName, activeStatus) + _ <- syncStatusWithUi(status) } yield () } @@ -186,13 +270,17 @@ class TechniqueCompilationErrorsActorSync( } /* - * The whole process that lookup for compilation status and update everything + * The whole process that lookup for compilation status and update everything. + * Sync always looks up for the latest status of techniques to filter out disabled ones. */ def getUpdateAndSync(results: Option[List[EditorTechniqueCompilationResult]]): IOResult[Unit] = { (for { - results <- results.map(_.succeed).getOrElse(reader.get()) - status <- updateStatus(results) - _ <- syncStatusWithUi(status) + res <- results.map(_.succeed).getOrElse(reader.get()) + activeStatuses <- attributesReader.getActiveStatuses() + // ones without status are filtered out (if the status is unknown, they are ignored) + resWithStatus = res.flatMap(r => activeStatuses.get(r.id).map(r -> _)) + status <- updateStatus(resWithStatus) + _ <- syncStatusWithUi(status) } yield status).flatMap { case CompilationStatusAllSuccess => StatusLoggerPure.Techniques.info("All techniques have success compilation result") case e: CompilationStatusErrors => @@ -210,6 +298,16 @@ class TechniqueCompilationErrorsActorSync( IOResult.attempt(actor ! UpdateCompilationStatus(status)) } + /** + * Get the latest active status from the technique + * Not found technique should mean that it is disabled/deleted. + */ + private def getActiveStatusOrDisabled(id: BundleName): IOResult[TechniqueActiveStatus] = { + attributesReader + .getActiveStatus(id) + .map(_.getOrElse(TechniqueActiveStatus.Disabled)) + } + private def getStatus(errors: Iterable[EditorTechniqueError]): CompilationStatus = { NonEmptyChunk.fromIterableOption(errors) match { case None => CompilationStatusAllSuccess @@ -220,11 +318,16 @@ class TechniqueCompilationErrorsActorSync( /* * Update the internal cache and build a Compilation status */ - private[ncf] def updateStatus(results: List[EditorTechniqueCompilationResult]): UIO[CompilationStatus] = { + private[ncf] def updateStatus( + results: List[(EditorTechniqueCompilationResult, TechniqueActiveStatus)] + ): UIO[CompilationStatus] = { errorBase.updateAndGet { m => results.collect { - case r @ EditorTechniqueCompilationResult(id, version, name, CompilationResult.Error(error)) => - (getKey(r) -> EditorTechniqueError(id, version, name, error)) + case ( + r @ EditorTechniqueCompilationResult(id, version, name, CompilationResult.Error(error)), + activeStatus + ) => + (getKey(r) -> EditorTechniqueError(id, version, activeStatus, name, error)) }.toMap }.map(m => getStatus(m.values)) } @@ -232,11 +335,14 @@ class TechniqueCompilationErrorsActorSync( /** * Only take a single result to update the cached technique if it is there, else do nothing */ - private[ncf] def updateOneStatus(result: EditorTechniqueCompilationResult): UIO[CompilationStatus] = { + private[ncf] def updateOneStatus( + result: EditorTechniqueCompilationResult, + activeStatus: TechniqueActiveStatus + ): UIO[CompilationStatus] = { // only replace when current one is an error, when present or absent we should set the value val replacement: Option[EditorTechniqueError] => Option[EditorTechniqueError] = result match { case EditorTechniqueCompilationResult(id, version, name, CompilationResult.Error(error)) => - _ => Some(EditorTechniqueError(id, version, name, error)) + _ => Some(EditorTechniqueError(id, version, activeStatus, name, error)) case _ => _ => None } @@ -245,6 +351,21 @@ class TechniqueCompilationErrorsActorSync( .map(m => getStatus(m.values)) } + /** + * Only update the active status of the technique : replace the active status if the technique exists in cache + */ + private[ncf] def updateOneActiveStatus( + bundleName: BundleName, + activeStatus: TechniqueActiveStatus + ): UIO[CompilationStatus] = { + errorBase + .updateAndGet(_.map { + case (id @ (`bundleName`, version), err) => id -> err.copy(status = activeStatus) + case o => o + }) + .map(m => getStatus(m.values)) + } + private def getKey(result: EditorTechniqueCompilationResult): (BundleName, Version) = { result.id -> result.version } @@ -252,11 +373,12 @@ class TechniqueCompilationErrorsActorSync( object TechniqueCompilationErrorsActorSync { def make( - actor: SimpleActor[UpdateCompilationStatus], - reader: ReadEditorTechniqueCompilationResult + actor: SimpleActor[UpdateCompilationStatus], + reader: ReadEditorTechniqueCompilationResult, + attributesReader: ReadEditorTechniqueActiveStatus ): UIO[TechniqueCompilationErrorsActorSync] = { Ref .make(Map.empty[(BundleName, Version), EditorTechniqueError]) - .map(new TechniqueCompilationErrorsActorSync(actor, reader, _)) + .map(new TechniqueCompilationErrorsActorSync(actor, reader, attributesReader, _)) } } diff --git a/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueCompilationCache.scala b/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueCompilationCache.scala index ada3b3c35df..b184733c30e 100644 --- a/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueCompilationCache.scala +++ b/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueCompilationCache.scala @@ -105,6 +105,14 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { } + private val readTechniqueActiveStatus: ReadEditorTechniqueActiveStatus = new ReadEditorTechniqueActiveStatus { + override def getActiveStatus(id: BundleName): IOResult[Option[TechniqueActiveStatus]] = Some( + TechniqueActiveStatus.Enabled + ).succeed + override def getActiveStatuses(): IOResult[Map[BundleName, TechniqueActiveStatus]] = + techniques.map(_.id -> TechniqueActiveStatus.Enabled).toMap.succeed + } + // the SUT private val compilationStatusService: ReadEditorTechniqueCompilationResult = new TechniqueCompilationStatusService( editorTechniqueReader, @@ -150,7 +158,8 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { ) .runNow } - private val writeCache = TechniqueCompilationErrorsActorSync.make(mockActor, compilationStatusService).runNow + private val writeCache = + TechniqueCompilationErrorsActorSync.make(mockActor, compilationStatusService, readTechniqueActiveStatus).runNow // create output test files for each technique override def beforeAll(): Unit = { @@ -172,12 +181,14 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { EditorTechniqueError( technique1.id, technique1.version, + TechniqueActiveStatus.Enabled, technique1.name, "tech1 error" ), EditorTechniqueError( technique3.id, technique3.version, + TechniqueActiveStatus.Enabled, technique3.name, "tech3 error" ) @@ -197,7 +208,9 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { "Error repository" should { "Correctly build the status" in { - writeCache.updateStatus(expectedListOfOutputs).runNow must beEqualTo(expectedCompilationStatus) + writeCache.updateStatus(expectedListOfOutputs.map(_ -> TechniqueActiveStatus.Enabled)).runNow must beEqualTo( + expectedCompilationStatus + ) } val newError = { @@ -213,6 +226,7 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { EditorTechniqueError( newError.id, newError.version, + TechniqueActiveStatus.Enabled, newError.name, "new tech error" ) @@ -234,18 +248,20 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { CompilationResult.Error("new tech3 error") ) } - writeCache.updateOneStatus(updatedResult).runNow must beEqualTo( + writeCache.updateOneStatus(updatedResult, TechniqueActiveStatus.Enabled).runNow must beEqualTo( CompilationStatusErrors( NonEmptyChunk( EditorTechniqueError( technique1.id, technique1.version, + TechniqueActiveStatus.Enabled, technique1.name, "tech1 error" ), EditorTechniqueError( technique3.id, technique3.version, + TechniqueActiveStatus.Enabled, technique3.name, "new tech3 error" ) @@ -257,12 +273,13 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { "update with an technique in success" in { val success = EditorTechniqueCompilationResult(technique1.id, technique1.version, technique1.name, CompilationResult.Success) - writeCache.updateOneStatus(success).runNow must beEqualTo( + writeCache.updateOneStatus(success, TechniqueActiveStatus.Enabled).runNow must beEqualTo( CompilationStatusErrors( NonEmptyChunk( EditorTechniqueError( technique3.id, technique3.version, + TechniqueActiveStatus.Enabled, technique3.name, "new tech3 error" ) @@ -272,16 +289,33 @@ class TestTechniqueCompilationCache extends Specification with BeforeAfterAll { } "delete no longer existing techniques, keep only new one" in { - writeCache.updateStatus(List(newError)).runNow must beEqualTo( + writeCache.updateStatus(List(newError -> TechniqueActiveStatus.Enabled)).runNow must beEqualTo( newErrorStatus ) } + "update a technique with disabled status" in { + writeCache.updateOneStatus(newError, TechniqueActiveStatus.Disabled).runNow must beEqualTo( + CompilationStatusErrors( + newErrorStatus.techniquesInError.map(_.copy(status = TechniqueActiveStatus.Disabled)) + ) + ) + } + + "sync technique active status" in { + // bring the status back to Enabled + (writeCache.syncTechniqueActiveStatus(newError.id) *> + msgLock.withPermit( + (mockActor hasReceivedMessage_? UpdateCompilationStatus(newErrorStatus)).succeed + )).runNow.aka("actor received message") must beTrue and (mockActor.messageCount must beEqualTo(2)) + } + "unsync one" in { (writeCache.unsyncOne(newError.id -> newError.version) *> msgLock.withPermit( (mockActor hasReceivedMessage_? UpdateCompilationStatus(CompilationStatusAllSuccess)).succeed - )).runNow.aka("actor received message") must beTrue and (mockActor.messageCount must beEqualTo(2)) + )).runNow.aka("actor received message") must beTrue and (mockActor.messageCount must beEqualTo(3)) } + } } diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala index f5291015dca..f4957f2dd9c 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala @@ -1274,6 +1274,7 @@ object RudderConfig extends Loggable { val updateDynamicGroups: UpdateDynamicGroups = rci.updateDynamicGroups val updateDynamicGroupsService: DynGroupUpdaterService = rci.updateDynamicGroupsService val updateTechniqueLibrary: UpdateTechniqueLibrary = rci.updateTechniqueLibrary + val techniqueCompilationStatusService: TechniqueCompilationStatusSyncService = rci.techniqueCompilationStatusService val userPropertyService: UserPropertyService = rci.userPropertyService val userRepository: UserRepository = rci.userRepository val userService: UserService = rci.userService @@ -1460,7 +1461,8 @@ case class RudderServiceApi( computeNodeStatusReportService: ComputeNodeStatusReportService & HasNodeStatusReportUpdateHook, scoreRepository: ScoreRepository, propertiesRepository: PropertiesRepository, - propertiesService: NodePropertiesService + propertiesService: NodePropertiesService, + techniqueCompilationStatusService: TechniqueCompilationStatusSyncService ) /* @@ -1919,8 +1921,14 @@ object RudderConfigInit { techniqueCompiler ) + lazy val techniqueStatusReaderService: ReadEditorTechniqueActiveStatus = new TechniqueActiveStatusService( + roDirectiveRepository + ) + lazy val techniqueCompilationCache: TechniqueCompilationStatusSyncService = { - val sync = TechniqueCompilationErrorsActorSync.make(asyncDeploymentAgent, techniqueCompilationStatusService).runNow + val sync = TechniqueCompilationErrorsActorSync + .make(asyncDeploymentAgent, techniqueCompilationStatusService, techniqueStatusReaderService) + .runNow techniqueRepositoryImpl.registerCallback(new SyncCompilationStatusOnTechniqueCallback("SyncCompilationStatus", 10000, sync)) sync } @@ -3839,7 +3847,8 @@ object RudderConfigInit { computeNodeStatusReportService, scoreRepository, propertiesRepository, - propertiesService + propertiesService, + techniqueCompilationCache ) // start init effects diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/comet/AsyncDeployment.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/comet/AsyncDeployment.scala index 559c68f72d0..8f7faeb53a2 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/comet/AsyncDeployment.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/comet/AsyncDeployment.scala @@ -106,9 +106,10 @@ class AsyncDeployment extends CometActor with CometListener with Loggable { override def lowPriority: PartialFunction[Any, Unit] = { case msg: AsyncDeploymentActorCreateUpdate => deploymentStatus = msg.deploymentStatus - compilationStatus = msg.compilationStatus nodeProperties = msg.nodeProperties groupProperties = msg.groupProperties + // we want to completely ignore rendering of disabled techniques, so we can directly adapt the received message + compilationStatus = CompilationStatus.ignoreDisabledTechniques(msg.compilationStatus) reRender() } diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/TechniqueEditForm.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/TechniqueEditForm.scala index 41280faeb4a..a7dd356c859 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/TechniqueEditForm.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/TechniqueEditForm.scala @@ -45,6 +45,7 @@ import com.normation.eventlog.ModificationId import com.normation.rudder.batch.AutomaticStartDeployment import com.normation.rudder.domain.eventlog.RudderEventActor import com.normation.rudder.domain.policies.* +import com.normation.rudder.ncf.BundleName import com.normation.rudder.services.policies.* import com.normation.rudder.users.CurrentUser import com.normation.rudder.web.ChooseTemplate @@ -102,15 +103,16 @@ class TechniqueEditForm( import TechniqueEditForm.* // find Technique - private val techniqueRepository = RudderConfig.techniqueRepository - private val roActiveTechniqueRepository = RudderConfig.roDirectiveRepository - private val rwActiveTechniqueRepository = RudderConfig.woDirectiveRepository - private val uuidGen = RudderConfig.stringUuidGenerator + private val techniqueRepository = RudderConfig.techniqueRepository + private val roActiveTechniqueRepository = RudderConfig.roDirectiveRepository + private val rwActiveTechniqueRepository = RudderConfig.woDirectiveRepository + private val techniqueCompilationStatusService = RudderConfig.techniqueCompilationStatusService + private val uuidGen = RudderConfig.stringUuidGenerator // transform Technique variable to human viewable HTML fields - private val directiveEditorService = RudderConfig.directiveEditorService - private val dependencyService = RudderConfig.dependencyAndDeletionService - private val asyncDeploymentAgent = RudderConfig.asyncDeploymentAgent - private val userPropertyService = RudderConfig.userPropertyService + private val directiveEditorService = RudderConfig.directiveEditorService + private val dependencyService = RudderConfig.dependencyAndDeletionService + private val asyncDeploymentAgent = RudderConfig.asyncDeploymentAgent + private val userPropertyService = RudderConfig.userPropertyService private var currentActiveTechnique: Box[ActiveTechnique] = Box(activeTechnique).or { for { @@ -409,7 +411,7 @@ class TechniqueEditForm( } else { currentActiveTechnique = currentActiveTechnique.map(activeTechnique => activeTechnique.copy(_isEnabled = status)) JsRaw("hideBsModal('disableActionDialog');") & // JsRaw ok, const - statusAndDeployTechnique(activeTechnique.id, status) + statusAndDeployTechnique(activeTechnique, status) } } @@ -561,12 +563,13 @@ class TechniqueEditForm( private def error(msg: String) = {msg} - private def statusAndDeployTechnique(uactiveTechniqueId: ActiveTechniqueId, status: Boolean): JsCmd = { + private def statusAndDeployTechnique(activeTechnique: ActiveTechnique, status: Boolean): JsCmd = { val modId = ModificationId(uuidGen.newUuid) (for { - save <- rwActiveTechniqueRepository - .changeStatus(uactiveTechniqueId, status, modId, CurrentUser.actor, crReasonsDisablePopup.map(_.get)) - .toBox + save <- + (rwActiveTechniqueRepository + .changeStatus(activeTechnique.id, status, modId, CurrentUser.actor, crReasonsDisablePopup.map(_.get)) + <* techniqueCompilationStatusService.syncTechniqueActiveStatus(BundleName(activeTechnique.techniqueName.value))).toBox deploy <- { asyncDeploymentAgent ! AutomaticStartDeployment(modId, RudderEventActor) Full("Policy update request sent") diff --git a/webapp/sources/rudder/rudder-web/src/test/scala/bootstrap/liftweb/checks/migration/TestMigrateJsonTechniquesToYaml.scala b/webapp/sources/rudder/rudder-web/src/test/scala/bootstrap/liftweb/checks/migration/TestMigrateJsonTechniquesToYaml.scala index 835748db398..caa76de06cb 100644 --- a/webapp/sources/rudder/rudder-web/src/test/scala/bootstrap/liftweb/checks/migration/TestMigrateJsonTechniquesToYaml.scala +++ b/webapp/sources/rudder/rudder-web/src/test/scala/bootstrap/liftweb/checks/migration/TestMigrateJsonTechniquesToYaml.scala @@ -55,6 +55,7 @@ import com.normation.rudder.ncf.EditorTechniqueReader import com.normation.rudder.ncf.EditorTechniqueReaderImpl import com.normation.rudder.ncf.GenericMethod import com.normation.rudder.ncf.GitResourceFileService +import com.normation.rudder.ncf.ReadEditorTechniqueActiveStatus import com.normation.rudder.ncf.ReadEditorTechniqueCompilationResult import com.normation.rudder.ncf.ResourceFile import com.normation.rudder.ncf.ResourceFileState @@ -62,6 +63,7 @@ import com.normation.rudder.ncf.RuddercOptions import com.normation.rudder.ncf.RuddercResult import com.normation.rudder.ncf.RuddercService import com.normation.rudder.ncf.RuddercTechniqueCompiler +import com.normation.rudder.ncf.TechniqueActiveStatus import com.normation.rudder.ncf.TechniqueCompilationErrorsActorSync import com.normation.rudder.ncf.TechniqueCompilationStatusService import com.normation.rudder.ncf.TechniqueWriterImpl @@ -162,7 +164,7 @@ class TestMigrateJsonTechniquesToYaml extends Specification with ContentMatchers "root" ) - val editorTechniqueReader: EditorTechniqueReader = new EditorTechniqueReaderImpl( + val editorTechniqueReader: EditorTechniqueReader = new EditorTechniqueReaderImpl( null, null, gitMock.gitRepo, @@ -179,12 +181,19 @@ class TestMigrateJsonTechniquesToYaml extends Specification with ContentMatchers override def getMethodsMetadata: IOResult[Map[BundleName, GenericMethod]] = Map.empty.succeed override def updateMethodsMetadataFile: IOResult[CmdResult] = Inconsistency("this should not be called").fail } - val compilationStatusService: ReadEditorTechniqueCompilationResult = new TechniqueCompilationStatusService( + val compilationStatusService: ReadEditorTechniqueCompilationResult = new TechniqueCompilationStatusService( editorTechniqueReader, techniqueCompiler ) - val compilationCache: TechniqueCompilationErrorsActorSync = - TechniqueCompilationErrorsActorSync.make(restTestSetUp.asyncDeploymentAgent, compilationStatusService).runNow + val techniqueActiveStatusService: ReadEditorTechniqueActiveStatus = new ReadEditorTechniqueActiveStatus { + override def getActiveStatus(id: BundleName): IOResult[Option[TechniqueActiveStatus]] = None.succeed + override def getActiveStatuses(): IOResult[Map[BundleName, TechniqueActiveStatus]] = Map.empty.succeed + } + val compilationCache: TechniqueCompilationErrorsActorSync = { + TechniqueCompilationErrorsActorSync + .make(restTestSetUp.asyncDeploymentAgent, compilationStatusService, techniqueActiveStatusService) + .runNow + } val techniqueWriter = new TechniqueWriterImpl( techniqueArchiver, techMock.techniqueRepo,