Skip to content

Commit

Permalink
Fixes #26046: Migrate compliance status from lift-json to zio-json
Browse files Browse the repository at this point in the history
  • Loading branch information
fanf committed Jan 8, 2025
1 parent 232427a commit 8124190
Show file tree
Hide file tree
Showing 19 changed files with 732 additions and 526 deletions.
2 changes: 1 addition & 1 deletion webapp/sources/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ limitations under the License.
<jgrapht-version>1.5.2</jgrapht-version>
<reflections-version>0.10.2</reflections-version>
<graalvm-version>24.1.1</graalvm-version>
<chimney-version>1.5.0</chimney-version>
<chimney-version>1.6.0</chimney-version>
<cron4s-version>0.7.0</cron4s-version>
<ipaddress-version>5.5.1</ipaddress-version>
<snakeyaml-version>2.3</snakeyaml-version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import doobie.util.log.ExecFailure
import doobie.util.log.LogEvent
import doobie.util.log.ProcessingFailure
import doobie.util.transactor
import io.scalaland.chimney.syntax.*
import java.sql.SQLXML
import javax.sql.DataSource
import net.liftweb.common.*
Expand Down Expand Up @@ -279,15 +280,16 @@ object Doobie {
}
}

/*
* The 4 following ones are used in udder-core/src/main/scala/com/normation/rudder/repository/jdbc/ComplianceRepository.scala
*/
implicit val CompliancePercentWrite: Write[CompliancePercent] = {
import ComplianceLevelSerialisation.*
import net.liftweb.json.*
Write[String].contramap(x => compactRender(x.toJson))
Write[String].contramap(x => x.transformInto[ComplianceSerializable].toJson)
}

implicit val ComplianceRunInfoComposite: Write[(RunAnalysis, RunComplianceInfo)] = {
import NodeStatusReportSerialization.*
Write[String].contramap(_.toCompactJson)
Write[String].contramap(runToJson)
}

implicit val AggregatedStatusReportComposite: Write[AggregatedStatusReport] = {
Expand All @@ -297,7 +299,7 @@ object Doobie {

implicit val SetRuleNodeStatusReportComposite: Write[Set[RuleNodeStatusReport]] = {
import NodeStatusReportSerialization.*
Write[String].contramap(_.toCompactJson)
Write[String].contramap(ruleNodeStatusReportToJson)
}

import doobie.enumerated.JdbcType.SqlXml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
*/
package com.normation.rudder.domain.policies

import com.normation.rudder.repository.json.DataExtractor.CompleteJson
import com.normation.rudder.repository.json.JsonExtractorUtils
import net.liftweb.common.*
import com.normation.errors.PureResult
import com.normation.errors.Unexpected
import io.scalaland.chimney.*
import io.scalaland.chimney.syntax.*
import zio.json.*

/**
* Tags that apply on Rules and Directives
Expand All @@ -64,52 +66,38 @@ final case class Tags(tags: Set[Tag]) extends AnyVal {
}

object Tags {
// get tags from a list of key/value embodied by a Map with one elements (but
// also works with several elements in map)
def fromMaps(tags: List[Map[String, String]]): Tags = {
Tags(tags.flatMap(_.map { case (k, v) => Tag(TagName(k), TagValue(v)) }).toSet)
private case class JsonTag(key: String, value: String)
implicit private val transformTag: Transformer[Tag, JsonTag] = { case Tag(name, value) => JsonTag(name.value, value.value) }
implicit private val transformJsonTag: Transformer[JsonTag, Tag] = {
case JsonTag(name, value) => Tag(TagName(name), TagValue(value))
}
}

object JsonTagSerialisation {

import net.liftweb.json.*
import net.liftweb.json.JsonDSL.*

def serializeTags(tags: Tags): JValue = {

// sort all the tags by name
val m: JValue = JArray(
tags.tags.toList.sortBy(_.name.value).map(t => ("key" -> t.name.value) ~ ("value" -> t.value.value): JObject)
)

m
implicit private val transformTags: Transformer[Tags, List[JsonTag]] = {
case Tags(tags) => tags.toList.sortBy(_.name.value).map(_.transformInto[JsonTag])
}
implicit private val transformListJsonTag: Transformer[List[JsonTag], Tags] = {
case list => Tags(list.map(_.transformInto[Tag]).toSet)
}

}

trait JsonTagExtractor[M[_]] extends JsonExtractorUtils[M] {
import net.liftweb.json.*
implicit private val codecJsonTag: JsonCodec[JsonTag] = DeriveJsonCodec.gen
implicit val encoderTags: JsonEncoder[Tags] = JsonEncoder.list[JsonTag].contramap(_.transformInto[List[JsonTag]])
implicit val decoderTags: JsonDecoder[Tags] = JsonDecoder.list[JsonTag].map(_.transformInto[Tags])

def unserializeTags(value: String): Box[M[Tags]] = {
parseOpt(value) match {
case Some(json) => extractTags(json)
case _ => Failure(s"Invalid JSON serialization for Tags ${value}")
}
// get tags from a list of key/value embodied by a Map with one elements (but
// also works with several elements in map)
def fromMaps(tags: List[Map[String, String]]): Tags = {
Tags(tags.flatMap(_.map { case (k, v) => Tag(TagName(k), TagValue(v)) }).toSet)
}

def convertToTag(jsonTag: JValue): Box[Tag] = {
for {
tagName <- CompleteJson.extractJsonString(jsonTag, "key", s => Full(TagName(s)))
tagValue <- CompleteJson.extractJsonString(jsonTag, "value", s => Full(TagValue(s)))
} yield {
Tag(tagName, tagValue)
}
}
val empty: Tags = Tags(Set())

def extractTags(value: JValue): Box[M[Tags]] = {
extractJsonArray(value, "")(convertToTag).map(k =>
monad.map(k)(tags => Tags(tags.toSet))
) ?~! s"Invalid JSON serialization for Tags ${value}"
// we have a lot of cases where we parse an `Option[String]` into a `PureResult[Tags]` with
// default value `Tags.empty`. The string format is:
// [{"key":"k1","value":"v1"},{"key":"k2","value":"v2"}]
def parse(opt: Option[String]): PureResult[Tags] = {
opt match {
case Some(v) => v.fromJson[Tags].left.map(Unexpected.apply)
case None => Right(Tags.empty)
}
}
}
Loading

0 comments on commit 8124190

Please sign in to comment.