Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
clarktsiory committed May 3, 2024
1 parent d7bf321 commit d349385
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import com.normation.rudder.services.queries.JsonQueryLexer
import com.normation.rudder.services.queries.StringCriterionLine
import com.normation.rudder.services.queries.StringQuery
import com.typesafe.config.ConfigValue
import io.scalaland.chimney.Transformer
import io.scalaland.chimney.dsl.*
import net.liftweb.common.*
import net.liftweb.http.Req
Expand Down Expand Up @@ -334,7 +335,37 @@ object JsonQueryObjects {
}
}

// policy servers are serialized in their output format
final case class JQNodeDetailLevel(
fields: Set[String]
) extends AnyVal

object JQNodeDetailLevel {
implicit val transformer: Transformer[JQNodeDetailLevel, NodeDetailLevel] = (jq: JQNodeDetailLevel) => {
import jq.fields
if (fields.contains("full")) {
FullDetailLevel
} else {
val base = {
if (fields.contains("minimal")) {
MinimalDetailLevel
} else {
DefaultDetailLevel
}
}
val customFields = fields.filter { field =>
field != "minimal" &&
field != "default" &&
NodeDetailLevel.allFields.contains(field)
}
if (customFields.isEmpty) {
base
} else {
val customLevel = CustomDetailLevel(base, customFields.toSet)
customLevel
}
}
}
}
}

trait RudderJsonDecoders {
Expand Down Expand Up @@ -466,6 +497,12 @@ class ZioJsonExtractor(queryParser: CmdbQueryParser with JsonQueryLexer) {
*/
implicit class Extract(params: Map[String, List[String]]) {
def optGet(key: String): Option[String] = params.get(key).flatMap(_.headOption)
def parseOne[A](key: String, decoder: String => A): PureResult[Option[A]] = {
optGet(key) match {
case None => Right(None)
case Some(x) => Right(Some(decoder(x)))
}
}
def parse[A](key: String, decoder: JsonDecoder[A]): PureResult[Option[A]] = {
optGet(key) match {
case None => Right(None)
Expand Down Expand Up @@ -622,4 +659,8 @@ class ZioJsonExtractor(queryParser: CmdbQueryParser with JsonQueryLexer) {
}
}

def extractNodeDetailLevelFromParams(params: Map[String, List[String]]): PureResult[Option[JQNodeDetailLevel]] = {
params.parseOne("include", _.split(",").toSet.transformInto[JQNodeDetailLevel])
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ import com.normation.cfclerk.domain.Technique
import com.normation.cfclerk.domain.TechniqueName
import com.normation.cfclerk.domain.TechniqueVersion
import com.normation.errors.*
import com.normation.inventory.domain.InventoryStatus
import com.normation.inventory.domain.NodeId
import com.normation.inventory.domain.Version
import com.normation.rudder.apidata.JsonResponseObjects.JRPropertyHierarchy.JRPropertyHierarchyHtml
import com.normation.rudder.apidata.JsonResponseObjects.JRPropertyHierarchy.JRPropertyHierarchyJson
import com.normation.rudder.domain.nodes.NodeGroup
import com.normation.rudder.domain.nodes.NodeGroupCategoryId
import com.normation.rudder.domain.nodes.NodeGroupId
import com.normation.rudder.domain.nodes.NodeState
import com.normation.rudder.domain.policies.*
import com.normation.rudder.domain.properties.GenericProperty
import com.normation.rudder.domain.properties.GlobalParameter
Expand Down Expand Up @@ -103,6 +106,73 @@ object RenderInheritedProperties {

// to avoid ambiguity with corresponding business objects, we use "JR" as a prfix
object JsonResponseObjects {

// Node details json with all fields optional but minimal fields. Fields are in the same order as in the list of all fields.
final case class JRNodeDetailLevel(
// minimal
id: NodeId,
hostname: String,
status: InventoryStatus,
// default
state: Option[NodeState],
os: Option[JRNodeDetailLevel.Os],
architectureDescription: Option[String],
ram: Option[String],
machine: Option[String],
ipAddresses: Option[String],
description: Option[String],
lastInventoryDate: Option[String],
lastRunDate: Option[String],
policyServerId: Option[String],
managementTechnology: Option[String],
properties: Option[String],
policyMode: Option[String],
timezone: Option[String],
tenant: Option[String],
// full
accounts: Option[String],
bios: Option[String],
controllers: Option[String],
environmentVariables: Option[String],
fileSystems: Option[String],
managementTechnologyDetails: Option[String],
memories: Option[String],
networkInterfaces: Option[String],
processes: Option[String],
processors: Option[String],
slots: Option[String],
software: Option[String],
softwareUpdate: Option[String],
sound: Option[String],
storage: Option[String],
ports: Option[String],
videos: Option[String],
virtualMachines: Option[String]
)

object JRNodeDetailLevel {
implicit val encoder: JsonEncoder[JRNodeDetailLevel] = DeriveJsonEncoder.gen[JRNodeDetailLevel]

@jsonDiscriminator("name") sealed trait OsType
object OsType {
case object Linux extends OsType
case object Windows extends OsType
case object Bsd extends OsType
@jsonHint("AIX") case object AixOS extends OsType
@jsonHint("Solaris") case object SolarisOS extends OsType
@jsonHint("Unknown") case object UnknownOSType extends OsType
}

case class Os(
@jsonField("type") os: OsType,
name: String,
version: Version,
fullName: String,
servicepack: Option[String],
kernelVersion: Version
)
}

final case class JRActiveTechnique(
name: String,
versions: List[String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import com.normation.rudder.api.ApiVersion
import com.normation.rudder.apidata.NodeDetailLevel
import com.normation.rudder.apidata.RenderInheritedProperties
import com.normation.rudder.apidata.RestDataSerializer
import com.normation.rudder.apidata.ZioExtractorService
import com.normation.rudder.domain.NodeDit
import com.normation.rudder.domain.logger.NodeLogger
import com.normation.rudder.domain.logger.NodeLoggerPure
Expand Down Expand Up @@ -167,6 +168,7 @@ import zio.syntax.*
*/
class NodeApi(
restExtractorService: RestExtractorService,
zioExtractorService: ZioExtractorService,
serializer: RestDataSerializer,
nodeApiService: NodeApiService,
inheritedProperties: NodeApiInheritedProperties,
Expand Down Expand Up @@ -257,7 +259,7 @@ class NodeApi(

object NodeDetails extends LiftApiModule {
val schema: OneParam = API.NodeDetails
val restExtractor = restExtractorService
val restExtractor = zioExtractorService
def process(
version: ApiVersion,
path: ApiPath,
Expand All @@ -266,13 +268,13 @@ class NodeApi(
params: DefaultParams,
authzToken: AuthzToken
): LiftResponse = {
restExtractor.extractNodeDetailLevel(req.params) match {
case Full(level) =>
nodeApiService.nodeDetailsGeneric(NodeId(id), level)(params.prettify, authzToken.qc)
case eb: EmptyBox =>
val failMsg = eb ?~ "node detail level not correctly sent"
toJsonError(None, failMsg.msg)("nodeDetail", params.prettify)
}
(for {
level <- restExtractor.extractNodeDetailLevel(req.params).chainError("error with node level detail").toIO
res <-
nodeApiService.getNodeDetails(NodeId(id), level.map(_.transformInto[NodeDetailLevel]).getOrElse(DefaultDetailLevel))
} yield {
res
}).toLiftResponseOne(params, schema, _ => Some(id))
}
}

Expand Down

0 comments on commit d349385

Please sign in to comment.