Skip to content

Commit

Permalink
Fixes #20851: Regroup report with their values, not with the expanded…
Browse files Browse the repository at this point in the history
… value
  • Loading branch information
VinceMacBuche committed Mar 2, 2022
1 parent c2c7fb7 commit 5c99638
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ final case class BlockStatusReport (
}
final case class ValueStatusReport (
componentName : String
, unexpanded : String
//only one ComponentValueStatusReport by valuex.
, componentValues : List[ComponentValueStatusReport]
) extends ComponentStatusReport {
Expand Down Expand Up @@ -379,13 +380,18 @@ object ComponentStatusReport extends Loggable {
components.groupBy( _.componentName).flatMap { case (cptName, reports) =>

val valueComponents = reports.collect{ case c : ValueStatusReport => c }.toList match {
case Nil => None
case Nil => Nil
case r =>
val newValues = ComponentValueStatusReport.merge(r.flatMap( _.componentValues))
Some(ValueStatusReport(cptName, newValues))
r.groupBy(_.unexpanded).toList.map {
case (unexpanded, r) =>

val newValues = ComponentValueStatusReport.merge(r.flatMap( _.componentValues))
ValueStatusReport(cptName, unexpanded, newValues)

}
}
val groupComponent= reports.collect{ case c : BlockStatusReport => c }.toList match {
case Nil => None
case Nil => Nil
case r =>
import ReportingLogic._
val reportingLogic = r.map(_.reportingLogic).reduce(
Expand All @@ -396,18 +402,13 @@ object ComponentStatusReport extends Loggable {
case (FocusReport(a), _) => FocusReport(a)
}
)
Some(BlockStatusReport(cptName, reportingLogic, ComponentStatusReport.merge(r.flatMap(_.subComponents)).toList))
BlockStatusReport(cptName, reportingLogic, ComponentStatusReport.merge(r.flatMap(_.subComponents)).toList) :: Nil
}

(valueComponents,groupComponent) match {
case (None , None ) => Nil
case (Some(v) , None ) => (cptName, v) :: Nil
case (None , Some(v) ) => (cptName, v) :: Nil
case (Some(value), Some(group)) => (cptName, group.copy(subComponents = value :: group.subComponents)) :: Nil
}
groupComponent ::: valueComponents

}
}.values.toList
}.toList
}

