Skip to content

Commit

Permalink
[DROOLS-7578] Evaluate Impact analysis for ansible integration rules (#…
Browse files Browse the repository at this point in the history
…94)

* [DROOLS-7578] Evaluate Impact analysis for ansible integration rules
- Quick prototype. Works for a basic example : ParserTest
- Replace jboss repo with apache repo for snapshot

* build apache/incubator-kie-drools rather than kiegroup
  • Loading branch information
tkobayas authored Dec 13, 2023
1 parent 855268f commit 26ac388
Show file tree
Hide file tree
Showing 14 changed files with 540 additions and 12 deletions.
4 changes: 2 additions & 2 deletions .ci/project-dependencies.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version: "2.1"
dependencies:
- project: kiegroup/drools
- project: apache/incubator-kie-drools
mapping:
dependant:
default:
Expand All @@ -10,7 +10,7 @@ dependencies:

- project: kiegroup/drools-ansible-rulebook-integration
dependencies:
- project: kiegroup/drools
- project: apache/incubator-kie-drools
mapping:
dependencies:
default:
Expand Down
2 changes: 1 addition & 1 deletion .ci/pull-request-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: "2.1"
dependencies: ./project-dependencies.yaml

build:
- project: kiegroup/drools
- project: apache/incubator-kie-drools
build-command:
current: mvn --batch-mode --update-snapshots install -Dquickly

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install Drools Snapshot
uses: actions/checkout@v3
with:
repository: kiegroup/drools
repository: apache/incubator-kie-drools
path: drools

- name: Build Drools Snapshot with Maven
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Install Drools Snapshot
uses: actions/checkout@v3
with:
repository: kiegroup/drools
repository: apache/incubator-kie-drools
path: drools

