Skip to content

Commit

Permalink
Merge pull request #995 from fanf/ust_7424/add_cfengine_classes_for_e…
Browse files Browse the repository at this point in the history
…ach_group_of_a_node

Fixes #7424: Add cfengine classes for each group of a node
  • Loading branch information
ncharles committed Dec 11, 2015
2 parents 99e4158 + 05e3b12 commit a490667
Show file tree
Hide file tree
Showing 59 changed files with 574 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,17 @@ class SystemVariableSpecServiceImpl extends SystemVariableSpecService {
, multivalued = false
, isUniqueVariable = true
)
// we have 2 systems variables for groups:
// - one to define all the classes related to groups
// - one to define the variable holding all groups
, SystemVariableSpec("RUDDER_NODE_GROUPS_CLASSES" , "The classes definition for groups, both group_UUID and group_normalized(NAME), in a formatted string"
, multivalued = false
, isUniqueVariable = true
)
, SystemVariableSpec("RUDDER_NODE_GROUPS_VARS" , "The array of group_UUID => group_NAME for the node, in a formatted string"
, multivalued = false
, isUniqueVariable = true
)
)

private[this] val varSpecsMap = varSpecs.map(x => (x.name -> x)).toMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* 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:
Expand All @@ -22,12 +22,12 @@
* 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/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* 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:
Expand All @@ -22,12 +22,12 @@
* 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/>.
Expand Down Expand Up @@ -387,6 +387,26 @@ object RuleTarget extends Loggable {
}
}


/**
* Transform a rule target string "id" to
* a cfengine class compatible string,
* prefixed by "group_"
*/
def toCFEngineClassName(target: String) = {
//normalisation process:
// 1) to asccii
// 2) cfengine normalisation, replacing all non [alphanum-]
/// char by _

// from http://stackoverflow.com/a/2413228/436331 and the precision
// in http://stackoverflow.com/a/5697575/436331
def toAscii(s: String) = java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD).replaceAll("""[\p{Mn}\p{Me}]+""", "")

"group_" + toAscii(target).toLowerCase.replaceAll("""[^\p{Alnum}-]""", "_")

}

}

/** common information on a target */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* 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:
Expand All @@ -22,12 +22,12 @@
* 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/>.
Expand Down Expand Up @@ -179,6 +179,29 @@ final case class FullNodeGroupCategory(

RuleTarget.getNodeIds(targets, allNodes, groups)
}

/**
* Given a nodeId, get all the groups where it belongs to.
*/
def getTarget(node: NodeInfo): Map[RuleTarget, FullRuleTargetInfo] = {
allTargets.filter { case(t, info) => info.target match {
case FullGroupTarget(target, group) => group.serverList.contains(node.id)
case FullCompositeRuleTarget(t) =>
//here, on choice but to calculate the list of nodes and see if it is in the result
//here, we don't need all node info, just the current node
//It's because we only do set analysis on node info, not things like "find all
//the node with that policy server" in target.
getNodeIds(Set(t), Map(node.id -> node)).contains(node.id)
case FullOtherTarget(t) => t match {
case AllTarget => true
case AllTargetExceptPolicyServers => !node.isPolicyServer
case AllServersWithRole => node.serverRoles.nonEmpty
case AllNodesWithoutRole => node.serverRoles.isEmpty
case PolicyServerTarget(id) => id == node.id
}
} }
}

}

