Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
fanf committed Jan 28, 2022
1 parent 9d0becd commit 0b41ff3
Show file tree
Hide file tree
Showing 14 changed files with 7,982 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
*************************************************************************************
* Copyright 2022 Normation SAS
*************************************************************************************
*
* This file is part of Rudder.
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
* Public License version 3, when you create a Related Module, this
* Related Module is not considered as a part of the work and may be
* distributed under the license agreement of your choice.
* A "Related Module" means a set of sources files including their
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
* Rudder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************************
*/

package com.normation.inventory.domain

import com.normation.errors._
import zio._
import zio.syntax._

import zio.json._

/*
* This file provide serializer for core inventory objects.
* They assume the object IS the law regarding field names and type.
* It means that they are ill suited to public APIs that should use a translation stub
* to provide garanties on stability.
* They are well suited for internal API that needs to evolve with the code.
*
*
* Use
* import zio.json._
* import com.normation.inventory.domain.JsonSerializers.implicits._
*
* to import serializer in code, then:
*
* val obj = fromJson(jsonString)
* val jsonString = toJson(obj)
*/


object JsonSerializers {
object implicits extends InventoryJsonEncoders with InventoryJsonDecoders
}


// encoder from object to json string
trait InventoryJsonEncoders {
implicit val softwareUpdateKindEnd : JsonEncoder[SoftwareUpdateKind] = JsonEncoder[String].contramap { k =>
k match {
case SoftwareUpdateKind.Other(v) => v
case kind => kind.name
}
}
implicit val softwareUpdateEnc: JsonEncoder[SoftwareUpdate] = DeriveJsonEncoder.gen

}


trait InventoryJsonDecoders {

implicit val softwareUpdateKindDec: JsonDecoder[SoftwareUpdateKind] = JsonDecoder[String].map(s =>
SoftwareUpdateKind.parse(s)
)

implicit val softwareUpdateDec: JsonDecoder[SoftwareUpdate] = DeriveJsonDecoder.gen
}

Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,44 @@ final case class CustomProperty(
, value: JValue
)


sealed trait SoftwareUpdateKind {
def name: String
}

final object SoftwareUpdateKind {
final case object None extends SoftwareUpdateKind { val name = "none" }
final case object Defect extends SoftwareUpdateKind { val name = "defect" }
final case object Security extends SoftwareUpdateKind { val name = "security" }
final case object Enhancement extends SoftwareUpdateKind { val name = "enhancement" }
final case class Other(value: String) extends SoftwareUpdateKind { val name = "other" }

def all = ca.mrvisser.sealerate.collect[SoftwareUpdateKind]

def parse(value: String) = all.find( _.name == value.toLowerCase()).getOrElse(Other(value))
}


/*
* A software update:
* - name: software name (the same that installed, used as key)
* - version: target version (only one, different updates for different version)
* - arch: arch of the package (x86_64, etc)
* - from: tools that produced that update (yum, apt, etc)
* - what kind
* - source: from what source like repo name (for now, they are not specific)
* #TODO: other informations ? A Map[String, String] of things ?
*/
final case class SoftwareUpdate(
name : String
, version: String
, arch : String
, from : String
, kind : SoftwareUpdateKind
, source : Option[String]
)


object KeyStatus {
def apply(value : String) : Either[InventoryError.SecurityToken, KeyStatus] = {
value match {
Expand Down Expand Up @@ -396,6 +434,8 @@ final case class NodeInventory(
*/
, timezone : Option[NodeTimezone] = None
, customProperties : List[CustomProperty] = Nil

, softwareUpdates : List[SoftwareUpdate] = Nil
) {

/**A copy of the node with the updated main.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,37 @@ class FusionInventoryParser(
}
}

/*
we have a list of UPDATE elements:
<UPDATE>
<NAME>rudder-agent</NAME>
<ARCH>x86_64</ARCH>
<FROM>yum</FROM>
<VERSION>7.0.1.release.EL.7</VERSION>
</UPDATE>
*/
def processSoftwareUpdates(xml:NodeSeq) : List[SoftwareUpdate] = {
def getOrError(e: NodeSeq, f: String) =
optTextHead(e \ f).notOptionalPure(s"Missing mandatory SOTWARE_UPDATE element: '${f}'")
(xml \ "UPDATE").flatMap { e =>
(for {
n <- getOrError(e, "NAME")
v <- getOrError(e, "VERSION")
a <- getOrError(e, "ARCH")
f <- getOrError(e, "FROM")
k = optText(e \ "KIND").map(SoftwareUpdateKind.parse(_)).getOrElse(SoftwareUpdateKind.None)
s = optText(e \ "SOURCE" )
} yield {
SoftwareUpdate(n, v, a, f, k, s)
}) match {
case Left(err) =>
InventoryProcessingLogger.logEffect.warn(s"Ignoring malformed software update: '${err.fullMsg}': ${e}")
None
case Right(value) =>
Some(value)
}
}.toList
}

/*
* Process agents. We want to keep the maximum number of agents,
Expand Down Expand Up @@ -417,10 +448,11 @@ class FusionInventoryParser(
rootUser <- uniqueValueInSeq(agents.map(_._2), "could not parse rudder user (tag OWNER) from rudder specific inventory")
policyServerId <- uniqueValueInSeq(agents.map(_._3), "could not parse policy server id (tag POLICY_SERVER_UUID) from specific inventory")
// Node Custom properties from agent hooks
customProperties = processCustomProperties(xml \ "CUSTOM_PROPERTIES")
customProperties = processCustomProperties(xml \ "CUSTOM_PROPERTIES")
// hostname is a special case processed in `processHostname`
// capabilties should be per agent
capabilities = processAgentCapabilities(xml)
capabilities = processAgentCapabilities(xml)
softwareUpdates = processSoftwareUpdates( xml \ "SOFTWARE_UPDATES")
} yield {

inventory.copy (
Expand All @@ -432,6 +464,7 @@ class FusionInventoryParser(
)
, agents = agents.map(_._1.copy(capabilities = capabilities))
, customProperties = customProperties
, softwareUpdates = softwareUpdates
)
)
} ) catchAll { eb =>
Expand Down
Loading

0 comments on commit 0b41ff3

Please sign in to comment.