/**
Expand Down Expand Up @@ -439,14 +440,14 @@ object ComponentValueStatusReport extends Loggable {
* them by component *unexpanded* value
*/
def merge(values: Iterable[ComponentValueStatusReport]): List[ ComponentValueStatusReport] = {
val pairs = values.groupBy(_.unexpandedComponentValue).map { case (unexpanded, values) =>
val pairs = values.toList /*groupBy(_.unexpandedComponentValue).map { case (unexpanded, values) =>
//the unexpanded value should be the same on all values.
//if not, report an error for devs
ComponentValueStatusReport(unexpanded, unexpanded, values.toList.flatMap(_.messages))
}
}*/
pairs.toList
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,8 @@ object RuleExpectedReportBuilder extends Loggable {
val initPath = technique.rootSection.name :: Nil
val allComponents = technique.rootSection.children.collect{case c : SectionSpec => c }.flatMap(c => sectionToExpectedReports(initPath)(c)).toList

logger.warn(allComponents)

if(allComponents.isEmpty) {
//that log is outputed one time for each directive for each node using a technique, it's far too
//verbose on debug.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,17 @@ import com.normation.rudder.domain.logger.ComplianceDebugLogger._
import com.normation.rudder.domain.logger.TimingDebugLogger
import com.normation.inventory.domain.NodeId
import com.normation.rudder.domain.policies.DirectiveId
import com.normation.rudder.domain.policies.DirectiveUid
import com.normation.rudder.domain.reports._
import com.normation.rudder.reports._
import com.normation.rudder.reports.execution.AgentRunId

import net.liftweb.common.Loggable

import java.util.regex.Pattern
import com.normation.rudder.domain.policies.PolicyMode
import com.normation.rudder.domain.reports.ReportType.BadPolicyMode
import com.normation.rudder.reports.execution.AgentRunWithNodeConfig
import com.normation.rudder.domain.policies.RuleId

import org.apache.commons.lang3.StringUtils

import scala.annotation.tailrec
Expand Down Expand Up @@ -886,7 +885,7 @@ final case class ContextForNoAnswer(

val reports = reportsForThatNodeRule.groupBy(x => x.directiveId )

val expectedComponents: Map[(DirectiveId, List[EffectiveExpectedComponent]), (PolicyMode, ReportType)] = (for {
val expectedComponentstmp: List[((DirectiveId, List[EffectiveExpectedComponent]), (PolicyMode, ReportType))] = (for {
directive <- directives
policyMode = PolicyMode.directivePolicyMode(
modes.globalPolicyMode
Expand All @@ -899,16 +898,19 @@ final case class ContextForNoAnswer(
// full compliance and "success" when on changes only - but that success
// depends upon the policy mode
missingReportStatus = missingReportType(modes.globalComplianceMode, policyMode)

_ = if (directive.directiveId == DirectiveId(DirectiveUid("5e5d1590-ef4a-4bf7-96ef-47ebec682a3c") )) { directive.components.foreach(c => logger.warn(c)) } else { () }
component <- directive.components

} yield {

((directive.directiveId, getExpectedComponents(component)), (policyMode, missingReportStatus))
}).toMap
})
val t2 = System.nanoTime
timer.u1 += t2-t1

expectedComponentstmp.filter(_._1._1 == DirectiveId(DirectiveUid("5e5d1590-ef4a-4bf7-96ef-47ebec682a3c"))).map(_._1._2).foreach(_.foreach( c => logger.error(c)))

val expectedComponents = expectedComponentstmp.toMap
/*
* now we have three cases:
* - expected component without reports => missing (modulo changes only interpretation)
Expand Down Expand Up @@ -946,6 +948,7 @@ final case class ContextForNoAnswer(
// HEre reports need to be filtered to only match values that are expected for the Value that is at the end of the component path
// and its component nae
// The component used to analyse reports is the component at the top of our structure that we recreate the whole tree
//logger.info(c.)
checkExpectedComponentWithReports(c.component, filteredReports, missingReportStatus, policyMode, unexpectedInterpretation)
}
// Merge all components together
Expand Down Expand Up @@ -1120,7 +1123,7 @@ final case class ContextForNoAnswer(
, mergeInfo.configId
, seq.groupBy(_.directiveId).map{ case (directiveId, reportsByDirectives) =>
(directiveId, DirectiveStatusReport(directiveId, reportsByDirectives.groupBy(_.component).toList.map { case (component, reportsByComponents) =>
ValueStatusReport(component, reportsByComponents.groupBy(_.keyValue).toList.map { case (keyValue, reportsByComponent) =>
ValueStatusReport(component, component, reportsByComponents.groupBy(_.keyValue).toList.map { case (keyValue, reportsByComponent) =>
ComponentValueStatusReport(keyValue, keyValue, reportsByComponent.map(r => MessageStatusReport(ReportType.Unexpected, r.message)).toList)
})
})
Expand All @@ -1135,7 +1138,7 @@ final case class ContextForNoAnswer(
private[this] def buildUnexpectedDirectives(reports: Seq[Reports]): Seq[DirectiveStatusReport] = {
reports.map { r =>
DirectiveStatusReport(r.directiveId,
ValueStatusReport(r.component, ComponentValueStatusReport(r.keyValue, r.keyValue, MessageStatusReport(ReportType.Unexpected, r.message) :: Nil) :: Nil
ValueStatusReport(r.component, r.component, ComponentValueStatusReport(r.keyValue, r.keyValue, MessageStatusReport(ReportType.Unexpected, r.message) :: Nil) :: Nil
) :: Nil)

}
Expand All @@ -1144,7 +1147,7 @@ final case class ContextForNoAnswer(
private[reports] def componentExpectedReportToStatusReport (reportType: ReportType, c : ComponentExpectedReport) : ComponentStatusReport = {
c match {
case c : ValueExpectedReport =>
ValueStatusReport(c.componentName, c.componentsValues.map {
ValueStatusReport(c.componentName,c.componentName, c.componentsValues.map {
case ExpectedValueId(v,_) => (v,v)
case ExpectedValueMatch(v,u) => (v,u)
}.map { case(v,u) =>
Expand Down Expand Up @@ -1348,12 +1351,33 @@ final case class ContextForNoAnswer(
}
}

val expectedNumber = Math.max(ok.size, 1)
val resOk = buildComponentValueStatus(expectedValueId, ok, componentGotAtLeastOneReport, expectedNumber, noAnswerType, policyMode)
val resKo = unexpected.map(r => ComponentValueStatusReport(r.component, r.keyValue, MessageStatusReport(ReportType.Unexpected, r.message) :: Nil))

val okRes = ok.groupBy(_.component).toList.map { case (component, r) =>
val cv = r.groupBy(_.keyValue).toList.map { case (key, r) =>
ComponentValueStatusReport(key, expectedValueId.value, r.map(_.toMessageStatusReport(policyMode)))
}
ValueStatusReport(component, expectedComponent.componentName, cv)
}


val missingRes = if (ok.isEmpty) {
ValueStatusReport(expectedComponent.componentName, expectedComponent.componentName, ComponentValueStatusReport( expectedValueId.value, expectedValueId.value, MessageStatusReport(noAnswerType, "Missing report") :: Nil) :: Nil) :: Nil
} else {
Nil
}

val unexpectedRes = unexpected.groupBy(_.component).toList.map { case (component, r) =>
val cv = r.groupBy(_.keyValue).toList.map { case (key, r) =>
ComponentValueStatusReport(key, expectedValueId.value, r.map(r => MessageStatusReport(ReportType.Unexpected, r.message)))
}
ValueStatusReport(component, expectedComponent.componentName, cv)
}



val koRes = missingRes ::: unexpectedRes
// we still attach the unexpected with that component since they have its reportId
(ValueStatusReport(expectedComponent.componentName, resOk :: resKo) :: acc, left)
( okRes ::: koRes ::: acc, left)
}

// 2. now the complicated case - do what we used to do for expected report without a reportId
Expand Down Expand Up @@ -1414,6 +1438,7 @@ final case class ContextForNoAnswer(
} else {
ValueStatusReport(
expectedComponent.componentName
, expectedComponent.componentName
, ComponentValueStatusReport.merge(pairedReportStatus)
) :: matched
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ class StatusReportTest extends Specification {
case n :: r :: _ :: d :: c :: v :: uv :: t :: m :: Nil =>
Some(RuleNodeStatusReport(n, r, None, None, Map(DirectiveId(DirectiveUid(d)) ->
DirectiveStatusReport(d, List(
ValueStatusReport(c, List(
ValueStatusReport(c,c, List(
ComponentValueStatusReport(v, uv, List(
MessageStatusReport(toRT(t), ?(m))
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ final case class BlockComplianceLine (

final case class ValueComplianceLine (
component : String
, unexpanded : String
, compliance : ComplianceLevel
, details : JsTableData[ComponentValueComplianceLine]
, noExpand : Boolean
Expand All @@ -287,6 +288,7 @@ final case class ValueComplianceLine (
val json = {
JsObj (
( "component" -> escapeHTML(component) )
, ( "unexpanded" -> escapeHTML(unexpanded) )
, ( "compliance" -> jsCompliance(compliance) )
, ( "compliancePercent" -> compliance.computePercent().compliance)
, ( "details" -> details.json )
Expand All @@ -310,6 +312,7 @@ final case class ValueComplianceLine (
*/
final case class ComponentValueComplianceLine (
value : String
, unexpandedValue : String
, messages : List[(String, String)]
, compliance : ComplianceLevel
, status : String
Expand All @@ -319,6 +322,7 @@ final case class ComponentValueComplianceLine (
val json = {
JsObj (
( "value" -> escapeHTML(value) )
, ( "unexpanded" -> escapeHTML(unexpandedValue) )
, ( "status" -> status )
, ( "statusClass" -> statusClass )
, ( "messages" -> JsArray(messages.map{ case(s, m) => JsObj(("status" -> s), ("value" -> escapeHTML(m)))}))
Expand Down Expand Up @@ -543,6 +547,7 @@ object ComplianceData extends Loggable {

ValueComplianceLine(
component.componentName
, component.unexpanded
, component.compliance
, values
, noExpand
Expand All @@ -563,11 +568,13 @@ object ComplianceData extends Loggable {
} yield {
val severity = ReportType.getWorseType(value.messages.map( _.reportType)).severity
val status = getDisplayStatusFromSeverity(severity)
val key = value.unexpandedComponentValue
val key = value.componentValue
println(key)
val messages = value.messages.map(x => (x.reportType.severity, x.message.getOrElse("")))

ComponentValueComplianceLine(
key
, value.unexpandedComponentValue
, messages
, value.compliance
, status
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,10 @@ function createComponentTable(isTopLevel, isNodeView, contextPath) {
} else {
$(nTd).addClass("noExpand");
}
if( oData.unexpanded !== undefined && oData["unexpanded"] !== sData) {
var elem = $("<i class=\"fa fa-question-circle icon-info\" title=\"original value is "+ oData["unexpanded"]+"\"></i>")
$(nTd).append(elem);
}
}
} , {
"sWidth": complianceWidth
Expand Down Expand Up @@ -983,6 +987,12 @@ function createNodeComponentValueTable(contextPath) {
"sWidth": "20%"
, "mDataProp": "value"
, "sTitle": "Value"
, "fnCreatedCell" : function (nTd, sData, oData, iRow, iCol) {
if(oData["unexpanded"] !== sData) {
var elem = $("<i class=\"fa fa-question-circle icon-info\" title=\"original value is "+ oData["unexpanded"]+"\"></i>")
$(nTd).append(elem);
}
}
} , {
"sWidth": "62.4%"
, "mDataProp": "messages"
Expand Down Expand Up @@ -1044,6 +1054,12 @@ function createRuleComponentValueTable (contextPath) {
"sWidth": componentSize
, "mDataProp": "value"
, "sTitle": "Value"
, "fnCreatedCell" : function (nTd, sData, oData, iRow, iCol) {
if(oData["unexpanded"] !== sData) {
var elem = $("<i class=\"fa fa-question-circle icon-info\" title=\"original value is "+ oData["unexpanded"]+"\"></i>")
$(nTd).append(elem);
}
}
} , {
"sWidth": complianceWidth
, "mDataProp": "compliancePercent"
Expand Down

0 comments on commit 5c99638

Please sign in to comment.