Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
VinceMacBuche committed Jan 11, 2017
1 parent ebd4b91 commit c571ea7
Show file tree
Hide file tree
Showing 2 changed files with 351 additions and 4 deletions.
@@ -0,0 +1,61 @@
/*
*************************************************************************************
* Copyright 2016 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.rudder.web.rest

import org.junit._
import org.junit.Assert._
import org.junit.runner._
import org.junit.runner.RunWith
import org.specs2.mutable._
import org.specs2.runner._

import RestTestSetUp._
import net.liftweb.common.Full
import net.liftweb.http.PlainTextResponse

@RunWith(classOf[JUnitRunner])
class RestDirectiveTest extends Specification {

"testing REST API for directive" should {
"be correct" in {
testGET("/api/status") { req =>
RestStatus(req)() must beEqualTo(Full(PlainTextResponse("OK")))
}
}
}
}
Expand Up @@ -64,7 +64,225 @@ import net.liftweb.http.LiftResponse
import net.liftweb.util.NamedPF
import net.liftweb.http.S
import net.liftweb.common.EmptyBox
import net.liftweb.json.JsonAST.JValue
import com.normation.rudder.repository.RoDirectiveRepository
import com.normation.cfclerk.domain._
import com.normation.rudder.domain.policies._
import com.normation.rudder.repository.FullActiveTechnique
import com.normation.rudder.repository.FullActiveTechniqueCategory
import scala.collection.SortedMap
import org.joda.time.DateTime
import com.normation.cfclerk.services.TechniqueRepository
import scala.collection.SortedSet
import com.normation.rudder.repository.CategoryWithActiveTechniques
import java.io.InputStream
import com.normation.cfclerk.services.TechniquesInfo
import com.normation.rudder.web.rest.directive.DirectiveAPIService2
import com.normation.rudder.repository.WoDirectiveRepository

object RestBaseObjects {
val techniqueId = TechniqueId(
TechniqueName("techniqueName")
, TechniqueVersion("1.0")
)

/* create representation of meta techniques */
def makePredefinedSectionSpec(name: String, providedValues: (String, Seq[String])) =
PredefinedValuesVariableSpec(
reportKeysVariableName(name)
, "description"
, providedValues
)
def makeComponentSectionSpec(name:String) =
SectionSpec(
name
, true
, true
, Some(reportKeysVariableName(name))
, HighDisplayPriority
, ""
, Seq(makePredefinedSectionSpec(name, ("variable_"+name, Seq("variable_"+name+"one", "variable_"+name+"two"))))
)

def makeRootSectionSpec() =
SectionSpec(
"root section"
, false
, false
, None
, HighDisplayPriority
, ""
, Seq(
makeComponentSectionSpec("component1")
, makeComponentSectionSpec("component2")
)
)

def makeMetaTechnique(id: TechniqueId) =
Technique(
id
, "meta" + id
, ""
, Seq()
, Seq()
, TrackerVariableSpec(None)
, makeRootSectionSpec
, None
, Set()
, None
, false
, ""
, false
, true
)

val technique = makeMetaTechnique(techniqueId)

val fullActiveTechnique =
FullActiveTechnique(
ActiveTechniqueId("activeTechId")
, techniqueId.name
, SortedMap((techniqueId.version, new DateTime()))
, SortedMap((techniqueId.version, technique))
, Nil
, true
, false
)

// create the ActiveTechniqueCategory
val fullActiveTechniqueCategory =
FullActiveTechniqueCategory(
ActiveTechniqueCategoryId("id")
, "name"
, "description"
, Nil
, List(fullActiveTechnique)
, false
)
}

object MemoryTechRepository extends TechniqueRepository {

import RestBaseObjects._

var techniques = Map((techniqueId,technique))
def getMetadataContent[T](techniqueId: TechniqueId)(useIt: Option[InputStream] => T): T = ???
def getTemplateContent[T](templateName: Cf3PromisesFileTemplateId)(useIt: Option[InputStream] => T): T = ???
def getReportingDetailsContent[T](techniqueId: TechniqueId)(useIt: Option[InputStream] => T): T = ???
def getTechniquesInfo(): TechniquesInfo = ???
def getAll(): Map[TechniqueId, Technique] = techniques
def get(techniqueId: TechniqueId): Option[Technique] = techniques.get(techniqueId)
def getLastTechniqueByName(techniqueName: TechniqueName): Option[Technique] = ???
def getByIds(techniqueIds: Seq[TechniqueId]): Seq[Technique] = ???
def getTechniqueVersions(name:TechniqueName) : SortedSet[TechniqueVersion] = ???
def getByName(name:TechniqueName) : Map[TechniqueVersion, Technique] = ???
def getTechniqueLibrary: RootTechniqueCategory = ???
def getTechniqueCategory(id: TechniqueCategoryId): Box[TechniqueCategory] = ???
def getParentTechniqueCategory_forTechnique(id: TechniqueId): Box[TechniqueCategory] = ???

}

