From 2b461023e65d25a0dc05abd9f0b3414c88b4df66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Membr=C3=A9?= Date: Tue, 10 Nov 2015 18:40:21 +0100 Subject: [PATCH] Fixes #7375: Add an option in the web interface to completely disable reporting --- .../impl/SystemVariableSpecServiceImpl.scala | 12 +- .../domain/logger/ComplianceDebugLogger.scala | 11 +- .../rudder/reports/ComplianceMode.scala | 76 ++++++--- .../reports/ReportingConfiguration.scala | 11 +- .../services/policies/DeploymentService.scala | 33 +--- .../policies/SystemVariableService.scala | 13 +- .../services/reports/ExecutionBatch.scala | 34 +--- .../reports/ReportingServiceImpl.scala | 14 +- .../jdbc/ReportingServiceTest.scala | 34 ++-- .../services/reports/ExecutionBatchTest.scala | 43 +++-- .../scala/bootstrap/liftweb/AppConfig.scala | 31 +--- .../rudder/appconfig/ConfigService.scala | 23 +-- .../components/AgentScheduleEditForm.scala | 3 +- .../components/ComplianceModeEditForm.scala | 152 +++++++++++++----- .../components/ShowNodeDetailsFromNode.scala | 38 +++-- .../administration/PropertiesManagement.scala | 32 ++-- .../rudder/angular/complianceMode.js | 18 ++- .../components/ComponentComplianceMode.html | 20 ++- 18 files changed, 311 insertions(+), 287 deletions(-) diff --git a/rudder-core/src/main/scala/com/normation/cfclerk/services/impl/SystemVariableSpecServiceImpl.scala b/rudder-core/src/main/scala/com/normation/cfclerk/services/impl/SystemVariableSpecServiceImpl.scala index 3fc4af2683..e39ae82fdc 100644 --- a/rudder-core/src/main/scala/com/normation/cfclerk/services/impl/SystemVariableSpecServiceImpl.scala +++ b/rudder-core/src/main/scala/com/normation/cfclerk/services/impl/SystemVariableSpecServiceImpl.scala @@ -42,7 +42,7 @@ import com.normation.cfclerk.domain.IntegerVType import com.normation.cfclerk.domain.BooleanVType import com.normation.cfclerk.domain.BasicStringVType import com.normation.cfclerk.domain.RegexConstraint - +import com.normation.rudder.reports.ComplianceModeName class SystemVariableSpecServiceImpl extends SystemVariableSpecService { @@ -164,8 +164,14 @@ class SystemVariableSpecServiceImpl extends SystemVariableSpecService { , constraint = Constraint( typeName = BasicStringVType( regex = Some(RegexConstraint( - pattern = "(full-compliance|changes-only)" - , errorMsg = s"Forbiden value, only 'full-compliane' and 'changes-only' are authorized" + pattern = { + val allModes = ComplianceModeName.allModes.map(_.name).mkString("(", "|", ")") + allModes + } + , errorMsg = { + val allModes = ComplianceModeName.allModes.map(_.name).mkString("'", "' or '", "'") + s"Forbiden value, only ${allModes} are authorized" + } )) ) , default=Some("full-compliance") diff --git a/rudder-core/src/main/scala/com/normation/rudder/domain/logger/ComplianceDebugLogger.scala b/rudder-core/src/main/scala/com/normation/rudder/domain/logger/ComplianceDebugLogger.scala index 1baa4c618c..2642d572cb 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/domain/logger/ComplianceDebugLogger.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/domain/logger/ComplianceDebugLogger.scala @@ -49,7 +49,6 @@ import com.google.common.cache.CacheBuilder import java.util.concurrent.TimeUnit import com.google.common.cache.CacheLoader - /** * Log information about compliance. * This log is intended to be used in debug & trace level. @@ -59,7 +58,6 @@ import com.google.common.cache.CacheLoader object ComplianceDebugLogger extends Logger { override protected def _logger = LoggerFactory.getLogger("explain_compliance") - //we have one logger defined by node. //they automatically expires after some time. @@ -121,9 +119,9 @@ object ComplianceDebugLogger extends Logger { implicit class AgentRunConfigurationToLog(info: (NodeId, ComplianceMode, ResolvedAgentRunInterval)) { private[this] def log(c: ComplianceMode, r: ResolvedAgentRunInterval): String = { - val h = c match { - case FullCompliance => "" - case ChangesOnly(_) => s", hearbeat every ${r.heartbeatPeriod} run(s)" + val h = c.mode match { + case ChangesOnly => s", hearbeat every ${r.heartbeatPeriod} run(s)" + case _ => "" } s"run interval: ${r.interval.toStandardMinutes.getMinutes} min${h}" } @@ -135,7 +133,4 @@ object ComplianceDebugLogger extends Logger { } } - } - - diff --git a/rudder-core/src/main/scala/com/normation/rudder/reports/ComplianceMode.scala b/rudder-core/src/main/scala/com/normation/rudder/reports/ComplianceMode.scala index b276040bb5..4f527e1a0f 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/reports/ComplianceMode.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/reports/ComplianceMode.scala @@ -44,25 +44,54 @@ import net.liftweb.json._ * - error_only: only report for repaired and error reports. */ -sealed trait ComplianceMode { - def name: String +sealed trait ComplianceModeName { + val name : String } -final case object FullCompliance extends ComplianceMode { +case object FullCompliance extends ComplianceModeName { val name = "full-compliance" } -final case class ChangesOnly ( - heartbeatPeriod : Int -)extends ComplianceMode { - val name = ChangesOnly.name -} -object ChangesOnly { +case object ChangesOnly extends ComplianceModeName { val name = "changes-only" } +case object ReportDisabled extends ComplianceModeName { + val name = "reports-disabled" +} + +object ComplianceModeName { + val allModes : List[ComplianceModeName] = FullCompliance :: ChangesOnly :: ReportDisabled :: Nil + + def parse (value : String) : Box[ComplianceModeName] = { + allModes.find { _.name == value } match { + case None => + Failure(s"Unable to parse the compliance mode name '${value}'. was expecting ${allModes.map(_.name).mkString("'", "' or '", "'")}.") + case Some(mode) => + Full(mode) + } + } +} + +sealed trait ComplianceMode { + def mode: ComplianceModeName + def heartbeatPeriod : Int + val name = mode.name +} + +case class GlobalComplianceMode ( + mode : ComplianceModeName + , heartbeatPeriod : Int +) extends ComplianceMode + +case class NodeComplianceMode ( + mode : ComplianceModeName + , heartbeatPeriod : Int + , overrideGlobal : Boolean +) extends ComplianceMode + trait ComplianceModeService { - def getComplianceMode : Box[ComplianceMode] + def getGlobalComplianceMode : Box[GlobalComplianceMode] } class ComplianceModeServiceImpl ( @@ -70,21 +99,16 @@ class ComplianceModeServiceImpl ( , readHeartbeatFreq : () => Box[Int] ) extends ComplianceModeService { - def getComplianceMode : Box[ComplianceMode] = { - readComplianceMode() match { - case Full(FullCompliance.name) => Full(FullCompliance) - case Full(ChangesOnly.name) => - readHeartbeatFreq() match { - case Full(freq) => Full(ChangesOnly(freq)) - case eb : EmptyBox => - val fail = eb ?~! "Could not get heartbeat period" - fail - } - case Full(value) => - Failure(s"Unable to parse the compliance mode name. was expecting '${FullCompliance.name}' or '${ChangesOnly.name}' and got '${value}'") - case eb : EmptyBox => - val fail = eb ?~! "Could not get compliance mode name" - fail - } + def getGlobalComplianceMode : Box[GlobalComplianceMode] = { + for { + modeName <- readComplianceMode() + mode <- ComplianceModeName.parse(modeName) + heartbeat <- readHeartbeatFreq() + } yield { + GlobalComplianceMode( + mode + , heartbeat + ) + } } } \ No newline at end of file diff --git a/rudder-core/src/main/scala/com/normation/rudder/reports/ReportingConfiguration.scala b/rudder-core/src/main/scala/com/normation/rudder/reports/ReportingConfiguration.scala index 73a21456c7..530313ddb1 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/reports/ReportingConfiguration.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/reports/ReportingConfiguration.scala @@ -94,8 +94,14 @@ trait AgentRunIntervalService { } -class AgentRunIntervalServiceImpl( - nodeInfoService: NodeInfoService, readGlobalInterval: () => Box[Int], readGlobalStartHour: () => Box[Int], readGlobalStartMinute: () => Box[Int], readGlobalSplaytime: () => Box[Int], readGlobalHeartbeat: () => Box[Int]) extends AgentRunIntervalService { +class AgentRunIntervalServiceImpl ( + nodeInfoService: NodeInfoService + , readGlobalInterval: () => Box[Int] + , readGlobalStartHour: () => Box[Int] + , readGlobalStartMinute: () => Box[Int] + , readGlobalSplaytime: () => Box[Int] + , readGlobalHeartbeat: () => Box[Int] +) extends AgentRunIntervalService { override def getGlobalAgentRun(): Box[AgentRunInterval] = { for { @@ -151,4 +157,3 @@ object SyslogTCP extends SyslogProtocol { object SyslogUDP extends SyslogProtocol { val value = "UDP" } - diff --git a/rudder-core/src/main/scala/com/normation/rudder/services/policies/DeploymentService.scala b/rudder-core/src/main/scala/com/normation/rudder/services/policies/DeploymentService.scala index e034952e20..96be631d06 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/services/policies/DeploymentService.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/services/policies/DeploymentService.scala @@ -78,7 +78,7 @@ import com.normation.rudder.services.policies.write.Cf3PromisesFileWriterService import com.normation.rudder.services.policies.write.Cf3PromisesFileWriterService import com.normation.rudder.services.policies.write.Cf3PolicyDraft import com.normation.rudder.services.policies.write.Cf3PolicyDraftId - +import com.normation.rudder.reports.GlobalComplianceMode /** * The main service which deploy modified rules and @@ -124,7 +124,6 @@ trait PromiseGenerationService extends Loggable { timeFetchAll = (System.currentTimeMillis - initialTime) _ = logger.debug(s"All relevant information fetched in ${timeFetchAll}ms, start names historization.") - nodeContextsTime = System.currentTimeMillis nodeContexts <- getNodeContexts(activeNodeIds, allNodeInfos, allInventories, globalParameters, globalAgentRun, globalComplianceMode) ?~! "Could not get node interpolation context" timeNodeContexts = (System.currentTimeMillis - nodeContextsTime) @@ -140,7 +139,6 @@ trait PromiseGenerationService extends Loggable { _ = logger.debug(s"Historization of names done in ${timeHistorize}ms, start to build rule values.") ///// end ignoring - ruleValTime = System.currentTimeMillis //only keep actually applied rules in a format where parameter analysis on directive is done. ruleVals <- buildRuleVals(activeRuleIds, allRules, directiveLib, groupLib, allNodeInfos) ?~! "Cannot build Rule vals" @@ -152,7 +150,6 @@ trait PromiseGenerationService extends Loggable { timeBuildConfig = (System.currentTimeMillis - buildConfigTime) _ = logger.debug(s"Node's target configuration built in ${timeBuildConfig}, start to update rule values.") - sanitizeTime = System.currentTimeMillis _ <- forgetOtherNodeConfigurationState(config.map(_.nodeInfo.id).toSet) ?~! "Cannot clean the configuration cache" sanitizedNodeConfig <- sanitize(config) ?~! "Cannot set target configuration node" @@ -202,8 +199,6 @@ trait PromiseGenerationService extends Loggable { result } - - /** * Snapshot all information needed: * - node infos @@ -240,7 +235,6 @@ trait PromiseGenerationService extends Loggable { */ def findDependantRules() : Box[Seq[Rule]] - /** * Rule vals are just rules with a analysis of parameter * on directive done, so that we will be able to bind them @@ -257,8 +251,6 @@ trait PromiseGenerationService extends Loggable { , globalComplianceMode : ComplianceMode ): Box[Map[NodeId, InterpolationContext]] - - /** * From a list of ruleVal, find the list of all impacted nodes * with the actual Cf3PolicyDraftBean they will have. @@ -283,7 +275,6 @@ trait PromiseGenerationService extends Loggable { */ def forgetOtherNodeConfigurationState(keep: Set[NodeId]) : Box[Set[NodeId]] - /** * Get the actual cached values for NodeConfiguration */ @@ -311,7 +302,6 @@ trait PromiseGenerationService extends Loggable { */ def writeNodeConfigurations(rootNodeId: NodeId, allNodeConfig: Map[NodeId, NodeConfiguration], versions: Map[NodeId, NodeConfigId], cache: Map[NodeId, NodeConfigurationCache]) : Box[Set[NodeConfiguration]] - /** * Set the expected reports for the rule * Caution : we can't handle deletion with this @@ -348,7 +338,6 @@ trait PromiseGenerationService extends Loggable { , globalStartMinute: Int ) : Box[Unit] - protected def computeNodeConfigIdFromCache(config: NodeConfigurationCache): NodeConfigId = { NodeConfigId(config.hashCode.toString) } @@ -426,7 +415,7 @@ trait PromiseGeneration_performeIO extends PromiseGenerationService { override def getGroupLibrary(): Box[FullNodeGroupCategory] = roNodeGroupRepository.getFullGroupLibrary() override def getAllGlobalParameters: Box[Seq[GlobalParameter]] = parameterService.getAllGlobalParameters() override def getAllInventories(): Box[Map[NodeId, NodeInventory]] = roInventoryRepository.getAllNodeInventories(AcceptedInventory) - override def getGlobalComplianceMode(): Box[ComplianceMode] = complianceModeService.getComplianceMode + override def getGlobalComplianceMode(): Box[GlobalComplianceMode] = complianceModeService.getGlobalComplianceMode override def getGlobalAgentRun(): Box[AgentRunInterval] = agentRunService.getGlobalAgentRun() override def getAppliedRuleIds(rules:Seq[Rule], groupLib: FullNodeGroupCategory, directiveLib: FullActiveTechniqueCategory, allNodeInfos: Map[NodeId, NodeInfo]): Set[RuleId] = { rules.filter(r => ruleApplicationStatusService.isApplied(r, groupLib, directiveLib, allNodeInfos) match { @@ -436,8 +425,6 @@ trait PromiseGeneration_performeIO extends PromiseGenerationService { } - - /** * Build interpolation contexts. * @@ -479,7 +466,6 @@ trait PromiseGeneration_performeIO extends PromiseGenerationService { }.map( _.toMap) } - for { globalSystemVariables <- systemVarService.getGlobalSystemVariables() parameters <- buildParams(globalParameters) ?~! "Can not parsed global parameter (looking for interpolated variables)" @@ -535,7 +521,6 @@ trait PromiseGeneration_buildRuleVals extends PromiseGenerationService { trait PromiseGeneration_buildNodeConfigurations extends PromiseGenerationService with Loggable { def roNodeGroupRepository: RoNodeGroupRepository - /** * This is the draft of the policy, not yet a cfengine policy, but a level of abstraction between both */ @@ -551,9 +536,6 @@ trait PromiseGeneration_buildNodeConfigurations extends PromiseGenerationService , directiveOrder : BundleOrder ) extends HashcodeCaching - - - /** * From a list of ruleVal, find the list of all impacted nodes * with the actual Cf3PolicyDraft they will have. @@ -568,15 +550,12 @@ trait PromiseGeneration_buildNodeConfigurations extends PromiseGenerationService , allNodeInfos : Map[NodeId, NodeInfo] ) : Box[Seq[NodeConfiguration]] = { - //step 1: from RuleVals to expanded rules vals //1.1: group by nodes (because parameter expansion is node sensitive //1.3: build node config, binding ${rudder.parameters} parameters - //1.1: group by nodes - val seqOfMapOfPolicyDraftByNodeId = ruleVals.map { ruleVal => val wantedNodeIds = groupLib.getNodeIds(ruleVal.targets, allNodeInfos) @@ -675,7 +654,6 @@ trait PromiseGeneration_buildNodeConfigurations extends PromiseGenerationService } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// trait PromiseGeneration_updateAndWriteRule extends PromiseGenerationService { @@ -711,7 +689,6 @@ trait PromiseGeneration_updateAndWriteRule extends PromiseGenerationService { def getNodeConfigurationCache(): Box[Map[NodeId, NodeConfigurationCache]] = nodeConfigurationService.getNodeConfigurationCache() - /** * Detect changes in rules and update their serial * Returns two seq : the updated rules, and the deleted rules @@ -803,7 +780,6 @@ trait PromiseGeneration_updateAndWriteRule extends PromiseGenerationService { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - trait PromiseGeneration_setExpectedReports extends PromiseGenerationService { def reportingService : ExpectedReportsUpdate def complianceCache : CachedFindRuleNodeStatusReports @@ -883,7 +859,6 @@ trait PromiseGeneration_setExpectedReports extends PromiseGenerationService { } ).toMap - //we also want to build the list of overriden directive based on unique techniques. val overriden = configs.flatMap { nodeConfig => nodeConfig.policyDrafts.flatMap( x => x.overrides.map { case (ruleId, directiveId) => @@ -899,7 +874,6 @@ trait PromiseGeneration_setExpectedReports extends PromiseGenerationService { } } - trait PromiseGeneration_historization extends PromiseGenerationService { def historizationService : HistorizationService @@ -924,7 +898,4 @@ trait PromiseGeneration_historization extends PromiseGenerationService { } } - - } - diff --git a/rudder-core/src/main/scala/com/normation/rudder/services/policies/SystemVariableService.scala b/rudder-core/src/main/scala/com/normation/rudder/services/policies/SystemVariableService.scala index 1bf1f6388f..6bf0a2b0a4 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/services/policies/SystemVariableService.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/services/policies/SystemVariableService.scala @@ -71,7 +71,6 @@ trait SystemVariableService { ) : Box[Map[String, Variable]] } - final case class RudderServerRole( val name : String , val configValue: String @@ -82,7 +81,6 @@ final case class ResolvedRudderServerRole( , val configValue: Option[Iterable[String]] ) - class SystemVariableServiceImpl( licenseRepository: LicenseRepository , systemVariableSpecService: SystemVariableSpecService @@ -295,17 +293,17 @@ class SystemVariableServiceImpl( // A policy server is always sending heartbeat 1 } else { - globalComplianceMode match { - case FullCompliance => - 1 - case ChangesOnly(globalFrequency) => + globalComplianceMode.mode match { + case ChangesOnly => nodeInfo.nodeReportingConfiguration.heartbeatConfiguration match { // It overrides! use it to compute the new heartbeatInterval case Some(heartbeatConf) if heartbeatConf.overrides => heartbeatConf.heartbeatPeriod case _ => - globalFrequency + globalComplianceMode.heartbeatPeriod } + case _ => + 1 } } } @@ -345,7 +343,6 @@ class SystemVariableServiceImpl( // the schedule must be the default one for policy server - Map( varManagedNodes.spec.name -> varManagedNodes , varManagedNodesId.spec.name -> varManagedNodesId diff --git a/rudder-core/src/main/scala/com/normation/rudder/services/reports/ExecutionBatch.scala b/rudder-core/src/main/scala/com/normation/rudder/services/reports/ExecutionBatch.scala index 6430aa332c..692e96dc84 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/services/reports/ExecutionBatch.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/services/reports/ExecutionBatch.scala @@ -48,10 +48,8 @@ import com.normation.rudder.domain.logger.ComplianceDebugLogger._ import com.normation.rudder.domain.policies.Directive import com.normation.inventory.domain.NodeId import com.normation.rudder.domain.reports._ -import com.normation.rudder.reports.ComplianceMode import com.normation.utils.Control.sequence -import com.normation.rudder.reports.FullCompliance -import com.normation.rudder.reports.ChangesOnly +import com.normation.rudder.reports._ import com.normation.rudder.reports.execution.AgentRunId import net.liftweb.common.Loggable import com.normation.rudder.domain.policies.DirectiveId @@ -59,7 +57,6 @@ import com.normation.rudder.repository.NodeConfigIdInfo import com.normation.rudder.reports.execution.AgentRun import com.normation.rudder.domain.policies.SerialedRuleId import com.normation.rudder.domain.policies.SerialedRuleId -import com.normation.rudder.reports.ResolvedAgentRunInterval import com.normation.rudder.repository.NodeConfigIdInfo import com.normation.rudder.domain.policies.SerialedRuleId import com.normation.cfclerk.xmlparsers.CfclerkXmlConstants.DEFAULT_COMPONENT_KEY @@ -161,7 +158,6 @@ case class VersionNotFound( , lastRunConfigId: Option[NodeConfigId] ) extends ErrorNoConfigData - /* * No report of interest (either none, or * some but too old for our situation) @@ -170,8 +166,6 @@ case class NoReportInInterval( expectedConfigId: NodeConfigIdInfo ) extends NoReport - - case class Pending( expectedConfigId : NodeConfigIdInfo , optLastRun : Option[(DateTime, NodeConfigIdInfo)] @@ -179,7 +173,6 @@ case class Pending( , missingReportStatus: ReportType ) extends NoReport with ExpiringStatus with MissingReportStatus - /* * the case where we have a version on the run, * versions are init in the server for that node, @@ -193,7 +186,6 @@ case class UnexpectedVersion( , expectedExpiration: DateTime ) extends Unexpected with LastRunAvailable - case class ComputeCompliance( lastRunDateTime : DateTime , lastRunConfigId : NodeConfigIdInfo @@ -202,9 +194,6 @@ case class ComputeCompliance( , missingReportStatus: ReportType ) extends Ok with LastRunAvailable with ExpiringStatus with MissingReportStatus - - - /** * An execution batch contains the node reports for a given Rule / Directive at a given date * An execution Batch is at a given time <- TODO : Is it relevant when we have several node ? @@ -254,7 +243,6 @@ object ExecutionBatch extends Loggable { , complianceMode : ComplianceMode ) - /* * Utility method to factor out common logging task and be assured that * the log message is actually sync with the info type. @@ -278,9 +266,10 @@ object ExecutionBatch extends Loggable { , complianceMode : ComplianceMode ): Map[NodeId, RunAndConfigInfo] = { - val missingReportType = complianceMode match { + val missingReportType = complianceMode.mode match { case FullCompliance => MissingReportType - case ChangesOnly(_) => SuccessReportType + case ChangesOnly => SuccessReportType + case ReportDisabled => MissingReportType } /* @@ -293,12 +282,12 @@ object ExecutionBatch extends Loggable { /* * How long time a run is valid before receiving any report (but not after an update) */ - def runValidityTime(runIntervalInfo: ResolvedAgentRunInterval) = complianceMode match { - case ChangesOnly(_) => + def runValidityTime(runIntervalInfo: ResolvedAgentRunInterval) = complianceMode.mode match { + case ChangesOnly => //expires after run*heartbeat period - we need an other run before that. val heartbeat = Duration.standardMinutes((runIntervalInfo.interval.getStandardMinutes * runIntervalInfo.heartbeatPeriod )) heartbeat.plus(GRACE_TIME_PENDING) - case FullCompliance => + case FullCompliance | ReportDisabled => updateValidityTime(runIntervalInfo) } @@ -480,7 +469,6 @@ object ExecutionBatch extends Loggable { , agentExecutionReports: Seq[Reports] ) : Seq[RuleNodeStatusReport] = { - //a method to get the expected reports for the given configId and log a debug message is none //are found - because they really should have def getExpectedReports(configId: NodeConfigId): Map[SerialedRuleId, RuleNodeExpectedReports] = { @@ -573,13 +561,10 @@ object ExecutionBatch extends Loggable { ComplianceDebugLogger.node(nodeId).warn(s"Can not get compliance for node with ID '${nodeId.value}' because it has no configuration id initialised nor sent reports (node just added ?)") Seq() - } } - - /** * That method only take care of the low level logic of comparing * expected reports with actual reports rule by rule. So we expect @@ -617,7 +602,6 @@ object ExecutionBatch extends Loggable { , missingReportStatus : ReportType ): Seq[RuleNodeStatusReport] = { - val complianceForRun: Map[SerialedRuleId, RuleNodeStatusReport] = (for { ( SerialedRuleId(ruleId, serial) , expectedReport ) <- expectedReportsForRun @@ -722,7 +706,6 @@ object ExecutionBatch extends Loggable { computed ++ newStatus } - private[this] def getUnexpanded(seq: Seq[Option[String]]): Option[String] = { val unexpanded = seq.toSet if(unexpanded.size > 1) { @@ -731,7 +714,6 @@ object ExecutionBatch extends Loggable { unexpanded.head } - private[this] def buildUnexpectedReports(mergeInfo: MergeInfo, reports: Seq[Reports]): Seq[RuleNodeStatusReport] = { reports.groupBy(x => (x.ruleId, x.serial)).map { case ((ruleId, serial), seq) => RuleNodeStatusReport( @@ -789,7 +771,6 @@ object ExecutionBatch extends Loggable { }.toSeq } - /** * Allows to calculate the status of component for a node. * We don't deal with interpretation at that level, @@ -962,7 +943,6 @@ object ExecutionBatch extends Loggable { // Generate our value for cfengine variables val (cfeVarValues, lastReports) = extractCFVarsFromReports (valueKind.cfeVar.mapValues(_.map(replaceCFEngineVars(_))).toList, Seq(), remainingReports) - // Finally, if we still got some reports, generate an unexpected report. /* * Here, we don't havve any mean to know if the unexpected comes from a CFEngine variable or not. diff --git a/rudder-core/src/main/scala/com/normation/rudder/services/reports/ReportingServiceImpl.scala b/rudder-core/src/main/scala/com/normation/rudder/services/reports/ReportingServiceImpl.scala index d37a935fd8..4677d9abac 100644 --- a/rudder-core/src/main/scala/com/normation/rudder/services/reports/ReportingServiceImpl.scala +++ b/rudder-core/src/main/scala/com/normation/rudder/services/reports/ReportingServiceImpl.scala @@ -51,9 +51,9 @@ import com.normation.rudder.reports.AgentRunIntervalService import com.normation.rudder.domain.policies.SerialedRuleId import com.normation.rudder.domain.logger.TimingDebugLogger import com.normation.rudder.services.nodes.NodeInfoService - import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global +import com.normation.rudder.reports.GlobalComplianceMode /** * Defaults non-cached version of the reporting service. @@ -65,10 +65,9 @@ class ReportingServiceImpl( , val agentRunRepository : RoReportsExecutionRepository , val nodeConfigInfoRepo : RoNodeConfigIdInfoRepository , val runIntervalService : AgentRunIntervalService - , val getComplianceMode : () => Box[ComplianceMode] + , val getGlobalComplianceMode : () => Box[GlobalComplianceMode] ) extends ReportingService with RuleOrNodeReportingServiceImpl with DefaultFindRuleNodeStatusReports - class CachedReportingServiceImpl( val defaultFindRuleNodeStatusReports: ReportingServiceImpl , val nodeInfoService : NodeInfoService @@ -143,7 +142,6 @@ trait CachedFindRuleNodeStatusReports extends ReportingService with CachedReposi }.mkString("\n", "\n", "") } - /** * Invalidate some keys in the cache. That won't charge them again * immediately @@ -158,7 +156,6 @@ trait CachedFindRuleNodeStatusReports extends ReportingService with CachedReposi () } - /** * For the nodeIds in parameter, check that the cache is: * - initialized, else go find missing rule node status reports (one time for all) @@ -234,7 +231,6 @@ trait CachedFindRuleNodeStatusReports extends ReportingService with CachedReposi } - trait DefaultFindRuleNodeStatusReports extends ReportingService { def confExpectedRepo : FindExpectedReportRepository @@ -242,7 +238,7 @@ trait DefaultFindRuleNodeStatusReports extends ReportingService { def agentRunRepository: RoReportsExecutionRepository def nodeConfigInfoRepo: RoNodeConfigIdInfoRepository def runIntervalService: AgentRunIntervalService - def getComplianceMode : () => Box[ComplianceMode] + def getGlobalComplianceMode : () => Box[GlobalComplianceMode] override def findRuleNodeStatusReports(nodeIds: Set[NodeId], ruleIds: Set[RuleId]) : Box[Set[RuleNodeStatusReport]] = { /* @@ -321,7 +317,7 @@ trait DefaultFindRuleNodeStatusReports extends ReportingService { } for { - compliance <- getComplianceMode() + compliance <- getGlobalComplianceMode() runs <- agentRunRepository.getNodesLastRun(nodeIds) nodeConfigIdInfos <- nodeConfigInfoRepo.getNodeConfigIdInfos(nodeIds) runIntervals <- runIntervalService.getNodeReportingConfigurations(nodeIds) @@ -334,7 +330,6 @@ trait DefaultFindRuleNodeStatusReports extends ReportingService { } } - /* * Given a set of agent runs and expected reports, retrieve the corresponding * execution reports and then nodestatusreports, being smart about what to @@ -377,4 +372,3 @@ trait DefaultFindRuleNodeStatusReports extends ReportingService { }.toSeq } } - diff --git a/rudder-core/src/test/scala/com/normation/rudder/repository/jdbc/ReportingServiceTest.scala b/rudder-core/src/test/scala/com/normation/rudder/repository/jdbc/ReportingServiceTest.scala index 225c1ed193..5ea85a3b21 100644 --- a/rudder-core/src/test/scala/com/normation/rudder/repository/jdbc/ReportingServiceTest.scala +++ b/rudder-core/src/test/scala/com/normation/rudder/repository/jdbc/ReportingServiceTest.scala @@ -69,6 +69,9 @@ import com.normation.rudder.services.reports.CachedFindRuleNodeStatusReports import com.normation.rudder.services.reports.DefaultFindRuleNodeStatusReports import com.normation.rudder.services.nodes.NodeInfoService import com.normation.rudder.services.reports.RuleOrNodeReportingServiceImpl +import com.normation.rudder.reports.ComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode /** * @@ -127,7 +130,6 @@ class ReportingServiceTest extends DBCommon { import slick._ - //help differentiate run number with the millis //perfect case: generation are followe by runs one minute latter @@ -161,11 +163,9 @@ class ReportingServiceTest extends DBCommon { * TODO: need to test for "overridden" unique directive on a node */ - //BE CAREFULL: we don't compare on expiration dates! val EXPIRATION_DATE = new DateTime(0) - val allNodes_t1 = Seq("n0", "n1", "n2", "n3", "n4").map(n => (NodeId(n), NodeConfigIdInfo(NodeConfigId(n+"_t1"), gen1, Some(gen2) ))).toMap val allNodes_t2 = Seq("n0", "n1", "n2", "n3", "n4").map(n => (NodeId(n), NodeConfigIdInfo(NodeConfigId(n+"_t2"), gen2, None ))).toMap @@ -250,7 +250,6 @@ class ReportingServiceTest extends DBCommon { updateExpected.addNodeConfigIdInfo(allNodes_t2.mapValues(_.configId), gen2).openOrThrowException("I should be able to add node config id info") } - "Testing set-up for expected reports and agent run" should { //be in ExpectedReportsTest! //essentially test the combination of in/in(values clause @@ -330,7 +329,15 @@ class ReportingServiceTest extends DBCommon { ///////////////////////////////// changes only mode ///////////////////////////////// "Finding rule status reports for the change only mode" should { - lazy val errorOnlyReportingService = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(ChangesOnly(1))) + lazy val errorOnlyReportingService = + new ReportingServiceImpl( + findExpected + , reportsRepo + , roAgentRun + , findExpected + , agentRunService + , () => Full(GlobalComplianceMode(ChangesOnly,1)) + ) "get r0" in { @@ -411,7 +418,6 @@ class ReportingServiceTest extends DBCommon { val r = errorOnlyReportingService.findDirectiveRuleStatusReportsByRule(RuleId("r2")) val result = r.openOrThrowException("'Test failled'") - val expected = Seq( /** * changed not to long ago => pending @@ -458,11 +464,11 @@ class ReportingServiceTest extends DBCommon { } } + val fullCompliance = GlobalComplianceMode(FullCompliance, 1) ///////////////////////////////// full compliance mode ///////////////////////////////// "Finding rule status reports for the compliance mode" should { - lazy val complianceReportingService = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(FullCompliance)) - + lazy val complianceReportingService = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(fullCompliance)) "get r0" in { @@ -579,7 +585,14 @@ class ReportingServiceTest extends DBCommon { ///////////////////////////////// error only mode ///////////////////////////////// "Finding node status reports for the changes only mode" should { - lazy val errorOnlyReportingService = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(ChangesOnly(1))) + lazy val errorOnlyReportingService = + new ReportingServiceImpl( + findExpected + , reportsRepo + , roAgentRun + , findExpected + , agentRunService + , () => Full(GlobalComplianceMode(ChangesOnly,1))) "get pending for node 0 on gen2 data" in { ComplianceDebugLogger.info("changes only / node0") @@ -668,7 +681,7 @@ class ReportingServiceTest extends DBCommon { ///////////////////////////////// full compliance mode ///////////////////////////////// "Finding node status reports for the compliance mode" should { - lazy val complianceReportingService:ReportingServiceImpl = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(FullCompliance)) + lazy val complianceReportingService:ReportingServiceImpl = new ReportingServiceImpl(findExpected, reportsRepo, roAgentRun, findExpected, agentRunService, () => Full(fullCompliance)) "get pending for node 0 on gen2 data (without msg)" in { ComplianceDebugLogger.info("compliance / node0") @@ -704,7 +717,6 @@ class ReportingServiceTest extends DBCommon { )) } - /* * This case is a little touchy because node2 sent reports for gen1/run1, * but not for gen2 (current expectation). diff --git a/rudder-core/src/test/scala/com/normation/rudder/services/reports/ExecutionBatchTest.scala b/rudder-core/src/test/scala/com/normation/rudder/services/reports/ExecutionBatchTest.scala index e532ddf3c9..de18ef5ff4 100644 --- a/rudder-core/src/test/scala/com/normation/rudder/services/reports/ExecutionBatchTest.scala +++ b/rudder-core/src/test/scala/com/normation/rudder/services/reports/ExecutionBatchTest.scala @@ -34,7 +34,6 @@ package com.normation.rudder.services.reports - import org.junit.runner._ import org.specs2.mutable._ import org.specs2.runner._ @@ -51,6 +50,10 @@ import com.normation.rudder.reports.ChangesOnly import com.normation.rudder.domain.policies.SerialedRuleId import com.normation.rudder.domain.policies.SerialedRuleId import com.normation.rudder.domain.policies.SerialedRuleId +import com.normation.rudder.reports.ComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode +import com.normation.rudder.reports.ReportDisabled @RunWith(classOf[JUnitRunner]) class ExecutionBatchTest extends Specification { @@ -72,7 +75,6 @@ class ExecutionBatchTest extends Specification { }.toMap } - def getNodeStatusReportsByRule( ruleExpectedReports : Map[NodeId, Map[NodeConfigId, Map[SerialedRuleId, RuleNodeExpectedReports]]] , reportsParam : Seq[Reports] @@ -80,15 +82,15 @@ class ExecutionBatchTest extends Specification { , complianceMode : ComplianceMode ): Seq[RuleNodeStatusReport] = { - val res = (for { (nodeId, expected) <- ruleExpectedReports.toSeq } yield { val runTime = reportsParam.headOption.map( _.executionTimestamp).getOrElse(DateTime.now) val info = NodeConfigIdInfo(expected.keySet.head, DateTime.now.minusDays(1), None) - val runInfo = complianceMode match { + val runInfo = complianceMode.mode match { case FullCompliance => ComputeCompliance(runTime, info, info, runTime.plusMinutes(5), MissingReportType) - case ChangesOnly(heartbeatPeriod) => ComputeCompliance(runTime, info, info, runTime.plusMinutes(5), SuccessReportType) + case ChangesOnly => ComputeCompliance(runTime, info, info, runTime.plusMinutes(5), SuccessReportType) + case ReportDisabled => ComputeCompliance(runTime, info, info, runTime.plusMinutes(5), MissingReportType) } ExecutionBatch.getNodeStatusReports(nodeId, runInfo, expected, reportsParam) @@ -99,8 +101,6 @@ class ExecutionBatchTest extends Specification { val getNodeStatusByRule = (getNodeStatusReportsByRule _).tupled - - //Test the component part "A component, with two different keys" should { val executionTimestamp = new DateTime() @@ -235,7 +235,6 @@ class ExecutionBatchTest extends Specification { } } - // Test the component part "A component, with generation-time known keys" should { val executionTimestamp = new DateTime() @@ -368,6 +367,7 @@ class ExecutionBatchTest extends Specification { } } + val fullCompliance = GlobalComplianceMode(FullCompliance, 1) "A detailed execution Batch, with one component, cardinality one, one node" should { val param = ( @@ -381,14 +381,11 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(DateTime.now(), "rule", "policy", "one", 12, "component", "value", DateTime.now(), "message")) - , FullCompliance + , fullCompliance ) - - val nodeStatus = (getNodeStatusReportsByRule _).tupled(param) - "have one detailed reports when we create it with one report" in { nodeStatus.size ==1 } @@ -397,7 +394,6 @@ class ExecutionBatchTest extends Specification { nodeStatus.head.nodeId === str2nodeId("one") } - "have one detailed rule success directive when we create it with one success report" in { nodeStatus.head.directives.head._1 === DirectiveId("policy") } @@ -419,7 +415,7 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(DateTime.now(), "rule", "policy", "two", 12, "component", "value",DateTime.now(), "message")) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -450,7 +446,7 @@ class ExecutionBatchTest extends Specification { new ResultSuccessReport(DateTime.now(), "rule", "policy", "one", 12, "component", "value",DateTime.now(), "message") , new ResultSuccessReport(DateTime.now(), "rule", "policy", "one", 12, "component", "value",DateTime.now(), "message") ) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -465,6 +461,7 @@ class ExecutionBatchTest extends Specification { } "A detailed execution Batch, with one component, cardinality one, two nodes, including one not responding" should { + val param = ( buildExpected( Seq("one", "two") @@ -476,7 +473,7 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(DateTime.now(), "rule", "policy", "one", 12, "component", "value",DateTime.now(), "message")) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -504,7 +501,7 @@ class ExecutionBatchTest extends Specification { new ResultSuccessReport(DateTime.now(), "rule", "policy", "one", 12, "component", "value", DateTime.now(), "message") , new ResultSuccessReport(DateTime.now(), "rule", "policy", "two", 12, "component", "value", DateTime.now(), "message") ) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -541,7 +538,7 @@ class ExecutionBatchTest extends Specification { new ResultSuccessReport(DateTime.now(), "rule", "policy", "two", 12, "component2", "value",DateTime.now(), "message"), new ResultSuccessReport(DateTime.now(), "rule", "policy2", "two", 12, "component", "value",DateTime.now(), "message") ) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) val aggregated = AggregatedStatusReport(nodeStatus.toSet) @@ -583,7 +580,7 @@ class ExecutionBatchTest extends Specification { new ResultSuccessReport(DateTime.now(), "rule", "policy2", "two", 12, "component", "value",DateTime.now(), "message"), new ResultSuccessReport(DateTime.now(), "rule", "policy", "three", 12, "component", "value",DateTime.now(), "message") ) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) val aggregated = AggregatedStatusReport(nodeStatus.toSet) @@ -628,7 +625,7 @@ class ExecutionBatchTest extends Specification { new ResultSuccessReport(DateTime.now(), "rule", "policy", "two", 12, "component", "value2",DateTime.now(), "message"), new ResultSuccessReport(DateTime.now(), "rule", "policy", "three", 12, "component", "value",DateTime.now(), "message") ) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) val aggregated = AggregatedStatusReport(nodeStatus.toSet) @@ -666,7 +663,7 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(new DateTime(), "rule", "policy", "one", 12, "component", """some\"text""",new DateTime(), "message")) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -694,7 +691,7 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(new DateTime(), "rule", "policy", "nodeId", 12, "component", """/var/cfengine/inputs/\"test""", new DateTime(), "message")) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) @@ -721,7 +718,7 @@ class ExecutionBatchTest extends Specification { ) ) , Seq[Reports](new ResultSuccessReport(new DateTime(), "rule", "policy", "nodeId", 12, "component", """/var/cfengine/inputs/"test""", new DateTime(), "message")) - , FullCompliance + , fullCompliance ) val nodeStatus = getNodeStatusByRule(param) diff --git a/rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala b/rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala index bbc03c737a..57007aaab3 100644 --- a/rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala +++ b/rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala @@ -153,7 +153,6 @@ sealed trait ConfigResource final case class ClassPathResource(name: String) extends ConfigResource final case class FileSystemResource(file: File) extends ConfigResource - final case class AuthenticationMethods(name: String) { val path = s"applicationContext-security-auth-${name}.xml" val configFile = s"classpath:${path}" @@ -166,8 +165,6 @@ final case class AuthenticationMethods(name: String) { */ object RudderProperties { - - val JVM_CONFIG_FILE_KEY = "rudder.configFile" val DEFAULT_CONFIG_FILE_NAME = "configuration.properties" @@ -232,10 +229,6 @@ object RudderProperties { } - - - - /** * Static initialization of Rudder services. * This is not a cake-pattern, more an ad-hoc replacement @@ -411,7 +404,6 @@ object RudderConfig extends Loggable { lazy val roAgentRunsRepository : RoReportsExecutionRepository = cachedAgentRunRepository lazy val woAgentRunsRepository : WoReportsExecutionRepository = cachedAgentRunRepository - //all cache that need to be cleared are stored here lazy val clearableCache: Seq[CachedRepository] = Seq( cachedAgentRunRepository @@ -448,14 +440,12 @@ object RudderConfig extends Loggable { ) } - val roRuleCategoryRepository : RoRuleCategoryRepository = roLDAPRuleCategoryRepository val ruleCategoryService : RuleCategoryService = new RuleCategoryService() val woRuleCategoryRepository : WoRuleCategoryRepository = woLDAPRuleCategoryRepository val changeRequestEventLogService : ChangeRequestEventLogService = new ChangeRequestEventLogServiceImpl(eventLogRepository) - val xmlSerializer = XmlSerializerImpl( ruleSerialisation , directiveSerialisation @@ -528,7 +518,6 @@ object RudderConfig extends Loggable { ///////////////////////////////////////// REST /////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// - val restExtractorService = RestExtractorService ( roRuleRepository @@ -671,8 +660,6 @@ object RudderConfig extends Loggable { , restExtractorService ) - - def nodeApi4Builder(version: Int) = { val fixedApiService2 = nodeApiService2.copy(fixedTag = true) val fixedApi2 = nodeApi2.copy(apiV2 = fixedApiService2) @@ -705,8 +692,6 @@ object RudderConfig extends Loggable { ) } - - val nodeApi6 = { new NodeAPI6 ( nodeApi5 @@ -754,7 +739,6 @@ object RudderConfig extends Loggable { , configService.rudder_workflow_enabled ) - val changeRequestApi3 = new ChangeRequestAPI3 ( restExtractorService @@ -770,7 +754,6 @@ object RudderConfig extends Loggable { ) ) - val apiV2 : List[RestAPI] = ruleApi2 :: directiveApi2 :: groupApi2 :: nodeApi2 :: parameterApi2 :: Nil val apiV3 : List[RestAPI] = changeRequestApi3 :: apiV2 val apiV4 : List[RestAPI] = nodeApi4 :: apiV3.filter( _ != nodeApi2) @@ -826,7 +809,6 @@ object RudderConfig extends Loggable { } } - // // Concrete implementation. // They are private to that object, and they can refer to other @@ -916,7 +898,6 @@ object RudderConfig extends Loggable { private[this] lazy val fullInventoryFromLdapEntries: FullInventoryFromLdapEntries = new FullInventoryFromLdapEntriesImpl(inventoryDitService, inventoryMapper) private[this] lazy val ldapDiffMapper = new LDAPDiffMapper(ldapEntityMapper, queryParser) - private[this] lazy val activeTechniqueCategoryUnserialisation = new ActiveTechniqueCategoryUnserialisationImpl private[this] lazy val activeTechniqueUnserialisation = new ActiveTechniqueUnserialisationImpl private[this] lazy val directiveUnserialisation = new DirectiveUnserialisationImpl @@ -973,8 +954,6 @@ object RudderConfig extends Loggable { new TechniqueParser(variableSpecParser,sectionSpecParser,new Cf3PromisesFileTemplateParser,systemVariableSpecService) } - - private[this] lazy val userPropertyServiceImpl = new StatelessUserPropertyService( configService.rudder_ui_changeMessage_enabled , configService.rudder_ui_changeMessage_mandatory @@ -1165,7 +1144,6 @@ object RudderConfig extends Loggable { private[this] lazy val nodeReadWriteMutex = ScalaLock.java2ScalaRWLock(new java.util.concurrent.locks.ReentrantReadWriteLock(true)) private[this] lazy val parameterReadWriteMutex = ScalaLock.java2ScalaRWLock(new java.util.concurrent.locks.ReentrantReadWriteLock(true)) - private[this] lazy val roLdapDirectiveRepository = new RoLDAPDirectiveRepository( rudderDitImpl, roLdap, ldapEntityMapper, techniqueRepositoryImpl, uptLibReadWriteMutex) private[this] lazy val woLdapDirectiveRepository = {{ @@ -1443,7 +1421,7 @@ object RudderConfig extends Loggable { , roAgentRunsRepository , findExpectedRepo , globalAgentRunService - , globalComplianceModeService.getComplianceMode _ + , globalComplianceModeService.getGlobalComplianceMode _ ) , nodeInfoServiceImpl ) @@ -1606,7 +1584,6 @@ object RudderConfig extends Loggable { * Event log migration */ - private[this] lazy val migrationRepository = new MigrationEventLogRepository(squerylDatasourceProvider) private[this] lazy val eventLogsMigration_2_3 = new EventLogsMigration_2_3( @@ -1676,8 +1653,6 @@ object RudderConfig extends Loggable { * ************************************************** */ - - private[this] lazy val ruleCategoriesDirectory = new File(new File(RUDDER_DIR_GITROOT),ruleCategoriesDirectoryName) private[this] lazy val allChecks = new SequentialImmediateBootStrapChecks( @@ -1705,8 +1680,6 @@ object RudderConfig extends Loggable { ) ) - - ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// Directive Editor and web fields ////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// @@ -1819,7 +1792,6 @@ object RudderConfig extends Loggable { val aggregateReportScheduler = new FindNewReportsExecution(executionService,RUDDER_REPORTS_EXECUTION_INTERVAL) } - /** * Spring configuration for services */ @@ -1827,7 +1799,6 @@ object RudderConfig extends Loggable { @Import(Array(classOf[AppConfigAuth])) class AppConfig extends Loggable { - ////////////////////// Snippet plugins & extension register ////////////////////// import com.normation.plugins.{ SnippetExtensionRegister, SnippetExtensionRegisterImpl } @Bean diff --git a/rudder-web/src/main/scala/com/normation/rudder/appconfig/ConfigService.scala b/rudder-web/src/main/scala/com/normation/rudder/appconfig/ConfigService.scala index 6a7bb9d054..7e34d9d458 100644 --- a/rudder-web/src/main/scala/com/normation/rudder/appconfig/ConfigService.scala +++ b/rudder-web/src/main/scala/com/normation/rudder/appconfig/ConfigService.scala @@ -110,19 +110,16 @@ trait ReadConfigService { */ def rudder_store_all_centralized_logs_in_file(): Box[Boolean] - /** - * Compliance mode: - * - "compliance": full compliance mode, where "success" execution reports are sent - * back from node to server, and taken into account for compliance reports, - * - "error_only": only error and repaired are going to the server. + * Compliance mode: See ComplianceMode class for more details */ - def rudder_compliance_mode(): Box[(String,Int)] = { + def rudder_compliance_mode(): Box[GlobalComplianceMode] = { for { name <- rudder_compliance_mode_name + modeName <- ComplianceModeName.parse(name) period <- rudder_compliance_heartbeatPeriod } yield { - (name,period) + GlobalComplianceMode(modeName,period) } } @@ -130,7 +127,6 @@ trait ReadConfigService { def rudder_compliance_heartbeatPeriod(): Box[Int] - /** * Send Metrics */ @@ -192,11 +188,11 @@ trait UpdateConfigService { /** * Set the compliance mode */ - def set_rudder_compliance_mode(name : String, frequency : Int, actor: EventActor, reason: Option[String]): Box[Unit] = { + def set_rudder_compliance_mode(mode : ComplianceMode, actor: EventActor, reason: Option[String]): Box[Unit] = { for { - _ <- set_rudder_compliance_mode_name(name,actor, reason) - u <- name match { - case ChangesOnly.name => set_rudder_compliance_heartbeatPeriod(frequency, actor, reason) + _ <- set_rudder_compliance_mode_name(mode.name,actor, reason) + u <- mode.name match { + case ChangesOnly.name => set_rudder_compliance_heartbeatPeriod(mode.heartbeatPeriod, actor, reason) case _ => Full(()) } } yield { @@ -343,7 +339,6 @@ class LDAPBasedConfigService(configFile: Config, repos: ConfigRepository, workfl } } - } def set_agent_run_interval(value: Int, actor: EventActor, reason: Option[String]): Box[Unit] = { cacheExecutionInterval = Some(value) @@ -399,7 +394,6 @@ class LDAPBasedConfigService(configFile: Config, repos: ConfigRepository, workfl save("rudder_compliance_heartbeatPeriod", value, Some(info)) } - /** * Send Metrics */ @@ -411,7 +405,6 @@ class LDAPBasedConfigService(configFile: Config, repos: ConfigRepository, workfl save("send_server_metrics",newVal,Some(info)) } - /** * Report protocol */ diff --git a/rudder-web/src/main/scala/com/normation/rudder/web/components/AgentScheduleEditForm.scala b/rudder-web/src/main/scala/com/normation/rudder/web/components/AgentScheduleEditForm.scala index 3465e78a49..f8cfc2ce58 100644 --- a/rudder-web/src/main/scala/com/normation/rudder/web/components/AgentScheduleEditForm.scala +++ b/rudder-web/src/main/scala/com/normation/rudder/web/components/AgentScheduleEditForm.scala @@ -34,7 +34,6 @@ package com.normation.rudder.web.components - import bootstrap.liftweb.RudderConfig import net.liftweb.http.DispatchSnippet import net.liftweb.common._ @@ -71,7 +70,7 @@ class AgentScheduleEditForm( .format(templatePath.mkString("/"))) case Full(n) => n } - def agentScheduleTemplate = chooseTemplate("schedule", "agentSchedule", template) + def agentScheduleTemplate = chooseTemplate("schedule", "agentschedule", template) def dispatch = { case "cfagentSchedule" => (xml) => cfagentScheduleConfiguration diff --git a/rudder-web/src/main/scala/com/normation/rudder/web/components/ComplianceModeEditForm.scala b/rudder-web/src/main/scala/com/normation/rudder/web/components/ComplianceModeEditForm.scala index 25c883bac5..8355c129c8 100644 --- a/rudder-web/src/main/scala/com/normation/rudder/web/components/ComplianceModeEditForm.scala +++ b/rudder-web/src/main/scala/com/normation/rudder/web/components/ComplianceModeEditForm.scala @@ -34,7 +34,6 @@ package com.normation.rudder.web.components - import bootstrap.liftweb.RudderConfig import net.liftweb.http.DispatchSnippet import net.liftweb.common._ @@ -54,108 +53,177 @@ import net.liftweb.util.PassThru import net.liftweb.util.ClearNodes import com.normation.rudder.reports.ComplianceMode import com.normation.rudder.reports.FullCompliance -import ComplianceModeEditForm._ import com.normation.eventlog.EventActor import com.normation.rudder.web.model.CurrentUser - - +import com.normation.rudder.reports.ComplianceModeName +import net.liftweb.json.JsonAST._ +import net.liftweb.json.Printer +import com.normation.rudder.reports.ComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode +import com.normation.rudder.reports.NodeComplianceMode +import scala.reflect.runtime.universe._ +import com.normation.rudder.reports.GlobalComplianceMode +import com.normation.rudder.reports.NodeComplianceMode /** * Component to display and configure the compliance Mode (and it's heartbeat) */ -class ComplianceModeEditForm ( - getConfigureCallback : () => Box[(String,Int,Boolean)] - , saveConfigureCallback: (String,Int,Boolean) => Box[Unit] +class ComplianceModeEditForm [T <: ComplianceMode] ( + getConfigureCallback : Box[T] + , saveConfigureCallback: Function1[T,Box[Unit]] , startNewPolicyGeneration: () => Unit - , getGlobalConfiguration : () => Option[Box[Int]] = () => None -) extends DispatchSnippet with Loggable { - + , getGlobalConfiguration : Box[GlobalComplianceMode] +) (implicit tt : TypeTag[T]) extends DispatchSnippet with Loggable { // Html template def templatePath = List("templates-hidden", "components", "ComponentComplianceMode") def template() = Templates(templatePath) match { - case Empty | Failure(_,_,_) => + case _ : EmptyBox => sys.error(s"Template for Compliance mode configuration not found. I was looking for ${templatePath.mkString("/")}.html") case Full(n) => n } - def agentScheduleTemplate = chooseTemplate("property", "complianceMode", template) + def complianceModeTemplate = chooseTemplate("property", "compliancemode", template) def dispatch = { case "complianceMode" => (xml) => complianceModeConfiguration } - def submit(jsonSchedule:String) = { - parseJsonSchedule(jsonSchedule) match { + val isNodePage : Boolean = { + typeOf[T] match { + case t if t =:= typeOf[GlobalComplianceMode] => false + case t if t =:= typeOf[NodeComplianceMode] => true + } + } + + def submit(jsonMode:String) = { + parseJsonMode(jsonMode) match { case eb:EmptyBox => - val e = eb ?~! s"Error when trying to parse user data: '${jsonSchedule}'" + val e = eb ?~! s"Error when trying to parse user data: '${jsonMode}'" logger.error(e.messageChain) S.error("complianceModeMessage", e.messageChain) - case Full((name,frequency,overrides)) => - saveConfigureCallback(name,frequency,overrides) match { + case Full(complianceMode : T) => + saveConfigureCallback(complianceMode) match { case eb:EmptyBox => - val e = eb ?~! s"Error when trying to store in base new agent schedule: '${jsonSchedule}'" + val e = eb ?~! s"Error when trying to store in base new compliance mode: '${jsonMode}'" logger.error(e.messageChain) S.error("complianceModeMessage", e.messageChain) case Full(success) => // start a promise generation, Since we check if there is change to save, if we got there it mean that we need to redeploy startNewPolicyGeneration() - S.notice("complianceModeMessage", "Agent schedule saved") + S.notice("complianceModeMessage", "Compliance mode saved") } } } /** - * Parse a json input into a cf-agent Scedule + * Parse a json input into a valid complianceMode */ - def parseJsonSchedule(s: String) : Box[(String,Int,Boolean)] = { + def parseJsonMode(s: String) : Box[ComplianceMode] = { import net.liftweb.json._ val json = parse(s) - ( for { - JField("name" , JString(name)) <- json - JField("heartbeatPeriod" , JInt(frequency)) <- json - JField("overrides" , JBool(overrides)) <- json - } yield { - (name,frequency.toInt,overrides) - } ) match { - case head :: _ => - Full(head) - case Nil => - Failure(s"Could not parse ${s} as a valid cf-agent schedule") + def parseOverride(jsonMode : JObject) : Box[Boolean] = { + jsonMode.values.get("overrides") match { + case Some(JBool(bool)) => Full(bool) + case Some(allow_override : Boolean) => Full(allow_override) + case Some(json : JValue) => Failure(s"'${render(json)}' is not a valid value for compliance mode 'override' attribute") + // Should not happen, values in lift json are only JValues, but since we type any we have to add it unless we will have a warning + case Some(any) => Failure(s"'${any}' is not a valid value for compliance mode 'override' attribute") + case None => Failure("compliance mode 'overrides' parameter must not be empty ") + } + } + + def parseMode(jsonMode: JObject) : Box[ComplianceModeName]= { + jsonMode.values.get("name") match { + case Some(JString(mode)) => ComplianceModeName.parse(mode) + case Some(mode : String) => ComplianceModeName.parse(mode) + case Some(json : JValue) => Failure(s"'${(json)}' is not a valid value for compliance mode 'name' attribute") + // Should not happen, values in lift json are only JValues, but since we type any we have to add it unless we will have a warning + case Some(any) => Failure(s"'${any}' is not a valid value for compliance mode 'name' attribute") + case None => Failure("compliance mode 'name' parameter must not be empty ") + } + } + + def parseHeartbeat(jsonMode: JObject) : Box[Int]= { + jsonMode.values.get("heartbeatPeriod") match { + case Some(JInt(heartbeat)) => Full(heartbeat.toInt) + case Some(heartbeat : BigInt) => Full(heartbeat.toInt) + case Some(json : JValue) => Failure(s"'${(json)}' is not a valid value for compliance mode 'heartbeatPeriod' attribute") + // Should not happen, values in lift json are only JValues, but since we type any we have to add it unless we will have a warning + case Some(any) => Failure(s"'${any}' is not a valid value for compliance mode 'heartbeatPeriod' attribute") + case None => Failure("compliance mode 'heartbeatPeriod' parameter must not be empty ") + } + } + json match { + case obj : JObject => + for { + mode <- parseMode(obj) + heartbeat <- parseHeartbeat(obj) + complianceMode <- + typeOf[T] match { + case t if t =:= typeOf[GlobalComplianceMode] => + Full(GlobalComplianceMode(mode,heartbeat)) + case t if t =:= typeOf[NodeComplianceMode] => + for { + overrides <- parseOverride(obj) + } yield { + NodeComplianceMode(mode,heartbeat,overrides) + } + } + } yield { + complianceMode + } + case _ => + Failure(s"Could not parse ${s} as a valid compliance mode") } } - def complianceModeConfiguration = { + def toJs (mode : ComplianceMode )= { + def json : JValue = { + import net.liftweb.json.JsonDSL._ + val baseMode = + ( "name" -> mode.name ) ~ + ( "heartbeatPeriod" -> mode.heartbeatPeriod) + + mode match { + case node : NodeComplianceMode => + baseMode ~ ( "overrides" -> node.overrideGlobal) + case _ => baseMode + } + } + Printer.compact(render(json)) + } + + def complianceModeConfiguration = { val transform = (for { - (complianceMode, frequency,overrides) <- getConfigureCallback() - globalRun <- getGlobalConfiguration() match { - case None => Full("undefined") - case Some(g) => g.map(_.toString()) - } + complianceMode <- getConfigureCallback + globalMode <- getGlobalConfiguration } yield { val callback = AnonFunc("complianceMode",SHtml.ajaxCall(JsVar("complianceMode"), submit)) + + val allModes = ComplianceModeName.allModes.mkString("['", "' , '", "']") s""" angular.bootstrap("#complianceMode", ['complianceMode']); var scope = angular.element($$("#complianceModeController")).scope(); scope.$$apply(function(){ - scope.init("${complianceMode}", ${frequency}, ${overrides}, ${globalRun} ,${callback.toJsCmd}, "${S.contextPath}"); + scope.init(${toJs(complianceMode)}, ${toJs(globalMode)}, ${isNodePage} ,${callback.toJsCmd}, "${S.contextPath}", ${allModes}); } ); """ }) match { case eb:EmptyBox => - val e = eb ?~! "Error when retrieving agent schedule from the database" + val e = eb ?~! "Error when retrieving compliance mode from the database" logger.error(e.messageChain) e.rootExceptionCause.foreach { ex => logger.error(s"Root exception was: ${ex}") } - ( "#complianceMode" #> "Error when retrieving agent schedule from the database. Please, contact an admin or try again later" ) + ( "#complianceMode" #> "Error when retrieving compliance mode from the database. Please, contact an admin or try again later" ) case Full(initScheduleParam) => ( "#complianceMode *+" #> Script(OnLoad(JsRaw(initScheduleParam)) & Noop) ) } - transform(agentScheduleTemplate); + transform(complianceModeTemplate); } } diff --git a/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala b/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala index 7eaffd5281..5e6676f947 100644 --- a/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala +++ b/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala @@ -62,6 +62,11 @@ import com.normation.plugins.SnippetExtensionKey import com.normation.plugins.SpringExtendableSnippet import com.normation.rudder.reports.HeartbeatConfiguration import com.normation.rudder.web.model.JsNodeId +import com.normation.rudder.reports.ComplianceMode +import com.normation.rudder.reports.ComplianceMode +import com.normation.rudder.reports.ComplianceModeName +import com.normation.rudder.reports.NodeComplianceMode +import com.normation.rudder.reports.GlobalComplianceMode object ShowNodeDetailsFromNode { @@ -93,32 +98,34 @@ class ShowNodeDetailsFromNode( def extendsAt = SnippetExtensionKey(classOf[ShowNodeDetailsFromNode].getSimpleName) - //val nodeInfo = nodeInfoService.getNodeInfo(nodeId) + def complianceModeEditForm = { + val (globalMode, nodeMode) = { + val modes = getHeartBeat + (modes.map(_._1),modes.map(_._2)) + } - def complianceModeEditForm = new ComplianceModeEditForm( - () => getHeartBeat + new ComplianceModeEditForm( + nodeMode , saveHeart , () => Unit - , () => Some(configService.rudder_compliance_heartbeatPeriod) + , globalMode ) - - def getHeartBeat : Box[(String,Int, Boolean)] = { + } + def getHeartBeat : Box[(GlobalComplianceMode,NodeComplianceMode)] = { for { - complianceMode <- configService.rudder_compliance_mode_name - gHeartbeat <- configService.rudder_compliance_heartbeatPeriod + globalMode <- configService.rudder_compliance_mode() nodeInfo <- nodeInfoService.getNodeInfo(nodeId) } yield { // If heartbeat is not overriden, we revert to the default one - val defaultHeartBeat = HeartbeatConfiguration(false, gHeartbeat) - + val defaultHeartBeat = HeartbeatConfiguration(false, globalMode.heartbeatPeriod) val hbConf = nodeInfo.nodeReportingConfiguration.heartbeatConfiguration.getOrElse(defaultHeartBeat) - (complianceMode,hbConf.heartbeatPeriod,hbConf.overrides) + val nodeMode = NodeComplianceMode(globalMode.mode,hbConf.heartbeatPeriod,hbConf.overrides) + (globalMode,nodeMode) } } - - def saveHeart(complianceMode : String, frequency: Int, overrides : Boolean) : Box[Unit] = { - val heartbeatConfiguration = HeartbeatConfiguration(overrides, frequency) + def saveHeart(complianceMode : NodeComplianceMode) : Box[Unit] = { + val heartbeatConfiguration = HeartbeatConfiguration(complianceMode.overrideGlobal, complianceMode.heartbeatPeriod) val modId = ModificationId(uuidGen.newUuid) for { result <- nodeRepo.updateNodeHeartbeat(nodeId, heartbeatConfiguration, modId, CurrentUser.getActor, None) @@ -127,8 +134,6 @@ class ShowNodeDetailsFromNode( } } - - def agentScheduleEditForm = new AgentScheduleEditForm( () => getSchedule , saveSchedule @@ -231,7 +236,6 @@ class ShowNodeDetailsFromNode( ).apply(serverDetailsTemplate) } - /** * Javascript to initialize a tree. * htmlId is the id of the div enclosing tree datas diff --git a/rudder-web/src/main/scala/com/normation/rudder/web/snippet/administration/PropertiesManagement.scala b/rudder-web/src/main/scala/com/normation/rudder/web/snippet/administration/PropertiesManagement.scala index 23689dc75c..ddaaa356df 100644 --- a/rudder-web/src/main/scala/com/normation/rudder/web/snippet/administration/PropertiesManagement.scala +++ b/rudder-web/src/main/scala/com/normation/rudder/web/snippet/administration/PropertiesManagement.scala @@ -57,7 +57,7 @@ import com.normation.rudder.web.components.ComplianceModeEditForm import com.normation.rudder.reports.SyslogUDP import com.normation.rudder.reports.SyslogTCP import com.normation.rudder.reports.SyslogProtocol - +import com.normation.rudder.reports.GlobalComplianceMode /** * This class manage the displaying of user configured properties. @@ -89,10 +89,8 @@ class PropertiesManagement extends DispatchSnippet with Loggable { case "networkProtocolSection" => networkProtocolSection } - def changeMessageConfiguration = { xml : NodeSeq => - // initial values var initEnabled = configService.rudder_ui_changeMessage_enabled var initMandatory = configService.rudder_ui_changeMessage_mandatory @@ -144,7 +142,6 @@ class PropertiesManagement extends DispatchSnippet with Loggable { ) } - // Rendering ( "#configurationRepoPath" #> RudderConfig.RUDDER_DIR_GITROOT & "#enabled" #> { @@ -192,7 +189,6 @@ class PropertiesManagement extends DispatchSnippet with Loggable { initExplanation match { case Full(value) => - SHtml.ajaxText( value , (s : String) => { explanation = s; check() } @@ -258,7 +254,6 @@ class PropertiesManagement extends DispatchSnippet with Loggable { var selfVal = initSelfVal.getOrElse(false) var selfDep = initSelfDep.getOrElse(false) - def submit = { configService.set_rudder_workflow_enabled(enabled).foreach(updateOk => initEnabled = Full(enabled)) configService.set_rudder_workflow_self_validation(selfVal).foreach(updateOk => initSelfVal = Full(selfVal)) @@ -374,12 +369,10 @@ class PropertiesManagement extends DispatchSnippet with Loggable { //convention: we negate on server i/o, not anywhere else var initNoSkipIdentify = configService.cfengine_server_skipidentify.map( !_ ) - // form values var denyBadClocks = initDenyBadClocks.getOrElse(false) var noSkipIdentify = initNoSkipIdentify.getOrElse(false) - def submit = { configService.set_cfengine_server_denybadclocks(denyBadClocks).foreach(updateOk => initDenyBadClocks = Full(denyBadClocks)) configService.set_cfengine_server_skipidentify(!noSkipIdentify).foreach(updateOk => initNoSkipIdentify = Full(noSkipIdentify)) @@ -428,7 +421,6 @@ class PropertiesManagement extends DispatchSnippet with Loggable { to within an hour. Disabling this will bypass this check, but may open a window for replay attacks. - case _ => NodeSeq.Empty } } & @@ -536,12 +528,17 @@ class PropertiesManagement extends DispatchSnippet with Loggable { , () => startNewPolicyGeneration ) - val complianceModeEditForm = new ComplianceModeEditForm( - () => configService.rudder_compliance_mode().map(a => (a._1,a._2,true)) - , (complianceMode,heartbeatPeriod,_) => { - configService.set_rudder_compliance_mode(complianceMode,heartbeatPeriod,CurrentUser.getActor,genericReasonMessage)} - , () => startNewPolicyGeneration - ) + val complianceModeEditForm = { + val globalMode = configService.rudder_compliance_mode() + new ComplianceModeEditForm[GlobalComplianceMode]( + globalMode + , (complianceMode) => { + configService.set_rudder_compliance_mode(complianceMode,CurrentUser.getActor,genericReasonMessage) + } + , () => startNewPolicyGeneration + , globalMode + ) + } def getSchedule() : Box[AgentRunInterval] = { for { @@ -576,19 +573,16 @@ class PropertiesManagement extends DispatchSnippet with Loggable { def cfagentScheduleConfiguration = agentScheduleEditForm.cfagentScheduleConfiguration def complianceModeConfiguration = complianceModeEditForm.complianceModeConfiguration - def cfengineGlobalProps = { xml : NodeSeq => // initial values, updated on successful submit var initModifiedFilesTtl = configService.cfengine_modified_files_ttl var initCfengineOutputsTtl = configService.cfengine_outputs_ttl - // form values var modifiedFilesTtl = initModifiedFilesTtl.getOrElse(30).toString var cfengineOutputsTtl = initCfengineOutputsTtl.getOrElse(7).toString - def submit = { // first, check if the content are effectively Int try { @@ -740,5 +734,3 @@ class PropertiesManagement extends DispatchSnippet with Loggable { } ) apply (xml ++ Script(Run("correctButtons();"))) } } - - diff --git a/rudder-web/src/main/webapp/javascript/rudder/angular/complianceMode.js b/rudder-web/src/main/webapp/javascript/rudder/angular/complianceMode.js index 2c3f55359f..9ab66f6e0b 100644 --- a/rudder-web/src/main/webapp/javascript/rudder/angular/complianceMode.js +++ b/rudder-web/src/main/webapp/javascript/rudder/angular/complianceMode.js @@ -51,7 +51,7 @@ function updateAgentRun (run) { var complianceModeModule = angular.module("complianceMode", ['ngAnimate']) complianceModeModule.controller("complianceModeController", function($scope) { - $scope.complianceMode = { name : "full-compliance", heartbeatPeriod : 1, overrides : true}; + $scope.complianceMode = { name : "full-compliance", heartbeatPeriod : 1}; $scope.globalValue $scope.agentRun = 5; if (currentAgentRun !== undefined) { @@ -62,17 +62,23 @@ complianceModeModule.controller("complianceModeController", function($scope) { $scope.savedValue; $scope.contextPath; - $scope.init = function(complianceMode, heartbeatFreq,overrides, globalValue, callback, contextPath) { - $scope.complianceMode.name=complianceMode; - $scope.complianceMode.heartbeatPeriod=heartbeatFreq; - $scope.complianceMode.overrides=overrides; + $scope.init = function(complianceMode, globalValue, isNodePage, callback, contextPath, allModes) { + $scope.complianceMode=complianceMode; $scope.globalValue = globalValue; - $scope.isNodePage = globalValue !== undefined + $scope.isNodePage = isNodePage; $scope.callback=callback; $scope.contextPath=contextPath; $scope.savedValue = angular.copy($scope.complianceMode) } + + $scope.disableHeartbeat = function(){ + if ($scope.isNodePage) { + return false; + } else { + return $scope.complianceMode.overrides; + } + } $scope.onChange = function() { $("#complianceModeMessage").empty(); diff --git a/rudder-web/src/main/webapp/templates-hidden/components/ComponentComplianceMode.html b/rudder-web/src/main/webapp/templates-hidden/components/ComponentComplianceMode.html index 82824e39f8..e68fc6c64a 100644 --- a/rudder-web/src/main/webapp/templates-hidden/components/ComponentComplianceMode.html +++ b/rudder-web/src/main/webapp/templates-hidden/components/ComponentComplianceMode.html @@ -12,7 +12,11 @@ network traffic, but provides more precise reporting and may be necessary to prove compliance in your organization.
In Changes only mode, reports will only be sent when the agent makes a change or an error occurs on a node (these are 'repair' or 'error' reports). This mode saves a lot of log space and bandwidth, but leads to some assumptions - about actual configuration status in reporting. + about actual configuration status in reporting.
+ In Disabled mode, no reports will be sent, and rudder-agent will not re-configure the local syslog to send reports. + This mode uses no log space or bandwidth, but will also not allow you to check if your configuration policy + is successfully applied. We do not recommend using this mode except for setups where you have another + feedback mechanism in place. @@ -31,11 +35,17 @@ Changes only + +
+
-
+
Agent run heartbeat
@@ -52,8 +62,8 @@ (no errors and no repairs). This frequency can be changed to send a heartbeat only every N runs.
This setting is defined as a default for all nodes in the global Settings.
- The current global setting is to run every {{globalValue}} runs, - (so every {{globalValue * agentRun}} minutes).
+ The current global setting is to run every {{globalValue.heartbeatPeriod}} runs, + (so every {{globalValue.heartbeatPeriod * agentRun}} minutes).
You may override this global setting just for this node below:
@@ -69,7 +79,7 @@
- +