- name: Build Drools Snapshot with Maven
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public MultipleConditions(RuleGenerationContext ruleContext) {

protected abstract org.drools.model.Condition.Type getConditionType();

public List<Condition> getConditions() {
return conditions;
}

@Override
public ViewItem toPattern(RuleGenerationContext ruleContext) {
if (conditions.size() == 1) {
Expand Down Expand Up @@ -275,5 +279,9 @@ public PatternCondition negate(RuleGenerationContext ruleContext) {
public SingleCondition<P> addSingleCondition(PrototypeExpression left, Index.ConstraintType operator, PrototypeExpression right) {
return parent.addSingleCondition(left, operator, right);
}

public ParsedCondition getParsedCondition() {
return parsedCondition;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ private static void parseTimeOut(RuleGenerationContext ruleContext, MapCondition
}
}

private static Condition map2Ast(RuleGenerationContext ruleContext, MapCondition condition, AstCondition.MultipleConditions parent) {
public static Condition map2Ast(RuleGenerationContext ruleContext, MapCondition condition, AstCondition.MultipleConditions parent) {
assert(condition.getMap().size() == 1);
Map.Entry entry = condition.getMap().entrySet().iterator().next();
String expressionName = (String) entry.getKey();
Expand Down
52 changes: 52 additions & 0 deletions drools-ansible-rulebook-integration-visualization/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>drools-ansible-rulebook-integration</artifactId>
<groupId>org.drools</groupId>
<version>1.0.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>drools-ansible-rulebook-integration-visualization</artifactId>

<name>Drools :: Ansible Rulebook Integration :: Visualization</name>

<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-ansible-rulebook-integration-api</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-impact-analysis-parser</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-impact-analysis-graph-common</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-impact-analysis-graph-graphviz</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.drools.ansible.rulebook.integration.visualization.parser;

import java.util.List;

import org.drools.ansible.rulebook.integration.api.domain.RuleGenerationContext;
import org.drools.ansible.rulebook.integration.api.domain.conditions.AstCondition;
import org.drools.ansible.rulebook.integration.api.domain.conditions.Condition;
import org.drools.ansible.rulebook.integration.api.domain.conditions.MapCondition;
import org.drools.ansible.rulebook.integration.api.rulesmodel.ParsedCondition;
import org.drools.base.facttemplates.FactTemplateObjectType;
import org.drools.impact.analysis.model.left.Constraint;
import org.drools.impact.analysis.model.left.LeftHandSide;
import org.drools.impact.analysis.model.left.Pattern;
import org.drools.model.ConstraintOperator;
import org.drools.model.Index;
import org.drools.model.PrototypeExpression;

public class LhsParser {

private LhsParser() {
// intentionally left blank
}

public static void parse(Condition condition, LeftHandSide lhs) {
Pattern pattern = new Pattern(FactTemplateObjectType.class, true);
parseConditions(condition, pattern);
lhs.addPattern(pattern);
}

private static void parseConditions(Condition condition, Pattern pattern) {
if (condition instanceof MapCondition mapCondition) {
// Firstly, process the raw condition
RuleGenerationContext ruleContext = new RuleGenerationContext();
Condition astCondition = MapCondition.map2Ast(ruleContext, mapCondition, null);
parseConditions(astCondition, pattern);
} else if (condition instanceof AstCondition.MultipleConditions multipleConditions) {
// All and Any conditions
List<Condition> conditions = multipleConditions.getConditions();
conditions.forEach(c -> parseConditions(c, pattern));
} else if (condition instanceof AstCondition.SingleCondition singleCondition) {
// Single condition turns into a constraint
ParsedCondition parsedCondition = singleCondition.getParsedCondition();
PrototypeExpression left = parsedCondition.getLeft();
ConstraintOperator operator = parsedCondition.getOperator();
PrototypeExpression right = parsedCondition.getRight();
Constraint constraint = createConstraint(operator, left, right);
pattern.addConstraint(constraint);
pattern.addReactOn(constraint.getProperty());
} else {
throw new UnsupportedOperationException("Unsupported condition type: " + condition.getClass().getName());
}
}

private static Constraint createConstraint(ConstraintOperator operator, PrototypeExpression left, PrototypeExpression right) {
// quick implementation assuming that the right is always a fixed value
return new Constraint(convertConstraintOperator(operator), left.getIndexingKey().get(), ((PrototypeExpression.FixedValue) right).getValue());
}

private static Constraint.Type convertConstraintOperator(ConstraintOperator operator) {
if (operator instanceof Index.ConstraintType constraintType) {
switch (constraintType) {
case EQUAL:
return Constraint.Type.EQUAL;
case NOT_EQUAL:
return Constraint.Type.NOT_EQUAL;
case GREATER_THAN:
return Constraint.Type.GREATER_THAN;
case GREATER_OR_EQUAL:
return Constraint.Type.GREATER_OR_EQUAL;
case LESS_OR_EQUAL:
return Constraint.Type.LESS_OR_EQUAL;
case LESS_THAN:
return Constraint.Type.LESS_THAN;
default:
return Constraint.Type.UNKNOWN;
}
}
return Constraint.Type.UNKNOWN;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.drools.ansible.rulebook.integration.visualization.parser;

import java.util.List;
import java.util.Map;

import org.drools.ansible.rulebook.integration.api.domain.actions.MapAction;
import org.drools.base.facttemplates.FactTemplateObjectType;
import org.drools.impact.analysis.model.right.DeleteSpecificFactAction;
import org.drools.impact.analysis.model.right.InsertAction;
import org.drools.impact.analysis.model.right.InsertedProperty;
import org.drools.impact.analysis.model.right.RightHandSide;
import org.drools.impact.analysis.model.right.SpecificProperty;

public class RhsParser {

private RhsParser() {
// intentionally private
}

public static void parse(List<MapAction> mapActions, RightHandSide rhs) {
for (MapAction mapAction : mapActions) {
Map map = (Map) mapAction.get("Action");
String action = (String) map.get("action");
Map actionArgs = (Map) map.get("action_args");
switch (action) {
case "post_event":
addInsertAction((Map<String, String>) actionArgs.get("event"), rhs);
break;
case "set_fact":
addInsertAction((Map<String, String>) actionArgs.get("fact"), rhs);
break;
case "retract_fact":
addDeleteAction((Map<String, String>) actionArgs.get("fact"), rhs);
break;
default:
// ignore any other actions
}
}
}

private static void addInsertAction(Map<String, String> propertyMap, RightHandSide rhs) {
InsertAction action = new InsertAction(FactTemplateObjectType.class);
propertyMap.entrySet().forEach(entry -> {
InsertedProperty insertedProperty = new InsertedProperty(entry.getKey(), entry.getValue());
action.addInsertedProperty(insertedProperty);
});
rhs.addAction(action);
}

private static void addDeleteAction(Map<String, String> propertyMap, RightHandSide rhs) {
DeleteSpecificFactAction action = new DeleteSpecificFactAction(FactTemplateObjectType.class);
propertyMap.entrySet().forEach(entry -> {
SpecificProperty specificProperty = new SpecificProperty(entry.getKey(), entry.getValue());
action.addSpecificProperty(specificProperty);
});
rhs.addAction(action);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.drools.ansible.rulebook.integration.visualization.parser;

import java.util.ArrayList;
import java.util.List;

import org.drools.ansible.rulebook.integration.api.domain.RulesSet;
import org.drools.ansible.rulebook.integration.api.domain.conditions.ConditionParseUtil;
import org.drools.impact.analysis.model.AnalysisModel;
import org.drools.impact.analysis.model.Package;
import org.drools.impact.analysis.model.Rule;
import org.drools.impact.analysis.model.left.LeftHandSide;
import org.drools.impact.analysis.model.right.RightHandSide;
import org.drools.model.impl.RuleBuilder;

/**
* Parse drools-ansible RulesSet to drools-impact-analysis AnalysisModel
*/
public class RulesSetParser {

public static AnalysisModel parse(RulesSet rulesSet) {
AnalysisModel analysisModel = new AnalysisModel();
List<org.drools.impact.analysis.model.Rule> rules = new ArrayList<>();
rulesSet.getRules().forEach(ruleContainer -> {
rules.add(parseRule(ruleContainer.getRule()));
});
Package pkg = new Package(RuleBuilder.DEFAULT_PACKAGE, rules);
analysisModel.addPackage(pkg);
return analysisModel;
}

private static Rule parseRule(org.drools.ansible.rulebook.integration.api.domain.Rule ansibleRule) {
Rule analysisRule = new Rule(RuleBuilder.DEFAULT_PACKAGE, ansibleRule.getName(), null);
LhsParser.parse(ansibleRule.getCondition(), analysisRule.getLhs());
RhsParser.parse(ansibleRule.getActions(), analysisRule.getRhs());
return analysisRule;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Default logging detail level for all instances of SimpleLogger.
org.slf4j.simpleLogger.defaultLogLevel=info

# Logging detail level
org.slf4j.simpleLogger.log.org.drools.ansible.rulebook.integration=info
org.slf4j.simpleLogger.log.guru.nidi.graphviz=warn

# Set to true if you want the current date and time to be included in output messages.
# Default is false, and will output the number of milliseconds elapsed since startup.
org.slf4j.simpleLogger.showDateTime=true

# The date and time format to be used in the output messages.
# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
# If the format is not specified or is invalid, the default format is used.
# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z

# Set to true if you want to output the current thread name.
# Defaults to true.
org.slf4j.simpleLogger.showThreadName=true

# Log output
# Defaults to System.err
org.slf4j.simpleLogger.logFile=System.out
Loading

0 comments on commit 26ac388

Please sign in to comment.