trait RoNodeGroupRepository {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* 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:
Expand All @@ -22,12 +22,12 @@
* 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/>.
Expand Down Expand Up @@ -140,7 +140,7 @@ trait PromiseGenerationService extends Loggable {
_ = logger.debug(s"All relevant information fetched in ${timeFetchAll}ms, start names historization.")

nodeContextsTime = System.currentTimeMillis
nodeContexts <- getNodeContexts(activeNodeIds, allNodeInfos, allLicenses, allParameters, globalAgentRun, globalComplianceMode) ?~! "Could not get node interpolation context"
nodeContexts <- getNodeContexts(activeNodeIds, allNodeInfos, groupLib, allLicenses, allParameters, globalAgentRun, globalComplianceMode) ?~! "Could not get node interpolation context"
timeNodeContexts = (System.currentTimeMillis - nodeContextsTime)
_ = logger.debug(s"Node contexts built in ${timeNodeContexts}ms, start to build new node configurations.")

Expand Down Expand Up @@ -261,6 +261,7 @@ trait PromiseGenerationService extends Loggable {
def getNodeContexts(
nodeIds : Set[NodeId]
, allNodeInfos : Map[NodeId, NodeInfo]
, allGroups : FullNodeGroupCategory
, allLicenses : Map[NodeId, NovaLicense]
, globalParameters : Seq[GlobalParameter]
, globalAgentRun : AgentRunInterval
Expand Down Expand Up @@ -455,6 +456,7 @@ trait PromiseGeneration_performeIO extends PromiseGenerationService {
override def getNodeContexts(
nodeIds : Set[NodeId]
, allNodeInfos : Map[NodeId, NodeInfo]
, allGroups : FullNodeGroupCategory
, allLicenses : Map[NodeId, NovaLicense]
, globalParameters : Seq[GlobalParameter]
, globalAgentRun : AgentRunInterval
Expand Down Expand Up @@ -492,7 +494,7 @@ trait PromiseGeneration_performeIO extends PromiseGenerationService {
nodeInfo <- Box(allNodeInfos.get(nodeId)) ?~! s"Node with ID ${nodeId.value} was not found"
policyServer <- Box(allNodeInfos.get(nodeInfo.policyServerId)) ?~! s"Node with ID ${nodeId.value} was not found"

nodeContext <- systemVarService.getSystemVariables(nodeInfo, allNodeInfos, allLicenses, globalSystemVariables, globalAgentRun, globalComplianceMode : ComplianceMode)
nodeContext <- systemVarService.getSystemVariables(nodeInfo, allNodeInfos, allGroups, allLicenses, globalSystemVariables, globalAgentRun, globalComplianceMode : ComplianceMode)
} yield {
(nodeId, InterpolationContext(
nodeInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* 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:
Expand All @@ -22,12 +22,12 @@
* 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/>.
Expand Down Expand Up @@ -64,13 +64,17 @@ import com.normation.rudder.reports.SyslogProtocol
import com.normation.rudder.domain.licenses.NovaLicense
import com.normation.rudder.reports.AgentRunIntervalService
import com.normation.rudder.reports.ComplianceModeService
import com.normation.rudder.repository.FullNodeGroupCategory
import com.normation.rudder.domain.policies.GroupTarget
import com.normation.rudder.domain.policies.RuleTarget

trait SystemVariableService {
def getGlobalSystemVariables(globalAgentRun: AgentRunInterval): Box[Map[String, Variable]]

def getSystemVariables(
nodeInfo : NodeInfo
, allNodeInfos : Map[NodeId, NodeInfo]
, allGroups : FullNodeGroupCategory
, allLicences : Map[NodeId, NovaLicense]
, globalSystemVariables : Map[String, Variable]
, globalAgentRun : AgentRunInterval
Expand Down Expand Up @@ -191,6 +195,7 @@ class SystemVariableServiceImpl(
def getSystemVariables(
nodeInfo : NodeInfo
, allNodeInfos : Map[NodeId, NodeInfo]
, allGroups : FullNodeGroupCategory
, allLicenses : Map[NodeId, NovaLicense]
, globalSystemVariables : Map[String, Variable]
, globalAgentRun : AgentRunInterval
Expand Down Expand Up @@ -356,12 +361,58 @@ class SystemVariableServiceImpl(
* Cf3PromisesFileWriterServiceImpl#prepareRulesForAgents
*/
val varNodeConfigVersion = systemVariableSpecService.get("RUDDER_NODE_CONFIG_ID").toVariable(Seq("DUMMY NODE CONFIG VERSION"))


/*
* RUDDER_NODE_GROUPS_VAR is an array of group_uuid -> group_name for the node
* RUDDER_NODE_GROUPS_CLASSE are pairs of group_UUID, group_NORMALIZED_NAME,
* for ex if node belongs to group:
* (id: 64f85ba8-39c7-418a-a099-24c2c2909dfd ; name: "Serveurs pré-prod")
* we will have the following classes:
* - group_64f85ba8_39c7_418a_a099_24c2c2909dfd
* - group_serveurs_pre_prod
* and vars:
* - by_uuid["64f85ba8-39c7-418a-a099-24c2c2909dfd"] string => "Serveurs pré-prod"
* with a meta: { "inventory", "attribute_name=rudder_groups" }
*/
//build the list of nodeId -> names, taking care of special nodeIds for special target
val nodeGroups = allGroups.getTarget(nodeInfo).map { case(target, info) =>
val id = info.target.target match {
case GroupTarget(id) => id.value
case t => t.target
}
(id, info.name)
}
val nodeMaxString = if(nodeGroups.isEmpty) 0 else nodeGroups.flatMap { case (a,b) => a.size :: b.size :: Nil }.max
val stringNodeGroupsVars = if(nodeGroups.isEmpty) {
""
} else {
nodeGroups.map { case (id, name) =>
s"""by_uuid["${id}"] ${" "*(nodeMaxString-id.size)} string => "${name}",\n""" +
s""" ${" "*(nodeMaxString) } meta => { "inventory", "attribute_name=rudder_groups" };"""
}.mkString("\n")
}
val stringNodeGroupsClasses = if(nodeGroups.isEmpty) {
""
} else {
nodeGroups.flatMap { case (id, name) =>
( s""""${RuleTarget.toCFEngineClassName(id )}" ${" "*(nodeMaxString- id.size)} expression => "any"; """
:: s""""${RuleTarget.toCFEngineClassName(name)}" ${" "*(nodeMaxString-name.size)} expression => "any"; """
:: Nil
)
}.mkString("\n")
}
val varNodeGroups = systemVariableSpecService.get("RUDDER_NODE_GROUPS_VARS").toVariable(Seq(stringNodeGroupsVars))
val varNodeGroupsClasses = systemVariableSpecService.get("RUDDER_NODE_GROUPS_CLASSES").toVariable(Seq(stringNodeGroupsClasses))

val baseVariables = {
Seq(
varNodeRole
, varAllowedNetworks
, varRudderServerRole
, varNodeConfigVersion
, varNodeGroups
, varNodeGroupsClasses
) map (x => (x.spec.name, x))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ package com.normation.rudder.services.policies.write

import java.io.File
import java.io.IOException
import com.normation.cfclerk.domain.PARAMETER_VARIABLE
import com.normation.cfclerk.domain.Technique
import com.normation.cfclerk.domain.TechniqueFile
import com.normation.cfclerk.domain.TechniqueId
Expand Down

0 comments on commit a490667

Please sign in to comment.