From 5cc6fc1a762c547f420ce281deac69f02f6c2b83 Mon Sep 17 00:00:00 2001 From: Guangrong Fu Date: Wed, 1 Dec 2021 14:22:37 +0800 Subject: [PATCH] Change rule retrieval from CBS to ConfigMap Issue-ID: HOLMES-488 Signed-off-by: Guangrong Fu Change-Id: I89f4d47b9b2e0f1c9c9d32083a146d54d0000c5d --- pom.xml | 4 +- rulemgt-frontend/pom.xml | 2 +- rulemgt-standalone/pom.xml | 2 +- rulemgt/pom.xml | 2 +- .../org/onap/holmes/rulemgt/RuleActiveApp.java | 17 +- .../rulemgt/dcae/ConfigFileScanningTask.java | 190 ++++++++++++++++ .../rulemgt/dcae/DcaeConfigurationPolling.java | 1 + .../rulemgt/dcae/ConfigFileScanningTaskTest.java | 241 +++++++++++++++++++++ ...179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl | 91 ++++++++ ...2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl | 88 ++++++++ ...-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl | 90 ++++++++ rulemgt/src/test/resources/index-add.json | 6 + rulemgt/src/test/resources/index-empty.json | 1 + rulemgt/src/test/resources/index-rule-changed.json | 6 + .../src/test/resources/index-rule-spaces-test.json | 6 + 15 files changed, 731 insertions(+), 16 deletions(-) create mode 100644 rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java create mode 100644 rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java create mode 100644 rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl create mode 100644 rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl create mode 100644 rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl create mode 100644 rulemgt/src/test/resources/index-add.json create mode 100644 rulemgt/src/test/resources/index-empty.json create mode 100644 rulemgt/src/test/resources/index-rule-changed.json create mode 100644 rulemgt/src/test/resources/index-rule-spaces-test.json diff --git a/pom.xml b/pom.xml index ec1c6d6..b3d917c 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.onap.holmes.rule-management holmes-rulemgt-parent - 1.3.4-SNAPSHOT + 1.3.5-SNAPSHOT pom holmes-rule-management @@ -130,7 +130,7 @@ org.onap.holmes.common holmes-actions - 1.3.5 + 1.3.7 org.glassfish.jersey.containers diff --git a/rulemgt-frontend/pom.xml b/rulemgt-frontend/pom.xml index 9609647..fbcb136 100644 --- a/rulemgt-frontend/pom.xml +++ b/rulemgt-frontend/pom.xml @@ -24,7 +24,7 @@ org.onap.holmes.rule-management holmes-rulemgt-parent - 1.3.4-SNAPSHOT + 1.3.5-SNAPSHOT holmes-rulemgt-frontend diff --git a/rulemgt-standalone/pom.xml b/rulemgt-standalone/pom.xml index db98945..be9e5ca 100644 --- a/rulemgt-standalone/pom.xml +++ b/rulemgt-standalone/pom.xml @@ -23,7 +23,7 @@ org.onap.holmes.rule-management holmes-rulemgt-parent - 1.3.4-SNAPSHOT + 1.3.5-SNAPSHOT holmes-rulemgt-standalone diff --git a/rulemgt/pom.xml b/rulemgt/pom.xml index 13c568a..7fbb227 100644 --- a/rulemgt/pom.xml +++ b/rulemgt/pom.xml @@ -20,7 +20,7 @@ org.onap.holmes.rule-management holmes-rulemgt-parent - 1.3.4-SNAPSHOT + 1.3.5-SNAPSHOT holmes-rulemgt diff --git a/rulemgt/src/main/java/org/onap/holmes/rulemgt/RuleActiveApp.java b/rulemgt/src/main/java/org/onap/holmes/rulemgt/RuleActiveApp.java index f77b909..a9a78c8 100644 --- a/rulemgt/src/main/java/org/onap/holmes/rulemgt/RuleActiveApp.java +++ b/rulemgt/src/main/java/org/onap/holmes/rulemgt/RuleActiveApp.java @@ -17,13 +17,10 @@ package org.onap.holmes.rulemgt; import io.dropwizard.setup.Environment; -import org.onap.holmes.common.config.MicroServiceConfig; +import org.onap.holmes.common.ConfigFileScanner; import org.onap.holmes.common.dropwizard.ioc.bundle.IOCApplication; -import org.onap.holmes.common.utils.CommonUtils; import org.onap.holmes.common.utils.transactionid.TransactionIdFilter; -import org.onap.holmes.rulemgt.dcae.DcaeConfigurationPolling; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.onap.holmes.rulemgt.dcae.ConfigFileScanningTask; import javax.servlet.DispatcherType; import java.util.EnumSet; @@ -41,12 +38,10 @@ public class RuleActiveApp extends IOCApplication { public void run(RuleAppConfig configuration, Environment environment) throws Exception { super.run(configuration, environment); - if (!"1".equals(System.getenv("TESTING"))) { - ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); - service.scheduleAtFixedRate( - new DcaeConfigurationPolling(CommonUtils.getEnv(MicroServiceConfig.HOSTNAME)), 0, - DcaeConfigurationPolling.POLLING_PERIOD, TimeUnit.MILLISECONDS); - } + ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); + service.scheduleAtFixedRate( + new ConfigFileScanningTask(new ConfigFileScanner()), 60L, + ConfigFileScanningTask.POLLING_PERIOD, TimeUnit.SECONDS); environment.servlets().addFilter("customFilter", new TransactionIdFilter()).addMappingForUrlPatterns(EnumSet .allOf(DispatcherType.class), true, "/*"); diff --git a/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java b/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java new file mode 100644 index 0000000..9f7b89f --- /dev/null +++ b/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java @@ -0,0 +1,190 @@ +/** + * Copyright 2021 ZTE Corporation. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.holmes.rulemgt.dcae; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.commons.lang.StringUtils; +import org.onap.holmes.common.ConfigFileScanner; +import org.onap.holmes.common.utils.FileUtils; +import org.onap.holmes.common.utils.JerseyClient; +import org.onap.holmes.rulemgt.bean.request.RuleCreateRequest; +import org.onap.holmes.rulemgt.bean.response.RuleQueryListResponse; +import org.onap.holmes.rulemgt.bean.response.RuleResult4API; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import java.io.File; +import java.nio.file.Paths; +import java.util.*; + +public class ConfigFileScanningTask implements Runnable { + final public static long POLLING_PERIOD = 30L; + final private static Logger LOGGER = LoggerFactory.getLogger(ConfigFileScanningTask.class); + final private static long FILE_SIZE_LMT = 1024 * 1024 * 10; // 10MB + final private Map configInEffect = new HashMap(); // Contents for configInEffect are : pairs. + private String configFile = "/opt/hrmrules/index.json"; + private ConfigFileScanner configFileScanner; + private String url = "https://127.0.0.1:9101/api/holmes-rule-mgmt/v1/rule"; + + public ConfigFileScanningTask(ConfigFileScanner configFileScanner) { + this.configFileScanner = configFileScanner; + } + + @Override + public void run() { + if (null == configFileScanner) { + configFileScanner = new ConfigFileScanner(); + } + Map newConfig = extractConfigItems(configFileScanner.scan(configFile)); + + List deployedRules = getExistingRules(); + + // deal with newly added rules + final Set existingKeys = new HashSet(configInEffect.keySet()); + final Set newKeys = new HashSet(newConfig.keySet()); + newKeys.stream() + .filter(key -> !existingKeys.contains(key)) + .forEach(key -> { + if (deployRule(key, newConfig.get(key))) { + configInEffect.put(key, newConfig.get(key)); + LOGGER.info("Rule '{}' has been deployed.", key); + } + }); + + // deal with removed rules + existingKeys.stream().filter(key -> !newKeys.contains(key)).forEach(key -> { + if (deleteRule(find(deployedRules, key))) { + configInEffect.remove(key); + LOGGER.info("Rule '{}' has been removed.", key); + } + }); + + // deal with changed rules + existingKeys.stream().filter(key -> newKeys.contains(key)).forEach(key -> { + if (changed(configInEffect.get(key), newConfig.get(key))) { + if (deleteRule(find(deployedRules, key))) { + configInEffect.remove(key); + deployRule(key, newConfig.get(key)); + configInEffect.put(key, newConfig.get(key)); + LOGGER.info("Rule '{}' has been updated.", key); + } + } + }); + } + + private Map extractConfigItems(Map configFiles) { + Map ret = new HashMap(); + for (Map.Entry entry : configFiles.entrySet()) { + JsonArray ja = JsonParser.parseString(entry.getValue().toString()).getAsJsonArray(); + Iterator iterator = ja.iterator(); + while (iterator.hasNext()) { + JsonObject jo = iterator.next().getAsJsonObject(); + String contents = readFile(jo.get("file").getAsString()); + if (StringUtils.isNotBlank(contents)) { + ret.put(jo.get("closedControlLoopName").getAsString(), contents); + } + } + } + return ret; + } + + private String normalizePath(String path) { + if (!path.startsWith("/")) { + return Paths.get(new File(configFile).getParent(), path).toString(); + } + return path; + } + private String readFile(String path) { + String finalPath = normalizePath(path); + File file = new File(finalPath); + if (file.exists() && !file.isDirectory() && file.length() <= FILE_SIZE_LMT) { + return FileUtils.readTextFile(finalPath); + } else { + LOGGER.warn("The file {} does not exist or it is a directory or it is too large to load.", finalPath); + } + return null; + } + + private RuleResult4API find(final List rules, String clName) { + for (RuleResult4API rule : rules) { + if (rule.getLoopControlName().equals(clName)) { + return rule; + } + } + return null; + } + + private boolean changed(String con1, String con2) { + // if either of the arguments is null, consider it as invalid and unchanged + if (con1 == null || con2 == null) { + return false; + } + + if (!con1.replaceAll("\\s", StringUtils.EMPTY) + .equals(con2.replaceAll("\\s", StringUtils.EMPTY))) { + return true; + } + + return false; + } + + private List getExistingRules() { + RuleQueryListResponse ruleQueryListResponse = JerseyClient.newInstance().get(url, RuleQueryListResponse.class); + List deployedRules = Collections.EMPTY_LIST; + if (null != ruleQueryListResponse) { + deployedRules = ruleQueryListResponse.getCorrelationRules(); + } + return deployedRules; + } + + private boolean deployRule(String clName, String contents) { + RuleCreateRequest ruleCreateRequest = getRuleCreateRequest(clName, contents); + if (JerseyClient.newInstance().header("Accept", MediaType.APPLICATION_JSON) + .put(url, Entity.json(ruleCreateRequest)) == null) { + LOGGER.error("Failed to deploy rule: {}.", clName); + return false; + } + return true; + } + + private RuleCreateRequest getRuleCreateRequest(String clName, String contents) { + RuleCreateRequest ruleCreateRequest = new RuleCreateRequest(); + ruleCreateRequest.setLoopControlName(clName); + ruleCreateRequest.setRuleName(clName); + ruleCreateRequest.setContent(contents); + ruleCreateRequest.setDescription(""); + ruleCreateRequest.setEnabled(1); + return ruleCreateRequest; + } + + private boolean deleteRule(RuleResult4API rule) { + if (rule == null) { + LOGGER.info("No rule found, nothing to delete."); + return false; + } + if (null == JerseyClient.newInstance().delete(url + "/" + rule.getRuleId())) { + LOGGER.warn("Failed to delete rule, the rule id is: {}", rule.getRuleId()); + return false; + } + return true; + } +} diff --git a/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/DcaeConfigurationPolling.java b/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/DcaeConfigurationPolling.java index f07d8ac..8049e8f 100644 --- a/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/DcaeConfigurationPolling.java +++ b/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/DcaeConfigurationPolling.java @@ -30,6 +30,7 @@ import javax.ws.rs.core.MediaType; import java.util.List; @Slf4j +@Deprecated public class DcaeConfigurationPolling implements Runnable { public static final long POLLING_PERIOD = 30 * 1000L; diff --git a/rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java b/rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java new file mode 100644 index 0000000..053612b --- /dev/null +++ b/rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java @@ -0,0 +1,241 @@ +/** + * Copyright 2021 ZTE Corporation. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.holmes.rulemgt.dcae; + +import org.easymock.EasyMock; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.holmes.common.ConfigFileScanner; +import org.onap.holmes.common.utils.FileUtils; +import org.onap.holmes.common.utils.JerseyClient; +import org.onap.holmes.rulemgt.bean.response.RuleQueryListResponse; +import org.onap.holmes.rulemgt.bean.response.RuleResult4API; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({JerseyClient.class}) +@SuppressStaticInitializationFor({"org.onap.holmes.common.utils.JerseyClient"}) +public class ConfigFileScanningTaskTest { + + @Test + public void run_add_rules() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String indexPath = getFilePath("index-add.json"); + String contents = FileUtils.readTextFile(indexPath); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(null); + Whitebox.setInternalState(cfst, "configFile", indexPath); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API(clName, contents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + // mock for deployRule + EasyMock.expect(jcMock.header(EasyMock.anyString(), EasyMock.anyObject())).andReturn(jcMock); + EasyMock.expect(jcMock.put(EasyMock.anyString(), EasyMock.anyObject())).andReturn(""); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(1)); + } + + @Test + public void run_remove_rules_normal() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String indexPath = getFilePath("index-add.json"); + String contents = FileUtils.readTextFile(indexPath); + Map configInEffect = new HashMap<>(); + configInEffect.put(clName, contents); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); + Whitebox.setInternalState(cfst, "configFile", getFilePath("index-empty.json")); + Whitebox.setInternalState(cfst, "configInEffect", configInEffect); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API(clName, contents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + // mock for deleteRule + EasyMock.expect(jcMock.delete(EasyMock.anyString())).andReturn(""); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(0)); + } + + @Test + public void run_remove_rules_delete_null_pointer() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String indexPath = getFilePath("index-add.json"); + String contents = FileUtils.readTextFile(indexPath); + Map configInEffect = new HashMap<>(); + configInEffect.put(clName, contents); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); + Whitebox.setInternalState(cfst, "configFile", indexPath); + Whitebox.setInternalState(cfst, "configInEffect", configInEffect); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API("a-non-existing-rule", contents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(1)); + } + + @Test + public void run_remove_rules_api_calling_returning_null() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String indexPath = getFilePath("index-add.json"); + String contents = FileUtils.readTextFile(indexPath); + Map configInEffect = new HashMap<>(); + configInEffect.put(clName, contents); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); + Whitebox.setInternalState(cfst, "configFile", indexPath); + Whitebox.setInternalState(cfst, "configInEffect", configInEffect); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API(clName, contents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + // mock for deleteRule + EasyMock.expect(jcMock.delete(EasyMock.anyString())).andReturn(null); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(1)); + } + + @Test + public void run_change_rules_normal() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String oldDrlPath = getFilePath("ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl"); + String oldDrlContents = FileUtils.readTextFile(oldDrlPath); + Map configInEffect = new HashMap<>(); + configInEffect.put(clName, oldDrlContents); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); + Whitebox.setInternalState(cfst, "configFile", getFilePath("index-rule-changed.json")); + Whitebox.setInternalState(cfst, "configInEffect", configInEffect); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API(clName, oldDrlContents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + // mock for deleteRule + EasyMock.expect(jcMock.delete(EasyMock.anyString())).andReturn(""); + + // mock for deployRule + EasyMock.expect(jcMock.header(EasyMock.anyString(), EasyMock.anyObject())).andReturn(jcMock); + EasyMock.expect(jcMock.put(EasyMock.anyString(), EasyMock.anyObject())).andReturn(""); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(1)); + assertThat(config.get(clName), + equalTo(FileUtils.readTextFile( + getFilePath("ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl")))); + } + + @Test + public void run_change_rules_no_change_except_for_spaces() throws Exception { + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; + String oldDrlPath = getFilePath("ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl"); + String oldDrlContents = FileUtils.readTextFile(oldDrlPath); + Map configInEffect = new HashMap<>(); + configInEffect.put(clName, oldDrlContents); + + ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); + Whitebox.setInternalState(cfst, "configFile", getFilePath("index-rule-spaces-test.json")); + Whitebox.setInternalState(cfst, "configInEffect", configInEffect); + + // mock for getExistingRules + JerseyClient jcMock = PowerMock.createMock(JerseyClient.class); + PowerMock.expectNew(JerseyClient.class).andReturn(jcMock).anyTimes(); + RuleQueryListResponse rqlr = new RuleQueryListResponse(); + rqlr.getCorrelationRules().add(getRuleResult4API(clName, oldDrlContents)); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andReturn(rqlr); + + PowerMock.replayAll(); + cfst.run(); + PowerMock.verifyAll(); + + Map config = Whitebox.getInternalState(cfst, "configInEffect"); + assertThat(config.size(), is(1)); + assertThat(config.get(clName), + equalTo(FileUtils.readTextFile( + getFilePath("ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl")))); + } + + private String getFilePath(String fileName) { + return ConfigFileScanningTaskTest.class.getResource("/" + fileName).getFile(); + } + + private RuleResult4API getRuleResult4API(String clName, String contents) { + RuleResult4API ruleResult4API = new RuleResult4API(); + ruleResult4API.setRuleId(clName); + ruleResult4API.setRuleName(clName); + ruleResult4API.setLoopControlName(clName); + ruleResult4API.setContent(contents); + ruleResult4API.setDescription(""); + ruleResult4API.setEnabled(1); + return ruleResult4API; + } +} \ No newline at end of file diff --git a/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl new file mode 100644 index 0000000..039bf68 --- /dev/null +++ b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl @@ -0,0 +1,91 @@ +package org.onap.holmes.droolsRule; + +import org.onap.holmes.common.dmaap.DmaapService; +import org.onap.holmes.common.api.stat.VesAlarm; +import org.onap.holmes.common.aai.CorrelationUtil; +import org.onap.holmes.common.dmaap.entity.PolicyMsg; +import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder; +import org.onap.holmes.common.utils.DroolsLog; + + +rule "Relation_analysis_Rule" +salience 200 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, + $sourceId: sourceId, sourceId != null && !sourceId.equals(""), + $sourceName: sourceName, sourceName != null && !sourceName.equals(""), + $startEpochMicrosec: startEpochMicrosec, + eventName in ("Fault_MultiCloud_VMFailure"), + $eventId: eventId) + $child : VesAlarm( eventId != $eventId, parentId == null, + CorrelationUtil.getInstance().isTopologicallyRelated(sourceId, $sourceId, $sourceName), + eventName in ("Fault_MME_eNodeB out of service alarm"), + startEpochMicrosec < $startEpochMicrosec + 60000 && startEpochMicrosec > $startEpochMicrosec - 60000 ) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("Relation_analysis_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + $child.setParentId($root.getEventId()); + update($child); + +end + +rule "root_has_child_handle_Rule" +salience 150 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, $eventId: eventId) + $child : VesAlarm(eventId != $eventId, parentId == $eventId) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_has_child_handle_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, $child, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_no_child_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, + sourceId != null && !sourceId.equals(""), + sourceName != null && !sourceName.equals(""), + eventName in ("Fault_MultiCloud_VMFailure")) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_no_child_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_cleared_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 1, rootFlag == 1) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_cleared_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + retract($root); +end + +rule "child_handle_Rule" +salience 100 +no-loop true + when + $child : VesAlarm(alarmIsCleared == 1, rootFlag == 0) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("child_handle_Rule: childId=" + $child.getEventId()); + retract($child); + DroolsLog.printInfo("done"); +end diff --git a/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl new file mode 100644 index 0000000..a75f202 --- /dev/null +++ b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl @@ -0,0 +1,88 @@ +package org.onap.holmes.droolsRule; + +import org.onap.holmes.common.dmaap.DmaapService; +import org.onap.holmes.common.api.stat.VesAlarm; +import org.onap.holmes.common.aai.CorrelationUtil; +import org.onap.holmes.common.dmaap.entity.PolicyMsg; +import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder; +import org.onap.holmes.common.utils.DroolsLog; + +rule "Relation_analysis_Rule" +salience 200 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, + $sourceId: sourceId, sourceId != null && !sourceId.equals(""), + $sourceName: sourceName, sourceName != null && !sourceName.equals(""), + $startEpochMicrosec: startEpochMicrosec, + eventName in ("Fault_MultiCloud_VMFailure"), + $eventId: eventId) + $child : VesAlarm( eventId != $eventId, parentId == null, + CorrelationUtil.getInstance().isTopologicallyRelated(sourceId, $sourceId, $sourceName), + eventName in ("Fault_MME_eNodeB out of service alarm"), + startEpochMicrosec < $startEpochMicrosec + 60000 && startEpochMicrosec > $startEpochMicrosec - 60000 ) + then + DroolsLog.printInfo( "===========================================================" ); + DroolsLog.printInfo("Relation_analysis_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + $child.setParentId($root.getEventId()); + update($child); +end + +rule "root_has_child_handle_Rule" +salience 150 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, $eventId: eventId) + $child : VesAlarm(eventId != $eventId, parentId == $eventId) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_has_child_handle_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, $child, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_no_child_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, + sourceId != null && !sourceId.equals(""), + sourceName != null && !sourceName.equals(""), + eventName in ("Fault_MultiCloud_VMFailure")) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_no_child_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_cleared_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 1, rootFlag == 1) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_cleared_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + retract($root); +end + +rule "child_handle_Rule" +salience 100 +no-loop true + when + $child : VesAlarm(alarmIsCleared == 1, rootFlag == 0) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("child_handle_Rule: childId=" + $child.getEventId()); + retract($child); +end diff --git a/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl new file mode 100644 index 0000000..5fbaaa5 --- /dev/null +++ b/rulemgt/src/test/resources/ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl @@ -0,0 +1,90 @@ +package org.onap.holmes.droolsRule; + +import org.onap.holmes.common.dmaap.DmaapService; +import org.onap.holmes.common.api.stat.VesAlarm; +import org.onap.holmes.common.aai.CorrelationUtil; +import org.onap.holmes.common.dmaap.entity.PolicyMsg; +import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder; +import org.onap.holmes.common.utils.DroolsLog; + + +rule "Relation_analysis_Rule" +salience 200 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, + $sourceId: sourceId, sourceId != null && !sourceId.equals(""), + $sourceName: sourceName, sourceName != null && !sourceName.equals(""), + $startEpochMicrosec: startEpochMicrosec, + eventName in ("Fault_MultiCloud_VMFailure"), + $eventId: eventId) + $child : VesAlarm( eventId != $eventId, parentId == null, + CorrelationUtil.getInstance().isTopologicallyRelated(sourceId, $sourceId, $sourceName), + eventName in ("Fault_MME_eNodeB out of service alarm"), + startEpochMicrosec < $startEpochMicrosec + 60000 && startEpochMicrosec > $startEpochMicrosec - 60000 ) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("Relation_analysis_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + $child.setParentId($root.getEventId()); + update($child); + +end + +rule "root_has_child_handle_Rule" +salience 150 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, $eventId: eventId) + $child : VesAlarm(eventId != $eventId, parentId == $eventId) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_has_child_handle_Rule: rootId=" + $root.getEventId() + ", childId=" + $child.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, $child, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_no_child_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, + sourceId != null && !sourceId.equals(""), + sourceName != null && !sourceName.equals(""), + eventName in ("Fault_MultiCloud_VMFailure")) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_no_child_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + $root.setRootFlag(1); + update($root); +end + +rule "root_cleared_handle_Rule" +salience 100 +no-loop true + when + $root : VesAlarm(alarmIsCleared == 1, rootFlag == 1) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("root_cleared_handle_Rule: rootId=" + $root.getEventId()); + DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class); + PolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, "org.onap.holmes.droolsRule"); + dmaapService.publishPolicyMsg(policyMsg, "dcae_cl_out"); + retract($root); +end + +rule "child_handle_Rule" +salience 100 +no-loop true + when + $child : VesAlarm(alarmIsCleared == 1, rootFlag == 0) + then + DroolsLog.printInfo("==========================================================="); + DroolsLog.printInfo("child_handle_Rule: childId=" + $child.getEventId()); + retract($child); +end diff --git a/rulemgt/src/test/resources/index-add.json b/rulemgt/src/test/resources/index-add.json new file mode 100644 index 0000000..f0ee695 --- /dev/null +++ b/rulemgt/src/test/resources/index-add.json @@ -0,0 +1,6 @@ +[ + { + "closedControlLoopName": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b", + "file": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b.drl" + } +] \ No newline at end of file diff --git a/rulemgt/src/test/resources/index-empty.json b/rulemgt/src/test/resources/index-empty.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/rulemgt/src/test/resources/index-empty.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/rulemgt/src/test/resources/index-rule-changed.json b/rulemgt/src/test/resources/index-rule-changed.json new file mode 100644 index 0000000..1c7b237 --- /dev/null +++ b/rulemgt/src/test/resources/index-rule-changed.json @@ -0,0 +1,6 @@ +[ + { + "closedControlLoopName": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b", + "file": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-changed.drl" + } +] \ No newline at end of file diff --git a/rulemgt/src/test/resources/index-rule-spaces-test.json b/rulemgt/src/test/resources/index-rule-spaces-test.json new file mode 100644 index 0000000..f1d82db --- /dev/null +++ b/rulemgt/src/test/resources/index-rule-spaces-test.json @@ -0,0 +1,6 @@ +[ + { + "closedControlLoopName": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b", + "file": "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b-spaces.drl" + } +] \ No newline at end of file -- 2.16.6