From 5916cfb479a3456d1e95bc526693f060dc8c9809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Membr=C3=A9?= Date: Tue, 23 Jul 2019 17:02:56 +0200 Subject: [PATCH] Fixes #15265: Migrate ncf delete api and improve workflow --- .../rudder/ncf/TechniqueWriter.scala | 35 +++++++++++++++++++ .../rudder/ncf/TestTechniqueWriter.scala | 9 +++-- .../rudder/rest/EndpointsDefinition.scala | 4 +++ .../normation/rudder/rest/lift/NcfApi.scala | 32 ++++++++++++++--- .../bootstrap/liftweb/RudderConfig.scala | 2 +- 5 files changed, 75 insertions(+), 7 deletions(-) diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueWriter.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueWriter.scala index 157f14131c1..b019355514e 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueWriter.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/ncf/TechniqueWriter.scala @@ -55,6 +55,7 @@ import java.nio.file.Paths import better.files.File import com.normation.cfclerk.services.UpdateTechniqueLibrary import com.normation.errors.IOResult +import com.normation.rudder.repository.RoDirectiveRepository import com.normation.rudder.repository.xml.RudderPrettyPrinter import com.normation.rudder.services.user.PersonIdentService import net.liftweb.common.Full @@ -79,12 +80,33 @@ class TechniqueWriter ( archiver : TechniqueArchiver , techLibUpdate : UpdateTechniqueLibrary , translater : InterpolatedValueCompiler + , readDirectives : RoDirectiveRepository , xmlPrettyPrinter : RudderPrettyPrinter , basePath : String ) { private[this] var agentSpecific = new ClassicTechniqueWriter(basePath) :: new DSCTechniqueWriter(basePath, translater) :: Nil + def deleteTechnique(techniqueName : String, techniqueVersion : String, modId : ModificationId, committer : EventActor) : IOResult[Unit] ={ + val resourcesPath = s"techniques/ncf_techniques/${techniqueName}/${techniqueVersion}" + + val resourceDir = File(s"/var/rudder/configuration-repository/${resourcesPath}") + + for { + d <- readDirectives.getFullDirectiveLibrary().map(_.allActiveTechniques.values.filter(_.techniqueName.value == techniqueName).flatMap(_.directives).filter(_.techniqueVersion.toString == techniqueVersion)) + _ <- (d match { + case Nil => Right(d) + case _ => Left(Inconsistancy(s"${d.size} directive are defined please delete them")) + }).toIO + _ <- archiver.deleteTechnique(techniqueName,techniqueVersion,modId,committer, s"Deleting technique ${techniqueName}/${techniqueVersion}") + + libUpdate <- techLibUpdate.update(modId, committer, Some(s"Update Technique library after deletion of Technique ${techniqueName}")). + toIO.chainError(s"An error occured during technique update after deletion of Technique ${techniqueName}") + } yield { + () + } + } + def techniqueMetadataContent(technique : Technique, methods: Map[BundleName, GenericMethod]) : PureResult[XmlNode] = { def reportingValuePerMethod (component: String, calls :Seq[MethodCall]) : PureResult[Seq[XmlNode]] = { @@ -547,6 +569,7 @@ class DSCTechniqueWriter( } trait TechniqueArchiver { + def deleteTechnique(techniqueName : String, techniqueVersion : String, modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] def commitTechnique(technique : Technique, filesToAdd : Seq[String], modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] } @@ -564,6 +587,18 @@ class TechniqueArchiverImpl ( override val encoding : String = "UTF-8" + def deleteTechnique(techniqueName : String, techniqueVersion : String, modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] = { + (for { + git <- gitRepo.git + ident <- personIdentservice.getPersonIdentOrDefault(commiter.name) + rm <- IOResult.effect(git.rm.addFilepattern(s"techniques/ncf_techniques/${techniqueName}/${techniqueVersion}").call()) + + commit <- IOResult.effect(git.commit.setCommitter(ident).setMessage(msg).call()) + } yield { + s"techniques/ncf_techniques/${techniqueName}/${techniqueVersion}" + }).chainError(s"error when deleting and committing Technique '${techniqueName}/${techniqueVersion}").unit + } + def commitTechnique(technique : Technique, gitPath : Seq[String], modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] = { val filesToAdd = diff --git a/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueWriter.scala b/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueWriter.scala index c55e7019c79..4f1009eb186 100644 --- a/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueWriter.scala +++ b/webapp/sources/rudder/rudder-core/src/test/scala/com/normation/rudder/ncf/TestTechniqueWriter.scala @@ -48,6 +48,7 @@ import com.normation.eventlog.EventActor import com.normation.eventlog.ModificationId import com.normation.inventory.domain.AgentType import com.normation.inventory.domain.Version +import com.normation.rudder.repository.RoDirectiveRepository import com.normation.rudder.repository.xml.RudderPrettyPrinter import com.normation.rudder.services.policies.InterpolatedValueCompilerImpl import com.normation.zio._ @@ -69,7 +70,8 @@ class TestTechniqueWriter extends Specification with ContentMatchers with Loggab val expectedPath = "src/test/resources/configuration-repository" object TestTechniqueArchiver extends TechniqueArchiver { - def commitTechnique(technique : Technique, gitPath : Seq[String], modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] = UIO.unit + def commitTechnique(technique : Technique, gitPath : Seq[String], modId: ModificationId, commiter: EventActor, msg : String) : IOResult[Unit] = UIO.unit + def deleteTechnique(techniqueName: String, techniqueVersion: String, modId: ModificationId, commiter: EventActor, msg: String): IOResult[Unit] = UIO.unit } object TestLibUpdater extends UpdateTechniqueLibrary { @@ -77,8 +79,11 @@ class TestTechniqueWriter extends Specification with ContentMatchers with Loggab def registerCallback(callback:TechniquesLibraryUpdateNotification) : Unit = () } + // Not used in test for now + def readDirectives : RoDirectiveRepository = ??? + val valueCompiler = new InterpolatedValueCompilerImpl - val writer = new TechniqueWriter(TestTechniqueArchiver,TestLibUpdater,valueCompiler, new RudderPrettyPrinter(Int.MaxValue, 2), basePath) + val writer = new TechniqueWriter(TestTechniqueArchiver,TestLibUpdater,valueCompiler, readDirectives, new RudderPrettyPrinter(Int.MaxValue, 2), basePath) val dscWriter = new DSCTechniqueWriter(basePath, valueCompiler) val classicWriter = new ClassicTechniqueWriter(basePath) diff --git a/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/EndpointsDefinition.scala b/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/EndpointsDefinition.scala index c92a2c552a1..2be67a351ae 100644 --- a/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/EndpointsDefinition.scala +++ b/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/EndpointsDefinition.scala @@ -184,6 +184,10 @@ object NcfApi extends ApiModuleProvider[NcfApi] { val description = "Create a new technique in Rudder from a technique in the technique editor" val (action, path) = PUT / "techniques" } + final case object DeleteTechnique extends NcfApi with TwoParam with StartsAtVersion9 with SortIndex { val z = implicitly[Line].value + val description = "Delete a technique from technique editor" + val (action, path) = DELETE / "techniques" / "{techniqueId}" / "{techniqueVersion}" + } final case object GetResources extends NcfApi with TwoParam with StartsAtVersion15 with SortIndex { val z = implicitly[Line].value val description = "Get currently deployed resources of a technique" val (action, path) = GET / "techniques" / "{techniqueId}" / "{techniqueVersion}" / "resources" diff --git a/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/lift/NcfApi.scala b/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/lift/NcfApi.scala index 202972c9e94..0061d3623a5 100644 --- a/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/lift/NcfApi.scala +++ b/webapp/sources/rudder/rudder-rest/src/main/scala/com/normation/rudder/rest/lift/NcfApi.scala @@ -60,6 +60,7 @@ import com.normation.rudder.ncf.ResourceFile import com.normation.rudder.ncf.ResourceFileState import net.liftweb.json.JsonAST.JArray import com.normation.rudder.ncf.CheckConstraint +import com.normation.rudder.repository.RoDirectiveRepository class NcfApi( techniqueWriter : TechniqueWriter @@ -82,10 +83,11 @@ class NcfApi( def schemas = API def getLiftEndpoints(): List[LiftApiModule] = { API.endpoints.map(e => e match { - case API.UpdateTechnique => UpdateTechnique - case API.CreateTechnique => CreateTechnique - case API.GetResources => GetResources - case API.ParameterCheck => ParameterCheck + case API.UpdateTechnique => UpdateTechnique + case API.CreateTechnique => CreateTechnique + case API.GetResources => GetResources + case API.ParameterCheck => ParameterCheck + case API.DeleteTechnique => DeleteTechnique }) } @@ -158,6 +160,28 @@ class NcfApi( resp(getRessourcesStatus.toBox, req, "Could not get resource state of technique")("techniqueResources") } } + + + object DeleteTechnique extends LiftApiModule { + val schema = API.DeleteTechnique + val restExtractor = restExtractorService + implicit val dataName = "techniques" + + def process(version: ApiVersion, path: ApiPath, techniqueInfo: (String, String), req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = { + + val modId = ModificationId(uuidGen.newUuid) + + val content = techniqueWriter.deleteTechnique(techniqueInfo._1, techniqueInfo._2, modId, authzToken.actor).toBox.map { _ => + import net.liftweb.json.JsonDSL._ + ( ("id" -> techniqueInfo._1 ) + ~ ("version" -> techniqueInfo._2 ) + ) + } + + resp(content,req,"delete technique")("deleteTechnique") + + } + } object UpdateTechnique extends LiftApiModule0 { val schema = API.UpdateTechnique val restExtractor = restExtractorService 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 8c7e3237a0b..d9beae49b7f 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 @@ -776,7 +776,7 @@ object RudderConfig extends Loggable { ) val techniqueArchiver = new TechniqueArchiverImpl(gitRepo, new File(RUDDER_DIR_GITROOT) , prettyPrinter, "/", gitModificationRepository, personIdentService) - val ncfTechniqueWriter = new TechniqueWriter(techniqueArchiver, updateTechniqueLibrary, interpolationCompiler, prettyPrinter, RUDDER_DIR_GITROOT) + val ncfTechniqueWriter = new TechniqueWriter(techniqueArchiver, updateTechniqueLibrary, interpolationCompiler, roDirectiveRepository, prettyPrinter, RUDDER_DIR_GITROOT) val ApiVersions = ApiVersion(7 , true ) ::