Skip to content

Commit

Permalink
Merge with master
Browse files Browse the repository at this point in the history
  • Loading branch information
fanf committed May 17, 2021
1 parent ec99e66 commit 17cfed2
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class WoLDAPRuleRepository(
case (false, true) => Inconsistency(s"Non-system Rule '${id.value}' can not be deleted with that method").fail
case _ => oldCr.succeed
}
deleted <- con.delete(rudderDit.RULES.configRuleDN(id.value, None)).chainError("Error when deleting rule with ID %s".format(id))
deleted <- con.delete(rudderDit.RULES.configRuleDN(id, None)).chainError("Error when deleting rule with ID %s".format(id))
diff = DeleteRuleDiff(oldCr)
loggedAction <- actionLogger.saveDeleteRule(modId, principal = actor, deleteDiff = diff, reason = reason)
autoArchive <- ZIO.when(autoExportOnModify && deleted.nonEmpty && !oldCr.isSystem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ final case class BoundPolicyDraft(
PolicyTechnique.forAgent(technique, agent).flatMap { pt =>
expandedVars.collectFirst { case (_, v) if(!v.spec.constraint.mayBeEmpty && v.values.exists(_ == "")) => v } match {
case Some(v) =>
Left(s"Error for policy for directive '${directiveName}' [${id.directiveId.value}] in rule '${ruleName}' [${id.ruleId.value}]: " +
Left(s"Error for policy for directive '${directiveName}' [${id.directiveRId.debugString}] in rule '${ruleName}' [${id.ruleId.value}]: " +
s"a non optional value is missing for parameter '${v.spec.description}' [param ID: ${v.spec.name}]")
case None =>
Right(Policy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import zio.syntax._
import com.normation.zio._
import com.softwaremill.quicklens._
import cats.implicits._
import com.normation.rudder.configuration.ConfigurationRepository
import com.normation.rudder.services.policies.nodeconfig.FileBasedNodeConfigurationHashRepository
import com.normation.rudder.utils.ParseMaxParallelism

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ object NodeConfigurationHash {
def toJvalue(hash: NodeConfigurationHash): JValue = {
(
("i" -> JArray(List(hash.id.value, hash.writtenDate.toString(ISODateTimeFormat.dateTime()), hash.nodeInfoHash, hash.parameterHash, hash.nodeContextHash)))
~ ("p" -> JArray(hash.policyHash.toList.map(p => JArray(List(p.draftId.ruleId.value, p.draftId.directiverId.serialize, p.draftId.techniqueVersion.serialize, p.cacheValue)))))
~ ("p" -> JArray(hash.policyHash.toList.map(p => JArray(List(p.draftId.ruleId.value, p.draftId.directiveRId.serialize, p.draftId.techniqueVersion.serialize, p.cacheValue)))))
)
}
def toJson(hash: NodeConfigurationHash): String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ class ReportsTest extends DBCommon {
"get reports" in {
val res = repostsRepo.getReportsfromId(0, DateTime.now().plusDays(1)).open
val expected = Seq(
AgentRun(AgentRunId(NodeId("n0"),run1),None,true,109)
, AgentRun(AgentRunId(NodeId("n1"),run1),Some(NodeConfigId("n1_run1")),true,115)
, AgentRun(AgentRunId(NodeId("n1"),run2),Some(NodeConfigId("n1_run2")),true,118)
, AgentRun(AgentRunId(NodeId("n2"),run1),Some(NodeConfigId("n2_run1")),true,120)
AgentRun(AgentRunId(NodeId("n0"),run1),None,109)
, AgentRun(AgentRunId(NodeId("n1"),run1),Some(NodeConfigId("n1_run1")),115)
, AgentRun(AgentRunId(NodeId("n1"),run2),Some(NodeConfigId("n1_run2")),118)
, AgentRun(AgentRunId(NodeId("n2"),run1),Some(NodeConfigId("n2_run1")),120)
)

val checkInsert = transacRun(xa => sql"""select id from ruddersysevents""".query[Long].to[Vector].transact(xa)).size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import better.files._
import com.normation.cfclerk.domain._
import com.normation.inventory.domain.NodeId
import com.normation.rudder.domain.policies.DirectiveId
import com.normation.rudder.domain.policies.DirectiveRId
import com.normation.rudder.domain.policies.RuleId
import com.normation.rudder.services.policies.PolicyId
import net.liftweb.common.Box
Expand All @@ -56,6 +57,15 @@ import org.specs2.specification.AfterAll
@RunWith(classOf[JUnitRunner])
class NodeConfigurationCacheRepositoryTest extends Specification with AfterAll with Loggable {

implicit class ParseTechniqueVerison(s: String) {
def toTV: TechniqueVersion = {
TechniqueVersion.parse(s) match {
case Right(v) => v
case Left(e) => throw new IllegalArgumentException(s"Error when parsing '${s}' as a technique version: ${e}")
}
}
}

implicit class ForceGet[A](b: Box[A]) {
def forceGet = b match {
case Full(a) => a
Expand Down Expand Up @@ -84,21 +94,21 @@ class NodeConfigurationCacheRepositoryTest extends Specification with AfterAll w
val h0_0 = NodeConfigurationHash(NodeId("node0"), d0, 0, 0, 0, Set())

val h1_0 = NodeConfigurationHash(NodeId("node1"), d0, 0, 0, 0, Set(
PolicyHash(PolicyId(RuleId("r0"), DirectiveId("d0"), TechniqueVersion("1.0")), 0)
, PolicyHash(PolicyId(RuleId("r1"), DirectiveId("d1"), TechniqueVersion("1.0")), 0)
PolicyHash(PolicyId(RuleId("r0"), DirectiveRId(DirectiveId("d0"), None), TechniqueVersionHelper("1.0")), 0)
, PolicyHash(PolicyId(RuleId("r1"), DirectiveRId(DirectiveId("d1"), None), TechniqueVersionHelper("1.0")), 0)
))

val h2_0 = NodeConfigurationHash(NodeId("node2"), d0, 0, 0, 0, Set(
PolicyHash(PolicyId(RuleId("r0"), DirectiveId("d0"), TechniqueVersion("1.0")), 0)
PolicyHash(PolicyId(RuleId("r0"), DirectiveRId(DirectiveId("d0"), None), TechniqueVersionHelper("1.0")), 0)
))

val h1_1 = NodeConfigurationHash(NodeId("node1"), d1, 0, 0, 0, Set(
PolicyHash(PolicyId(RuleId("r0"), DirectiveId("d0"), TechniqueVersion("1.0")), 0)
, PolicyHash(PolicyId(RuleId("r2"), DirectiveId("d2"), TechniqueVersion("1.0")), 0)
PolicyHash(PolicyId(RuleId("r0"), DirectiveRId(DirectiveId("d0"), None), TechniqueVersionHelper("1.0")), 0)
, PolicyHash(PolicyId(RuleId("r2"), DirectiveRId(DirectiveId("d2"), None), TechniqueVersionHelper("1.0")), 0)
))

val h3_0 = NodeConfigurationHash(NodeId("node3"), d1, 0, 0, 0, Set(
PolicyHash(PolicyId(RuleId("r3"), DirectiveId("d3"), TechniqueVersion("1.0")), 0)
PolicyHash(PolicyId(RuleId("r3"), DirectiveRId(DirectiveId("d3"), None), TechniqueVersionHelper("1.0")), 0)
))

val s1 = Set(h1_0, h0_0, h2_0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ class ReportingServiceUtilsTest extends Specification {
)
}
// a case where two directive from the same unique technique are on two rules
def thisOverrideThatOn2(overrider: RuleId, directiver: DirectiveId, overridden: RuleId, directiven: DirectiveId) = {
def thisOverrideThatOn2(overrider: RuleId, directiver: DirectiveRId, overridden: RuleId, directiven: DirectiveRId) = {
OverridenPolicy(
PolicyId(overridden, directiven, TechniqueVersion("1.0")) //this one is
, PolicyId(overrider , directiver, TechniqueVersion("1.0")) //overridden by that one
PolicyId(overridden, directiven, TechniqueVersionHelper("1.0")) //this one is
, PolicyId(overrider , directiver, TechniqueVersionHelper("1.0")) //overridden by that one
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
package com.normation.rudder.rest

import com.github.ghik.silencer.silent
import com.normation.GitVersion.ParseRev
import com.normation.GitVersion.RevId
import com.normation.cfclerk.domain.Technique
import com.normation.cfclerk.domain.TechniqueName
import com.normation.cfclerk.domain.TechniqueVersion
Expand Down Expand Up @@ -728,7 +730,13 @@ trait RudderJsonEncoders {

/*
* Object used in JSON query POST/PUT request.
* For disambiguation, objects are prefixed by JQ
* For disambiguation, objects are prefixed by JQ.
*
* Note about id/revision: it does not make sense to try to change a
* revision, it's immutable. Only head can be changed, so revId is never
* specified in JQ object.
* It can make sense to clone a specific revision, so sourceId can have a
* sourceRevId too.
*/
object JsonQueryObjects {
import JsonResponseObjects.JRRuleTarget
Expand Down Expand Up @@ -795,6 +803,7 @@ object JsonQueryObjects {
, tags : Option[Tags] = None
//for clone
, source : Option[String] = None
, sourceRevId : Option[String] = None
) {
val onlyName = displayName.isDefined &&
shortDescription.isEmpty &&
Expand Down Expand Up @@ -823,6 +832,11 @@ object JsonQueryObjects {
, tags
))
}

def getSourceId = source match {
case None => None
case Some(x) => Some(DirectiveRId(DirectiveId(x), sourceRevId.map(RevId)))
}
}

final case class JQRule(
Expand All @@ -837,6 +851,7 @@ object JsonQueryObjects {
, tags : Option[Tags] = None
//for clone
, source : Option[String] = None
, sourceRevId : Option[String] = None
) {

val onlyName = displayName.isDefined &&
Expand Down Expand Up @@ -885,10 +900,11 @@ object JsonQueryObjects {

final case class JQGroupProperty(
name : String
, revId : Option[String]
, value : ConfigValue
, inheritMode: Option[InheritMode]
) {
def toGroupProperty = GroupProperty(name, value, inheritMode, Some(PropertyProvider.defaultPropertyProvider))
def toGroupProperty = GroupProperty(name, revId.map(RevId), value, inheritMode, Some(PropertyProvider.defaultPropertyProvider))
}

final case class JQStringQuery(
Expand All @@ -911,15 +927,16 @@ object JsonQueryObjects {
)

final case class JQGroup(
id : Option[String] = None
, displayName : Option[String] = None
, description : Option[String] = None
, properties : Option[List[GroupProperty]]
, query : Option[StringQuery] = None
, dynamic : Option[Boolean] = None
, enabled : Option[Boolean] = None
id : Option[String] = None
, displayName : Option[String] = None
, description : Option[String] = None
, properties : Option[List[GroupProperty]] = None
, query : Option[StringQuery] = None
, dynamic : Option[Boolean] = None
, enabled : Option[Boolean] = None
, category : Option[NodeGroupCategoryId] = None
, source : Option[String] = None
, source : Option[String] = None
, sourceRevId : Option[String] = None
) {

val onlyName = displayName.isDefined &&
Expand Down Expand Up @@ -1162,11 +1179,12 @@ class ZioJsonExtractor(queryParser: CmdbQueryParser with JsonQueryLexer) {
def extractDirectiveFromParams(params: Map[String,List[String]]) : PureResult[JQDirective] = {

for {
enabled <- params.parse("enabled" , JsonDecoder[Boolean])
priority <- params.parse("priority" , JsonDecoder[Int])
parameters <- params.parse("parameters" , JsonDecoder[Map[String, JQDirectiveSection]])
policyMode <- params.parse2("policyMode", PolicyMode.parseDefault(_))
tags <- params.parse("tags" , JsonDecoder[Tags])
enabled <- params.parse("enabled" , JsonDecoder[Boolean])
priority <- params.parse("priority" , JsonDecoder[Int])
parameters <- params.parse("parameters" , JsonDecoder[Map[String, JQDirectiveSection]])
policyMode <- params.parse2("policyMode" , PolicyMode.parseDefault(_))
tags <- params.parse("tags" , JsonDecoder[Tags])
tv <- params.parse2("techniqueVersion", TechniqueVersion.parse(_).left.map(Inconsistency(_)))
} yield {
JQDirective(
params.optGet("id")
Expand All @@ -1177,10 +1195,11 @@ class ZioJsonExtractor(queryParser: CmdbQueryParser with JsonQueryLexer) {
, parameters
, priority
, params.optGet("techniqueName").map(TechniqueName)
, params.optGet("techniqueVersion").map(TechniqueVersion(_))
, tv
, policyMode
, tags
, params.optGet("source")
, params.optGet("sourceRevId")
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ final case class RestDataSerializerImpl (
~ ( "categoryId" -> rule.categoryId.value)
~ ( "shortDescription" -> rule.shortDescription )
~ ( "longDescription" -> rule.longDescription )
~ ( "directives" -> rule.directiveIds.toList.map(x => JsonDirectiveId.fromRId(x).json).sorted )
~ ( "directives" -> rule.directiveIds.toList.sortBy(_.serialize).map(x => JsonDirectiveId.fromRId(x).json) )
~ ( "targets" -> rule.targets.map(_.toJson) )
~ ( "enabled" -> rule.isEnabledStatus )
~ ( "system" -> rule.isSystem )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

package com.normation.rudder.rest.lift

import com.normation.GitVersion.RevId
import com.normation.cfclerk.domain.Technique
import com.normation.cfclerk.domain.TechniqueId
import com.normation.cfclerk.services.TechniqueRepository
Expand Down Expand Up @@ -74,11 +75,12 @@ import net.liftweb.http.LiftResponse
import net.liftweb.http.Req
import net.liftweb.json.JArray
import net.liftweb.json.JsonAST.JValue

import com.normation.box._
import com.normation.cfclerk.domain.TechniqueName
import com.normation.cfclerk.domain.TechniqueVersion
import com.normation.errors._
import com.normation.rudder.configuration.ConfigurationRepository
import com.normation.rudder.domain.policies.DirectiveRId
import zio._
import zio.syntax._
import com.normation.rudder.rest._
Expand Down Expand Up @@ -222,7 +224,8 @@ class DirectiveApi (
object DirectiveDetailsV14 extends LiftApiModuleString {
val schema = API.DirectiveDetails
def process(version: ApiVersion, path: ApiPath, id: String, req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = {
serviceV14.directiveDetails(DirectiveId(id)).toLiftResponseOne(params, schema, _.id)
val revId = req.params.get("revId").flatMap(_.headOption).map(RevId)
serviceV14.directiveDetails(DirectiveRId(DirectiveId(id), revId)).toLiftResponseOne(params, schema, _.id)
}
}

Expand All @@ -232,7 +235,7 @@ class DirectiveApi (

(for {
restDirective <- zioJsonExtractor.extractDirective(req).chainError(s"Could not extract directive parameters from request").toIO
result <- serviceV14.createOrCloneDirective(restDirective, DirectiveId(restDirective.id.getOrElse(uuidGen.newUuid)), restDirective.source.map(DirectiveId), params, authzToken.actor)
result <- serviceV14.createOrCloneDirective(restDirective, DirectiveId(restDirective.id.getOrElse(uuidGen.newUuid)), restDirective.getSourceId, params, authzToken.actor)
} yield {
val action = if (restDirective.source.nonEmpty) "cloneDirective" else schema.name
(RudderJsonResponse.ResponseSchema(action, schema.dataContainer), result)
Expand Down Expand Up @@ -525,6 +528,7 @@ class DirectiveApiService2 (

class DirectiveApiService14 (
readDirective : RoDirectiveRepository
, readRevDirective : ConfigurationRepository
, writeDirective : WoDirectiveRepository
, uuidGen : StringUuidGenerator
, asyncDeploymentAgent : AsyncDeploymentActor
Expand All @@ -551,7 +555,7 @@ class DirectiveApiService14 (
}
}

def createOrCloneDirective(restDirective: JQDirective, directiveId : DirectiveId, source: Option[DirectiveId], params: DefaultParams, actor: EventActor): IOResult[JRDirective] = {
def createOrCloneDirective(restDirective: JQDirective, directiveId: DirectiveId, source: Option[DirectiveRId], params: DefaultParams, actor: EventActor): IOResult[JRDirective] = {
def actualDirectiveCreation(restDirective: JQDirective, baseDirective: Directive, activeTechnique: ActiveTechnique, technique: Technique, params: DefaultParams, actor: EventActor): IOResult[JRDirective] = {
val newDirective = restDirective.updateDirective(baseDirective)
val modId = ModificationId(uuidGen.newUuid)
Expand Down Expand Up @@ -581,7 +585,8 @@ class DirectiveApiService14 (
case Some(cloneId) =>
for {
name <- restDirective.displayName.checkMandatory(_.size > 3, v => "'displayName' is mandatory and must be at least 3 char long")
triple <- readDirective.getDirectiveWithContext(cloneId).notOptional(s"Cannot find Directive '${cloneId.value}' to use as clone base.")
// TODO: manage revId
triple <- readDirective.getDirectiveWithContext(cloneId.id).notOptional(s"Cannot find Directive '${cloneId.debugString}' to use as clone base.")
(technique, activeTechnique, sourceDirective) = triple
version <- DirectiveApiService.checkTechniqueVersion(techniqueRepository, technique.id.name, restDirective.techniqueVersion).chainError(s"Cannot find a valid technique version" ).toIO
newDirective = restDirective.copy(enabled = Some(false), techniqueVersion = version)
Expand All @@ -595,7 +600,7 @@ class DirectiveApiService14 (
name <- restDirective.displayName.checkMandatory(_.size > 3, v => "'displayName' is mandatory and must be at least 3 char long")
technique <- DirectiveApiService.extractTechnique(techniqueRepository, restDirective.techniqueName, restDirective.techniqueVersion).chainError(s"Technique is not correctly defined in request data.").toIO
activeTechnique <- readDirective.getActiveTechnique(technique.id.name).notOptional(s"Technique ${technique.id.name} cannot be found.")
baseDirective = Directive(directiveId, technique.id.version, Map(), name, "", None, _isEnabled = true)
baseDirective = Directive(directiveId, None, technique.id.version, Map(), name, "", None, _isEnabled = true)
result <- actualDirectiveCreation(restDirective, baseDirective, activeTechnique, technique, params, actor)
} yield {
result
Expand Down Expand Up @@ -640,6 +645,7 @@ class DirectiveApiService14 (
}

def deleteDirective(id: DirectiveId, params: DefaultParams, actor: EventActor): IOResult[JRDirective] = {
// TODO: manage revId
readDirective.getDirectiveWithContext(id).flatMap {
case Some((technique, activeTechnique, directive)) =>
val change = DirectiveChangeRequest(DGModAction.Delete, technique.id.name, activeTechnique.id, technique.rootSection, directive, Some(directive), Nil, Nil)
Expand All @@ -650,9 +656,10 @@ class DirectiveApiService14 (
}


def directiveDetails(id: DirectiveId): IOResult[JRDirective] = {
def directiveDetails(id: DirectiveRId): IOResult[JRDirective] = {
for {
triple <- readDirective.getDirectiveWithContext(id).notOptional(s"Could not find Directive ${id.value}")
// TODO: manage revId
triple <- readDirective.getDirectiveWithContext(id.id).notOptional(s"Could not find Directive ${id.debugString}")
} yield {
JRDirective.fromDirective(triple._1, triple._3, None)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ class ParameterApiService14 (

def createParameter(restParameter: JQGlobalParameter, params: DefaultParams, actor: EventActor): IOResult[JRGlobalParameter] = {
import com.normation.rudder.domain.nodes.GenericProperty._
val baseParameter = GlobalParameter.apply("", "".toConfigValue, None,"",None)
val baseParameter = GlobalParameter.apply("", None, "".toConfigValue, None,"",None)
val parameter = restParameter.updateParameter(baseParameter)
val diff = AddGlobalParameterDiff(parameter)
val p = GenericProperty.patternName // pattern for parameter ID
Expand Down
Loading

0 comments on commit 17cfed2

Please sign in to comment.