Skip to content

Commit

Permalink
Fixes #7375: Add an option in the web interface to completely disable…
Browse files Browse the repository at this point in the history
… reporting
  • Loading branch information
VinceMacBuche committed Nov 10, 2015
1 parent 7bd6fe5 commit 3199e0e
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 226 deletions.
Expand Up @@ -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 {

Expand Down Expand Up @@ -164,8 +164,11 @@ 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 = s"Forbiden value, only 'full-compliance' and 'changes-only' are authorized"
))
)
, default=Some("full-compliance")
Expand Down
Expand Up @@ -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.
Expand All @@ -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.

Expand Down Expand Up @@ -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 {
val h = c.mode match {
case FullCompliance => ""
case ChangesOnly(_) => s", hearbeat every ${r.heartbeatPeriod} run(s)"
case ChangesOnly => s", hearbeat every ${r.heartbeatPeriod} run(s)"
}
s"run interval: ${r.interval.toStandardMinutes.getMinutes} min${h}"
}
Expand All @@ -135,7 +133,4 @@ object ComplianceDebugLogger extends Logger {
}
}


}


Expand Up @@ -44,47 +44,89 @@ 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 {
final case object FullCompliance extends ComplianceModeName {
val name = "full-compliance"
}
final case class ChangesOnly (
heartbeatPeriod : Int
)extends ComplianceMode {
val name = ChangesOnly.name
}

object ChangesOnly {
final case object ChangesOnly extends ComplianceModeName {
val name = "changes-only"
}

final case object ReportDisabled extends ComplianceModeName {
val name = "report-disabled"
}

object ComplianceModeName {
val allModes : List[ComplianceModeName] = FullCompliance :: ChangesOnly :: ReportDisabled :: Nil

def apply (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)
}
}
}
case class ComplianceMode (
mode: ComplianceModeName
, heartbeatPeriod : Int
, overrideGlobal : Boolean
) {
val name = mode.name
}

/*
*
*
* case class ComplianceMode {
def mode: ComplianceModeName
def heartbeatPeriod : Int
def overrideGlobal : Boolean
val name = mode.name
}
*
case class GlobalComplianceMode (
mode : ComplianceModeName
, heartbeatPeriod : Int
) extends ComplianceMode {
override val overrideGlobal = true
}
case class NodeComplianceMode (
mode : ComplianceModeName
, heartbeatPeriod : Int
) extends ComplianceMode {
override val overrideGlobal = true
}
*/
trait ComplianceModeService {
def getComplianceMode : Box[ComplianceMode]
}

class ComplianceModeServiceImpl (
readComplianceMode : () => Box[String]
, readHeartbeatFreq : () => Box[Int]
, readOverride : () => Box[Boolean]
) 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
}

for {
modeName <- readComplianceMode()
mode <- ComplianceModeName(modeName)
heartbeat <- readHeartbeatFreq()
overrideGlobal <- readOverride()
} yield {
ComplianceMode(
mode
, heartbeat
, overrideGlobal
)
}
}
}
Expand Up @@ -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 {
Expand Down Expand Up @@ -151,4 +157,3 @@ object SyslogTCP extends SyslogProtocol {
object SyslogUDP extends SyslogProtocol {
val value = "UDP"
}

Expand Up @@ -71,7 +71,6 @@ trait SystemVariableService {
) : Box[Map[String, Variable]]
}


final case class RudderServerRole(
val name : String
, val configValue: String
Expand All @@ -82,7 +81,6 @@ final case class ResolvedRudderServerRole(
, val configValue: Option[Iterable[String]]
)


class SystemVariableServiceImpl(
licenseRepository: LicenseRepository
, systemVariableSpecService: SystemVariableSpecService
Expand Down Expand Up @@ -295,16 +293,16 @@ class SystemVariableServiceImpl(
// A policy server is always sending heartbeat
1
} else {
globalComplianceMode match {
globalComplianceMode.mode match {
case FullCompliance =>
1
case ChangesOnly(globalFrequency) =>
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
}
}
}
Expand Down Expand Up @@ -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
Expand Down
Expand Up @@ -161,7 +161,6 @@ case class VersionNotFound(
, lastRunConfigId: Option[NodeConfigId]
) extends ErrorNoConfigData


/*
* No report of interest (either none, or
* some but too old for our situation)
Expand All @@ -170,16 +169,13 @@ case class NoReportInInterval(
expectedConfigId: NodeConfigIdInfo
) extends NoReport



case class Pending(
expectedConfigId : NodeConfigIdInfo
, optLastRun : Option[(DateTime, NodeConfigIdInfo)]
, expirationDateTime : DateTime
, 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,
Expand All @@ -193,7 +189,6 @@ case class UnexpectedVersion(
, expectedExpiration: DateTime
) extends Unexpected with LastRunAvailable


case class ComputeCompliance(
lastRunDateTime : DateTime
, lastRunConfigId : NodeConfigIdInfo
Expand All @@ -202,9 +197,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 ?
Expand Down Expand Up @@ -254,7 +246,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.
Expand All @@ -278,9 +269,9 @@ 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
}

/*
Expand All @@ -293,8 +284,8 @@ 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)
Expand Down Expand Up @@ -480,7 +471,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] = {
Expand Down Expand Up @@ -573,13 +563,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
Expand Down Expand Up @@ -617,7 +604,6 @@ object ExecutionBatch extends Loggable {
, missingReportStatus : ReportType
): Seq[RuleNodeStatusReport] = {


val complianceForRun: Map[SerialedRuleId, RuleNodeStatusReport] = (for {
( SerialedRuleId(ruleId, serial)
, expectedReport ) <- expectedReportsForRun
Expand Down Expand Up @@ -722,7 +708,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) {
Expand All @@ -731,7 +716,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(
Expand Down Expand Up @@ -789,7 +773,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,
Expand Down Expand Up @@ -962,7 +945,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.
Expand Down

0 comments on commit 3199e0e

Please sign in to comment.