object MemoryDirectiveRepository extends RoDirectiveRepository with WoDirectiveRepository {

import RestBaseObjects._

var rootCategory =
FullActiveTechniqueCategory(
ActiveTechniqueCategoryId("root")
, "root"
, ""
, fullActiveTechniqueCategory :: Nil
, Nil
, false
)
def getFullDirectiveLibrary() : Box[FullActiveTechniqueCategory] = Full(rootCategory)
def getDirective(directiveId:DirectiveId) : Box[Directive] = {
getActiveTechniqueAndDirective(directiveId).map(_._2)
}
def getDirectiveWithContext(directiveId:DirectiveId) : Box[(Technique, ActiveTechnique, Directive)] = {
for {
(activeTech,directive) <- getActiveTechniqueAndDirective(directiveId)
activeTechniqueId = TechniqueId(activeTech.techniqueName, directive.techniqueVersion)
technique <- Box(MemoryTechRepository.get(activeTechniqueId)) ?~! "No Technique with ID=%s found in reference library.".format(activeTechniqueId)
} yield {
(technique, activeTech, directive)
}
}
def getActiveTechniqueAndDirective(id:DirectiveId) : Box[(ActiveTechnique, Directive)] = {
for {
(activeTech,directive) <- Box(rootCategory.allDirectives.get(id)) ?~! s"Directive ${id.value} not found"
} yield {
(activeTech.toActiveTechnique,directive)
}
}
def getDirectives(activeTechniqueId:ActiveTechniqueId, includeSystem:Boolean = false) : Box[Seq[Directive]] = {
rootCategory.allDirectivesByActiveTechniques.get(activeTechniqueId)
}
def getActiveTechniqueByCategory(includeSystem:Boolean = false) : Box[SortedMap[List[ActiveTechniqueCategoryId], CategoryWithActiveTechniques]] = ???
def getActiveTechnique(id:ActiveTechniqueId) : Box[Option[ActiveTechnique]] = {
Full(rootCategory.allActiveTechniques.get(id).map(_.toActiveTechnique()))
}
def getActiveTechnique(techniqueName: TechniqueName) : Box[Option[ActiveTechnique]] = {
Full(rootCategory.allActiveTechniques.find(_._2.techniqueName == techniqueName).map(_._2.toActiveTechnique()))
}
def activeTechniqueBreadCrump(id:ActiveTechniqueId) : Box[List[ActiveTechniqueCategory]] = ???
def getActiveTechniqueLibrary : Box[ActiveTechniqueCategory] = ???
def getAllActiveTechniqueCategories(includeSystem:Boolean = false) : Box[Seq[ActiveTechniqueCategory]] = ???
def getActiveTechniqueCategory(id:ActiveTechniqueCategoryId) : Box[ActiveTechniqueCategory] = ???
def getParentActiveTechniqueCategory(id:ActiveTechniqueCategoryId) : Box[ActiveTechniqueCategory] = ???
def getParentsForActiveTechniqueCategory(id:ActiveTechniqueCategoryId) : Box[List[ActiveTechniqueCategory]] = ???
def getParentsForActiveTechnique(id:ActiveTechniqueId) : Box[ActiveTechniqueCategory] = ???
def containsDirective(id: ActiveTechniqueCategoryId) : Boolean = ???

def saveDirective(inActiveTechniqueId:ActiveTechniqueId, directive:Directive, modId: ModificationId, actor:EventActor, reason:Option[String]) : Box[Option[DirectiveSaveDiff]] = {

def saveInCategory(current : FullActiveTechniqueCategory) = {
current.activeTechniques.find { _.id == inActiveTechniqueId } match {
case Some(toSaveIn) => saveInActiveTechniqueId(toSaveIn)
}
}
def saveInActiveTechniqueId(current : FullActiveTechnique) {
val newDirectives = current.directives.filterNot { _.id == directive.id } :+ directive
Some(current.copy(directives = newDirectives))
}
}

def saveSystemDirective(inActiveTechniqueId:ActiveTechniqueId,directive:Directive, modId: ModificationId, actor:EventActor, reason:Option[String]) : Box[Option[DirectiveSaveDiff]]

def delete(id:DirectiveId, modId: ModificationId, actor:EventActor, reason:Option[String]) : Box[DeleteDirectiveDiff]

def addTechniqueInUserLibrary(
categoryId : ActiveTechniqueCategoryId
, techniqueName: TechniqueName
, versions : Seq[TechniqueVersion]
, modId : ModificationId
, actor : EventActor
, reason : Option[String]
) : Box[ActiveTechnique]

def move(id:ActiveTechniqueId, newCategoryId:ActiveTechniqueCategoryId, modId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueId]

def changeStatus(id:ActiveTechniqueId, status:Boolean, modId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueId]

def setAcceptationDatetimes(id:ActiveTechniqueId, datetimes: Map[TechniqueVersion,DateTime], modId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueId]

def delete(id:ActiveTechniqueId, modId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueId]

def addActiveTechniqueCategory(
that : ActiveTechniqueCategory
, into : ActiveTechniqueCategoryId //parent category
, modificationId: ModificationId
, actor: EventActor
, reason: Option[String]
) : Box[ActiveTechniqueCategory]

def saveActiveTechniqueCategory(category:ActiveTechniqueCategory, modificationId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueCategory]

def delete(id:ActiveTechniqueCategoryId, modificationId: ModificationId, actor: EventActor, reason: Option[String], checkEmpty:Boolean = true) : Box[ActiveTechniqueCategoryId]

def move(categoryId:ActiveTechniqueCategoryId, intoParent:ActiveTechniqueCategoryId, modificationId: ModificationId, actor: EventActor, reason: Option[String]) : Box[ActiveTechniqueCategoryId]

}

