forked from Normation/rudder-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
...e-out-relay/src/main/scala/com/normation/plugins/scaleoutrelay/ScaleOutRelayService.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
package com.normation.plugins.scaleoutrelay | ||
|
||
import bootstrap.liftweb.RudderConfig | ||
import com.normation.cfclerk.domain.TechniqueVersion | ||
import com.normation.errors.IOResult | ||
import com.normation.errors._ | ||
import com.normation.eventlog.EventActor | ||
import com.normation.eventlog.ModificationId | ||
import com.normation.inventory.domain.NodeId | ||
import com.normation.rudder.domain.nodes.Node | ||
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.NodeInfo | ||
import com.normation.rudder.domain.policies._ | ||
import com.normation.rudder.domain.queries._ | ||
import com.normation.rudder.rule.category.RuleCategoryId | ||
import net.liftweb.common.EmptyBox | ||
import net.liftweb.common.Failure | ||
import net.liftweb.common.Full | ||
import zio.ZIO | ||
|
||
|
||
object ScaleOutRelayService { | ||
val SYSTEM_GROUPS = "SystemGroups" | ||
val DISTRIBUTE_POLICY = "distributePolicy" | ||
val COMMON = "common" | ||
|
||
private val nodeInfosService = RudderConfig.nodeInfoService | ||
private val woLDAPNodeGroupRepository = RudderConfig.woNodeGroupRepository | ||
private val woLDAPNodeRepository = RudderConfig.woNodeRepository | ||
private val woDirectiveRepository = RudderConfig.woDirectiveRepository | ||
private val woRuleRepository = RudderConfig.woRuleRepository | ||
private val uuidGen = RudderConfig.stringUuidGenerator | ||
private val policyServerManagementService = RudderConfig.policyServerManagementService | ||
private val removeNodeService = RudderConfig.removeNodeService | ||
|
||
def promoteNodeToRelay(uuid: NodeId, actor: EventActor, reason:Option[String]): ZIO[Any, RudderError, NodeInfo] = { | ||
val modId = ModificationId(uuidGen.newUuid) | ||
for { | ||
nodeInfos <- getNodeToPromote(uuid) | ||
updatedNode = createNodeToPolicyServerType(nodeInfos) | ||
_ <- removeNodeService.removeNode(nodeInfos.node.id, modId, actor).toIO | ||
newRelay <- createRelayFromNode(updatedNode, modId, actor, reason) | ||
} yield { | ||
newRelay | ||
} | ||
} | ||
|
||
private[scaleoutrelay] def createRelayFromNode(nodeInf: NodeInfo, modId: ModificationId, actor: EventActor, reason:Option[String])= { | ||
for { | ||
commonDirective <- createCommonDirective(nodeInf).toIO | ||
|
||
directDistribPolicy = createDirectiveDistributePolicy(nodeInf.node.id) | ||
ruleTarget = createPolicyServer(nodeInf.node.id) | ||
nodeGroup = createNodeGroup(nodeInf.node.id) | ||
ruleDistribPolicy = createRuleDistributePolicy(nodeInf.node.id) | ||
ruleSetup = createRuleSetup(nodeInf.node.id) | ||
|
||
categoryId = NodeGroupCategoryId(SYSTEM_GROUPS) | ||
activeTechniqueId = ActiveTechniqueId(DISTRIBUTE_POLICY) | ||
activeTechniqueIdCommon = ActiveTechniqueId(COMMON) | ||
|
||
_ <- woLDAPNodeRepository.createNode(nodeInf.node, modId, actor, reason) | ||
_ <- woLDAPNodeGroupRepository.createPolicyServerTarget(ruleTarget, modId, actor, reason) | ||
_ <- woLDAPNodeGroupRepository.create(nodeGroup, categoryId, modId, actor, reason) | ||
_ <- woDirectiveRepository.saveSystemDirective(activeTechniqueId, directDistribPolicy, modId, actor, reason) | ||
_ <- woDirectiveRepository.saveSystemDirective(activeTechniqueIdCommon, commonDirective, modId, actor, reason) | ||
_ <- woRuleRepository.create(ruleSetup, modId, actor, reason) | ||
_ <- woRuleRepository.create(ruleDistribPolicy, modId, actor, reason) | ||
} yield { | ||
nodeInf | ||
} | ||
} | ||
|
||
private[scaleoutrelay] def getNodeToPromote(uuid: NodeId): IOResult[NodeInfo] = { | ||
nodeInfosService.getNodeInfo(uuid) match { | ||
case Full(nodeOpt) => nodeOpt.notOptional(s"Node with UUID ${uuid.value} is missing and can not be upgraded to relay") | ||
case eb: EmptyBox => eb.toIO | ||
} | ||
} | ||
|
||
private[scaleoutrelay] def createNodeToPolicyServerType(nodeInf: NodeInfo) = { | ||
val newNode = nodeInf.node.copy(id = nodeInf.node.id, name = nodeInf.node.id.value, isSystem = true, isPolicyServer = true) | ||
nodeInf.copy(node = newNode) | ||
} | ||
|
||
private[scaleoutrelay] def createPolicyServer(uuid: NodeId) = { | ||
PolicyServerTarget(uuid) | ||
} | ||
|
||
private[scaleoutrelay] def createNodeGroup(uuid: NodeId) = { | ||
val objectType = ObjectCriterion("node", Seq(Criterion("policyServerId", StringComparator, None),Criterion("agentName", AgentComparator, None))) | ||
val attribute = Criterion("agentName", StringComparator) | ||
val comparator = Equals | ||
val value = "cfengine" | ||
|
||
val attribute2 = Criterion("policyServerId", StringComparator) | ||
val comparator2 = Equals | ||
val value2 = uuid.value | ||
NodeGroup( | ||
NodeGroupId(s"hasPolicyServer-${uuid.value}") | ||
, s"All classic Nodes managed by ${uuid.value} policy server" | ||
, s"All classic Nodes known by Rudder directly connected to the ${uuid.value} server. This group exists only as internal purpose and should not be used to configure Nodes." | ||
, Some( | ||
Query( | ||
NodeAndPolicyServerReturnType | ||
, And | ||
, List(CriterionLine(objectType, attribute, comparator, value) | ||
, CriterionLine(objectType, attribute2, comparator2, value2)) | ||
) | ||
) | ||
, true | ||
, Set() | ||
, true | ||
, true | ||
) | ||
} | ||
|
||
private[scaleoutrelay] def createDirectiveDistributePolicy(uuid: NodeId) = { | ||
Directive( | ||
DirectiveId(s"${uuid.value}-distributePolicy") | ||
, TechniqueVersion("1.0") | ||
, Map() | ||
, s"${uuid.value}-Distribute Policy" | ||
, "Distribute policy - Technical" | ||
, None | ||
, "" | ||
, 0 | ||
, true | ||
, true | ||
, Tags(Set.empty) | ||
) | ||
} | ||
|
||
private[scaleoutrelay] def createCommonDirective(nodeInf: NodeInfo) = { | ||
for { | ||
authorizedNetworks <- policyServerManagementService.getAuthorizedNetworks(nodeInf.node.id) | ||
} yield { | ||
val parameters = | ||
Map ( | ||
"OWNER" -> Seq("${rudder.node.admin}") | ||
, "UUID" -> Seq("${rudder.node.id}") | ||
, "POLICYSERVER" -> Seq(nodeInf.hostname) | ||
, "POLICYSERVER_ID" -> Seq(nodeInf.policyServerId.value) | ||
, "POLICYSERVER_ADMIN" -> Seq("root") | ||
, "ALLOWEDNETWORK" -> authorizedNetworks | ||
) | ||
Directive( | ||
DirectiveId(s"common-${nodeInf.node.id.value}") | ||
, TechniqueVersion("1.0") | ||
, parameters | ||
, s"Common-${nodeInf.node.id.value}" | ||
, "Common - Technical" | ||
, None | ||
, "" | ||
, 0 | ||
, true | ||
, true | ||
, Tags(Set.empty) | ||
) | ||
} | ||
} | ||
|
||
private[scaleoutrelay] def createRuleDistributePolicy(uuid: NodeId) = { | ||
Rule( | ||
RuleId(s"${uuid.value}-DP") | ||
, s"${uuid.value}-distributePolicy" | ||
, RuleCategoryId("rootRuleCategory") | ||
, Set(PolicyServerTarget(uuid)) | ||
, Set(DirectiveId(s"${uuid.value}-distributePolicy")) | ||
, "Distribute Policy - Technical" | ||
, "This rule allows to distribute policies to nodes" | ||
, true | ||
, true | ||
) | ||
} | ||
|
||
private[scaleoutrelay] def createRuleSetup(uuid: NodeId) = { | ||
Rule( | ||
RuleId(s"hasPolicyServer-${uuid.value}") | ||
, s"Rudder system policy: basic setup (common)-${uuid.value}" | ||
, RuleCategoryId("rootRuleCategory") | ||
, Set(GroupTarget(NodeGroupId(s"hasPolicyServer-${uuid.value}"))) | ||
, Set(DirectiveId(s"common-${uuid.value}")) | ||
, "Common - Technical" | ||
, "This is the basic system rule which all nodes must have." | ||
, true | ||
, true | ||
) | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
...e-out-relay/src/main/scala/com/normation/plugins/scaleoutrelay/api/ScaleOutRelayApi.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package com.normation.plugins.scaleoutrelay.api | ||
|
||
|
||
import com.normation.box._ | ||
import com.normation.eventlog.EventActor | ||
import com.normation.inventory.domain.NodeId | ||
import com.normation.plugins.scaleoutrelay.ScaleOutRelayService | ||
import com.normation.rudder.api.HttpAction.POST | ||
import com.normation.rudder.rest.EndpointSchema.syntax._ | ||
import com.normation.rudder.rest._ | ||
import com.normation.rudder.rest.lift.DefaultParams | ||
import com.normation.rudder.rest.lift.LiftApiModule | ||
import com.normation.rudder.rest.lift.LiftApiModuleProvider | ||
import net.liftweb.common.Box | ||
import net.liftweb.common.EmptyBox | ||
import net.liftweb.common.Full | ||
import net.liftweb.http.LiftResponse | ||
import net.liftweb.http.Req | ||
import net.liftweb.json.JsonAST.JValue | ||
import net.liftweb.json.NoTypeHints | ||
import sourcecode.Line | ||
import com.normation.eventlog.EventActor | ||
import com.normation.inventory.domain.NodeId | ||
import com.normation.plugins.scaleoutrelay.ScaleOutRelayService | ||
import com.normation.rudder.api.HttpAction.POST | ||
import com.normation.rudder.repository.json.DataExtractor.CompleteJson | ||
import com.normation.rudder.rest.EndpointSchema.syntax._ | ||
import com.normation.rudder.rest.RestUtils.toJsonError | ||
import com.normation.rudder.rest.RestUtils.toJsonResponse | ||
import com.normation.rudder.rest._ | ||
import com.normation.rudder.rest.lift.DefaultParams | ||
import com.normation.rudder.rest.lift.LiftApiModule | ||
import com.normation.rudder.rest.lift.LiftApiModuleProvider | ||
import net.liftweb.common.Box | ||
import net.liftweb.common.Full | ||
import net.liftweb.http.LiftResponse | ||
import net.liftweb.http.Req | ||
import net.liftweb.json.JsonAST.JString | ||
import net.liftweb.json.JsonAST.JValue | ||
import net.liftweb.json.JsonDSL._ | ||
import net.liftweb.json.NoTypeHints | ||
import sourcecode.Line | ||
|
||
|
||
|
||
sealed trait ScaleOutRelayApi extends EndpointSchema with GeneralApi with SortIndex | ||
object ScaleOutRelayApi extends ApiModuleProvider[ScaleOutRelayApi] { | ||
|
||
final case object PromoteNodeToRelay extends ScaleOutRelayApi with OneParam with StartsAtVersion10 { | ||
val z = implicitly[Line].value | ||
val description = "Promote a node to relay" | ||
val (action, path) = POST / "scaleoutrelay" / "promote" / "{nodeId}" | ||
} | ||
|
||
override def endpoints: List[ScaleOutRelayApi] = ca.mrvisser.sealerate.values[ScaleOutRelayApi].toList.sortBy( _.z ) | ||
} | ||
|
||
class ScaleOutRelayApiImpl( | ||
restExtractorService: RestExtractorService | ||
) extends LiftApiModuleProvider[ScaleOutRelayApi] { | ||
|
||
api => | ||
|
||
implicit val formats = net.liftweb.json.Serialization.formats((NoTypeHints)) | ||
override def schemas = ScaleOutRelayApi | ||
|
||
override def getLiftEndpoints(): List[LiftApiModule] = { | ||
ScaleOutRelayApi.endpoints.map { | ||
case ScaleOutRelayApi.PromoteNodeToRelay => PromoteNodeToRelay | ||
}.toList | ||
} | ||
|
||
def response(function: Box[JValue], req: Req, errorMessage: String, id: Option[String], dataName: String)(implicit action: String): LiftResponse = { | ||
RestUtils.response(restExtractorService, dataName, id)(function, req, errorMessage) | ||
} | ||
|
||
object PromoteNodeToRelay extends LiftApiModule { | ||
val schema = ScaleOutRelayApi.PromoteNodeToRelay | ||
val restExtractor = api.restExtractorService | ||
|
||
def process(version: ApiVersion, path: ApiPath, nodeId: String, req: Req, params: DefaultParams, authz: AuthzToken): LiftResponse = { | ||
val response = for { | ||
node <- ScaleOutRelayService.promoteNodeToRelay(NodeId(nodeId), EventActor("rudder"), Some(s"Promote node ${nodeId} to relay")).toBox | ||
} yield { | ||
node | ||
} | ||
|
||
response match { | ||
case Full(node) => | ||
toJsonResponse(None,node.id.value)("promoteToRelay",true) | ||
case eb: EmptyBox => | ||
val message = (eb ?~ (s"Error when trying to promote mode $nodeId")).msg | ||
println(eb) | ||
toJsonError(None, message)("promoteToRelay",true) | ||
} | ||
|
||
} | ||
} | ||
} |