I have modified a template rule to include rule execution interval. This will allow template based rules to have this parameter.
To test the modified template rule I have created a rule file that includes a template based rule that is using the medified template. The rule case class in in the top of the file and the template rule is included below. Plese see the code below (it is attached as a .txt file as well, the forum does not allow .rule attachements) :CrossVendorSnmpCommunitiesComparisonREI.txt
package com.indeni.server.rules.library.templatebased.crossvendorimport com.indeni.server.rules.RuleContext
import com.indeni.server.rules.library.{ConditionalRemediationSteps, SnapshotComparisonTemplateRule}
import com.indeni.time.TimeSpan/**
*
*/// Modified template based rule.
case class CrossVendorSnmpCommunitiesComparisonREI(context: RuleContext) extends SnapshotComparisonTemplateRuleREI(context,
ruleName = “cross_vendor_snmp_communities_comparisonREI”,
ruleFriendlyName = “Clustered Devices: SNMP community settings do not match across cluster members REI”,
ruleExecutionInterval = TimeSpan.fromMinutes(1),
ruleDescription = “Indeni will identify when two devices are part of a cluster and alert if the SNMP settings do not match.”,
metricName = “snmp-communities”,
isArray = true,
alertDescription = “Devices that are part of a cluster should have the same SNMP configuration. Review the differences below.”,
baseRemediationText = “Ensure all of the SNMP settings are configured correctly on all cluster members.”)(
ConditionalRemediationSteps.OS_NXOS ->
"""|
|1. Ensure all of the SNMPv2 communities are configured correctly on all cluster members by using the “show snmp” NX-OS command.
|2. Configure the same SNMPv2c communities by using the next command “snmp-server community name group { ro | rw }” across the peer Switches.
|3. For more information please review the next CISCO configuration guide:
|https://www.cisco.com/c/en/us/td/docs/switches/datacenter/sw/5_x/nx-os/system_management/configuration/guide/sm_nx_os_cg/sm_9snmp.html
""".stripMargin
)// Modified template
import com.indeni.data.conditions.{TagsStoreCondition, True}
import com.indeni.ruleengine.expressions.cluster.SelectClusterComparisonExpression
import com.indeni.ruleengine.expressions.conditions.{Equals, Not}
import com.indeni.ruleengine.expressions.core.{StatusTreeExpression, _}
import com.indeni.ruleengine.expressions.data.SelectTagsExpression
import com.indeni.server.metrics.DeviceStoreActor
import com.indeni.server.rules.{RuleContext, RuleMetadata, _}
import com.indeni.server.sensor.models.managementprocess.alerts.dto.AlertSeverity
import com.indeni.time.TimeSpan
import com.indeni.server.rules.library.{ConditionalRemediationSteps, PerDeviceRule, RuleHelper, SnapshotDiffExpression}class SnapshotComparisonTemplateRuleREI(context: RuleContext, ruleName: String, ruleFriendlyName: String,
ruleExecutionInterval: TimeSpan = TimeSpan.fromMinutes(1),
severity: AlertSeverity = AlertSeverity.ERROR,
ruleDescription: String, metricName: String, isArray: Boolean, applicableMetricTag: String = null, alertDescription: String,
alertItemsHeader: String = “Mismatching Cluster Members”, descriptionMetricTag: String = null, descriptionStringFormat: String = “”, baseRemediationText: String, metaCondition: TagsStoreCondition = True,
includeSnapshotDiff: Boolean = true)(vendorToRemediationText: (String, String)*)
extends PerDeviceRule with RuleHelper {override val metadata: RuleMetadata = RuleMetadata(ruleName, ruleFriendlyName, ruleDescription, severity)
override def expressionTree: StatusTreeExpression = {
val thisSnapshot = SelectClusterComparisonExpression.thisSnapshotExpression().mostRecent().noneable.withLazy val clusterSnapshot = SelectClusterComparisonExpression.clusterSnapshotExpression().mostRecent().noneable.withLazy val selectExpression = SelectClusterComparisonExpression(context.metaDao, DeviceStoreActor.TAG_DEVICE_ID, DeviceStoreActor.TAG_DEVICE_NAME, DeviceStoreActor.TAG_DEVICE_IP, "cluster-id", context.snapshotsDao, metricName) StatusTreeExpression( // Which objects to pull (normally, devices) SelectTagsExpression(context.metaDao, Set(DeviceKey), metaCondition), // What constitutes an issue if (applicableMetricTag != null) StatusTreeExpression( // The additional tags we care about (we"ll be including this in alert data) SelectTagsExpression(context.snapshotsDao, if (descriptionMetricTag == null) Set(applicableMetricTag) else Set(applicableMetricTag, descriptionMetricTag), withTagsCondition(metricName)), StatusTreeExpression( if (isArray) selectExpression.multi() else selectExpression.single(), // The condition which, if true, we have an issue. Checked against the time-series we"ve collected Not(Equals(thisSnapshot, clusterSnapshot)) // The Alert Item to add for this specific item ).withSecondaryInfo( scopableStringFormatExpression("${scope(\"" + applicableMetricTag + "\")}" + (if (descriptionMetricTag != null) " (${scope(\"" + descriptionMetricTag + "\")})" else "") + " on %s (%s)", SelectClusterComparisonExpression.clusterDeviceNameExpression(), SelectClusterComparisonExpression.clusterDeviceIpExpression()), if (includeSnapshotDiff) SnapshotDiffExpression(thisSnapshot, clusterSnapshot) else EMPTY_STRING, title = alertItemsHeader ).asCondition() ).withoutInfo().asCondition() else StatusTreeExpression( // The time-series we check the test condition against: if (isArray) selectExpression.multi() else selectExpression.single(), // The condition which, if true, we have an issue. Checked against the time-series we"ve collected Not(Equals(thisSnapshot, clusterSnapshot)) ).withSecondaryInfo( scopableStringFormatExpression("%s (%s)", SelectClusterComparisonExpression.clusterDeviceNameExpression(), SelectClusterComparisonExpression.clusterDeviceIpExpression()), if (includeSnapshotDiff) SnapshotDiffExpression(thisSnapshot, clusterSnapshot) else EMPTY_STRING, title = alertItemsHeader ).asCondition() // Details of the alert itself ).withRootInfo( getHeadline(), ConstantExpression(alertDescription), ConditionalRemediationSteps(baseRemediationText, vendorToRemediationText: _*) )
}
}
In the IntelliJ the code compiles without errors.
After loding it to the Indeni server on the KD Lab I have got the following error:
error_printout_from_KDL_for_rule_with_template_with_REI.txt
INFO [2017-09-27 11:07:31,966] com.indeni.server.rules.manager.factory.FileSystemRuleFactory: Loading rule from file "/usr/share/indeni/rules/CrossVendorSnmpCommunitiesComparisonREI.rule" ERROR [2017-09-27 11:07:32,650] com.indeni.server.rules.manager.factory.FileSystemRuleFactory: Failed to load rule from file "/usr/share/indeni/rules/CrossVendorSnmpCommunitiesComparisonREI.rule" ! com.indeni.server.rules.manager.factory.RuleCompilationException: Couldn"t compile rule code. Cause: Compiled rule "__wrapper$3227$6e8d7395959548c78a20fb2124988708.__wrapper$3227$6e8d7395959548c78a20fb2124988708$SnapshotComparisonTemplateRuleREI$2" constructor"s doesn"t have expected number of parameters ! Code: ! import com.indeni.server.rules.RuleContext ! import com.indeni.server.rules.library.{ConditionalRemediationSteps, SnapshotComparisonTemplateRule} ! import com.indeni.time.TimeSpan ! ! /** ! * ! */ ! ! // Modified template based rule. ! ! case class CrossVendorSnmpCommunitiesComparisonREI(context: RuleContext) extends SnapshotComparisonTemplateRuleREI(context,
The same error with the statement that the template rule constructor doen't have the expecter number of parameters is printed out even when I included the original unmodified template rule in the file.
Looks like the rule compiler is triing to complite the template rule a normal rule and not as a template class.
Is there a way to overcome this behaviuor?
What are other ways currently used to test modified template rules?