/*
* This file provides all the necessary plumbing to allow test REST API.
Expand All @@ -81,10 +299,48 @@ object RestTestSetUp {
def registerCallback(callback:TechniquesLibraryUpdateNotification) : Unit = {}
}, uuidGen)

val restExtractorService =
RestExtractorService (
null //roRuleRepository
, null //roDirectiveRepository
, null //roNodeGroupRepository
, null //techniqueRepository
, null //queryParser
, null //userPropertyService
, null //workflowService
)

val restDataSerializer = RestDataSerializerImpl(
null //techniqueRepository
, null //diffService
, () => Full(false)
)

val directiveAPIService =
new DirectiveAPIService2 (
MemoryDirectiveRepository
, writeDirective
, uuidGen
, asyncDeploymentAgent
, changeRequestService
, workflowService
, restExtractorService
, workflowEnabled
, editorService
, restDataSerializer
, MemoryTechRepository
)
/*
val dataSourceApiService = new DataSourceApiService(datasourceRepo, restDataSerializer, restExtractorService)
val dataSourceApi9 = new DataSourceApi9(restExtractorService, dataSourceApiService, uuidGen)
*/
val api = APIDispatcher( Map((ApiVersion(42,false)-> List())), restExtractorService)

val liftRules = {
val l = new LiftRules()
l.statelessDispatch.append(RestStatus)
l.statelessDispatch.append(reloadTechniques)
l.statelessDispatch.append(api)
//TODO: add all other rest classes here
l
}
Expand Down Expand Up @@ -121,16 +377,46 @@ object RestTestSetUp {
}
}


def GET(path: String) = {
private[this] def mockRequest (path : String, method : String) = {
val mockReq = new MockHttpServletRequest("http://localhost:8080")
mockReq.method = "GET"
mockReq.method = method
mockReq.path = path
mockReq
}
def GET(path: String) = mockRequest(path,"GET")
def DELETE(path: String) = mockRequest(path,"DELETE")

private[this] def mockJsonRequest (path : String, method : String, data : JValue) = {
val mockReq = mockRequest(path,method)
mockReq.body = data
mockReq
}

private[this] def mockDataRequest (path : String, method : String, data : Map[String,String]) = {
val mockReq = mockRequest(path,method)
mockReq.body = data.map{case (key,value) => s"$key=$value"}.mkString("\n")
mockReq
}

def jsonPUT(path: String, json : JValue) = {
mockJsonRequest(path,"PUT", json)
}

def jsonPOST(path: String, json : JValue) = {
mockJsonRequest(path,"POST", json)
}

def testGET[T](path: String)(tests: Req => MatchResult[T]) = {
doReq(GET(path))(tests)
}
}
def testDELETE[T](path: String)(tests: Req => MatchResult[T]) = {
doReq(DELETE(path))(tests)
}

def testPUT[T](path: String, json : JValue)(tests: Req => MatchResult[T]) = {
doReq(jsonPUT(path, json))(tests)
}
def testPOST[T](path: String, json : JValue)(tests: Req => MatchResult[T]) = {
doReq(jsonPOST(path, json))(tests)
}
}

0 comments on commit c571ea7

Please sign in to comment.