Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
fanf committed Oct 26, 2017
1 parent 7861963 commit 9436e90
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 110 deletions.
5 changes: 0 additions & 5 deletions rudder-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,6 @@ along with Rudder. If not, see <http://www.gnu.org/licenses/>.
<version>${spring-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>

<!-- that dep is needed to make scalac happy and avoid "missing class NotNull" -->
<dependency>
Expand Down
10 changes: 10 additions & 0 deletions rudder-core/src/main/scala/com/normation/rudder/db/Doobie.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ object Doobie {
case \/-(a) => Full(a)
}
}
implicit def xorBoxToBox[A](res: \/[Throwable, Box[A]]): Box[A] = res match {
case -\/(e) => Failure(e.getMessage, Full(e), Empty)
case \/-(a) => a
}
implicit class XorBoxToBox[A](res: \/[Throwable, Box[A]]) {
def box = res match {
case -\/(e) => Failure(e.getMessage, Full(e), Empty)
case \/-(a) => a
}
}

/*
* Doobie is missing a Query0 builder, so here is simple one.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@ package com.normation.rudder.migration

import scala.xml.Elem

import org.springframework.jdbc.core.JdbcTemplate

import com.normation.rudder.domain.Constants
import com.normation.rudder.services.marshalling.TestFileFormat

import net.liftweb.common.Box
import net.liftweb.util.Helpers.StringToCssBindPromoter
import net.liftweb.util.Helpers.tryo
import com.normation.rudder.db.Doobie

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,16 @@ import java.sql.ResultSet
import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.Timestamp
import org.springframework.jdbc.core.JdbcTemplate
import com.normation.rudder.domain.workflows.ChangeRequest
import org.springframework.jdbc.core.RowMapper
import com.normation.rudder.domain.workflows.ConfigurationChangeRequest
import com.normation.rudder.domain.workflows.ChangeRequestId
import com.normation.rudder.domain.workflows.ChangeRequestInfo
import scala.util.{Try, Failure => Catch, Success}
import scala.collection.JavaConversions._
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
import com.normation.rudder.domain.policies.DirectiveId
import com.normation.rudder.domain.nodes.NodeGroupId
import com.normation.rudder.domain.policies.RuleId
import com.normation.rudder.repository.WoChangeRequestRepository
import com.normation.rudder.services.marshalling.ChangeRequestChangesSerialisation
import org.springframework.jdbc.support.GeneratedKeyHolder
import org.springframework.jdbc.core.PreparedStatementCreator
import com.normation.eventlog.EventActor
import com.normation.rudder.services.marshalling.ChangeRequestChangesUnserialisation
import scala.xml.XML
Expand All @@ -70,80 +64,53 @@ import com.normation.rudder.domain.logger.ApplicationLogger
import com.normation.eventlog.ModificationId
import scala.xml.Elem

import com.normation.rudder.db.Doobie
import com.normation.rudder.db.Doobie._
import scalaz.{Failure => _, _}, Scalaz._
import doobie.imports._
import scalaz.concurrent.Task
import com.normation.utils.Control


class RoChangeRequestJdbcRepository(
jdbcTemplate : JdbcTemplate
, changeRequestsMapper : ChangeRequestsMapper
doobie: Doobie
, mapper: ChangeRequestMapper
) extends RoChangeRequestRepository with Loggable {

import doobie._
import mapper.ChangeRequestComposite


val SELECT_SQL = "SELECT id, name, description, creationTime, content, modificationId FROM ChangeRequest"

val SELECT_SQL_JOIN_WORKFLOW = "SELECT CR.id, name, description, creationTime, content, modificationId FROM changeRequest CR LEFT JOIN workflow W on CR.id = W.id"

override def getAll() : Box[Vector[ChangeRequest]] = {
Try {
jdbcTemplate.query(SELECT_SQL, Array[AnyRef](), changeRequestsMapper).toSeq
} match {
case Success(x) =>
Full(x.:\(Vector[ChangeRequest]()){(changeRequest,seq) => changeRequest match {
case Full(cr) => seq :+ cr
case eb:EmptyBox =>
seq
}
} )

case Catch(error) =>
Failure(error.toString())
}
val q = query[Box[ChangeRequest]](SELECT_SQL)
q.vector.attempt.map(
// we are just ignoring change request with unserialisation
// error. Does not seem the best.
_.map(_.flatten.toVector)
).transact(xa).run
}

override def get(changeRequestId:ChangeRequestId) : Box[Option[ChangeRequest]] = {
Try {
jdbcTemplate.query(
SELECT_SQL + " where id = ?"
, Array[AnyRef](changeRequestId.value.asInstanceOf[AnyRef])
, changeRequestsMapper).toSeq
} match {
case Success(x) => x match {
case Seq() => Full(None)
case Seq(res) => Full(res.headOption)
case _ => Failure(s"Too many change request have the same id ${changeRequestId.value}")
}
case Catch(error) => Failure(error.toString())
}
val q = Query[ChangeRequestId, Box[ChangeRequest]](SELECT_SQL + " where id = ?", None).toQuery0(changeRequestId)
q.option.map(_.map(_.toOption)).transact(xa).run

}

// Get every change request where a user add a change
override def getByContributor(actor:EventActor) : Box[Vector[ChangeRequest]] = {
Try {

jdbcTemplate.query(
new PreparedStatementCreator() {
def createPreparedStatement(connection : Connection) : PreparedStatement = {

val query= s"${SELECT_SQL} where cast( xpath('//firstChange/change/actor/text()',content) as text[]) = ?"
val ps = connection.prepareStatement(
query, Array[String]());
ps.setArray(1, connection.createArrayOf("text", Seq(actor.name).toArray[AnyRef]) )
val q = (fr"${SELECT_SQL}" ++ sql"""where cast( xpath('//firstChange/change/actor/text()',content) as text[]) = ${actor.name}""").query[Box[ChangeRequest]]

// if with have eventtype filter, apply them
ps
}
}, changeRequestsMapper)
} match {
case Success(x) =>
Full(x.:\(Vector[ChangeRequest]()){(changeRequest,seq) => changeRequest match {
case Full(cr) => seq :+ cr
case eb:EmptyBox =>
seq
}
} )
case Catch(x) => ApplicationLogger.error(s"could not fetch change request for user ${actor}: ${x}")
Failure(s"could not fetch change request for user ${actor}")
}
q.vector.attempt.map(
// we are just ignoring change request with unserialisation
// error. Does not seem the best.
_.map(_.flatten.toVector)
).transact(xa).run
}

override def getByDirective(id : DirectiveId, onlyPending:Boolean) : Box[Vector[ChangeRequest]] = {
Expand Down Expand Up @@ -212,7 +179,6 @@ class RoChangeRequestJdbcRepository(

class WoChangeRequestJdbcRepository(
jdbcTemplate : JdbcTemplate
, crSerialiser : ChangeRequestChangesSerialisation
, roRepo : RoChangeRequestRepository
) extends WoChangeRequestRepository with Loggable {

Expand Down Expand Up @@ -328,53 +294,71 @@ class WoChangeRequestJdbcRepository(
}
}

// doobie mapping, must be done here because of TechniqueRepo in ChangeRequestChangesUnserialisation impl
class ChangeRequestMapper(
crcUnserialiser: ChangeRequestChangesUnserialisation
, crcSerialiser : ChangeRequestChangesSerialisation
) extends Loggable {

implicit val ChangeRequestComposite: Composite[Box[ChangeRequest]] = {

class ChangeRequestsMapper(
changeRequestChangesUnserialisation : ChangeRequestChangesUnserialisation
) extends RowMapper[Box[ChangeRequest]] with Loggable {

type CR = (Int, Elem, Option[String], Option[String], Option[String])

// unserialize the XML.
// If it fails, produce a failure
// directives map is boxed because some Exception could be launched
def unserialize(id: Int, content: Elem, modId: Option[String], name: Option[String], description: Option[String]) = {
changeRequestChangesUnserialisation.unserialise(content) match {
case Full((directivesMaps, nodesMaps, ruleMaps, paramMaps)) =>
directivesMaps match {
case Full(map) => Full(ConfigurationChangeRequest(
ChangeRequestId(id)
, modId.map(ModificationId.apply)
, ChangeRequestInfo(
name.getOrElse("")
, description.getOrElse("")
)
, map
, nodesMaps
, ruleMaps
, paramMaps
) )
case eb:EmptyBox =>
val fail = eb ?~! s"could not deserialize directive change of change request #${id} cause is: ${eb}"
ApplicationLogger.error(fail)
def unserialize(id: Int, content: Elem, modId: Option[String], name: Option[String], description: Option[String]): Box[ConfigurationChangeRequest] = {
crcUnserialiser.unserialise(content) match {
case Full((directivesMaps, nodesMaps, ruleMaps, paramMaps)) =>
directivesMaps match {
case Full(map) => Full(ConfigurationChangeRequest(
ChangeRequestId(id)
, modId.map(ModificationId.apply)
, ChangeRequestInfo(
name.getOrElse("")
, description.getOrElse("")
)
, map
, nodesMaps
, ruleMaps
, paramMaps
) )

case eb:EmptyBox =>
val fail = eb ?~! s"could not deserialize directive change of change request #${id} cause is: ${eb}"
logger.error(fail)
fail
}

case eb:EmptyBox =>
val fail = eb ?~! s"Error when trying to get the content of the change request ${id} : ${eb}"
logger.error(fail.msg)
fail
}
}
}

def serialize(optCR: Box[ChangeRequest]): CR = {
optCR match {
case Full(cr) =>
val elem = crcSerialiser.serialise(cr)
val name = cr.info.name match {
case "" => None
case x => Some(x)
}
val desc = cr.info.description match {
case "" => None
case x => Some(x)
}
(cr.id.value, elem, cr.modId.map(_.value), name, desc)

case eb:EmptyBox =>
val fail = eb ?~! s"Error when trying to get the content of the change request ${id} : ${eb}"
logger.error(fail.msg)
fail
case _ => throw new IllegalArgumentException(s"We can only serialize Full(ChangeRequest)")
}
}
}

def mapRow(rs : ResultSet, rowNum: Int) : Box[ChangeRequest] = {
unserialize(
rs.getInt("id")
, XML.load(rs.getSQLXML("content").getBinaryStream())
, Some(rs.getString("modificationId"))
, Some(rs.getString("name"))
, Some(rs.getString("description"))
Composite[CR].xmap(
(t : CR ) => unserialize(t._1, t._2, t._3, t._4, t._5)
, (cr: Box[ChangeRequest]) => serialize(cr)
)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,10 @@ import com.normation.rudder.db.Doobie
import com.normation.rudder.db.Doobie._
import scalaz.{Failure => _, _}, Scalaz._
import doobie.imports._
import scalaz.concurrent.Task
import doobie.postgres.pgtypes._
import com.normation.rudder.db.DB
import com.normation.rudder.services.reports._
import com.normation.inventory.domain.NodeId
import org.joda.time.DateTime
import com.normation.rudder.domain.reports.RunComplianceInfo
import com.normation.rudder.domain.reports.ComplianceLevel
import com.normation.rudder.domain.reports.AggregatedStatusReport
import com.normation.rudder.domain.reports.CompliancePercent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,9 @@ import com.normation.rudder.repository.ReportsRepository

import org.joda.time._
import org.slf4j.{Logger,LoggerFactory}
import org.springframework.jdbc.core._

import net.liftweb.common._
import net.liftweb.common.Box._
import org.springframework.dao.DataAccessException

import scalaz.{Failure => _, _}, Scalaz._
import doobie.imports._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ package com.normation.rudder.services.system

import net.liftweb.common._
import org.joda.time.DateTime
import org.springframework.jdbc.core.JdbcTemplate
import net.liftweb.common.Loggable
import com.normation.rudder.repository.ReportsRepository
import com.normation.rudder.repository.UpdateExpectedReportsRepository
Expand Down

0 comments on commit 9436e90

Please sign in to comment.