From 58e113734959922ec70516f9be1d7ebcc3fd5dc3 Mon Sep 17 00:00:00 2001 From: Guangrong Fu Date: Thu, 20 Jan 2022 11:45:39 +0800 Subject: [PATCH] bugfix - rule deployment issue during init Issue-ID: HOLMES-488 Signed-off-by: Guangrong Fu Change-Id: If667a3691aa67a2559020b0bc91f7f4c21347026 --- pom.xml | 6 ++ .../rulemgt/dcae/ConfigFileScanningTask.java | 31 ++++++-- .../rulemgt/dcae/ConfigFileScanningTaskTest.java | 88 ++++++++-------------- 3 files changed, 61 insertions(+), 64 deletions(-) diff --git a/pom.xml b/pom.xml index 4029c1d..0c308bb 100644 --- a/pom.xml +++ b/pom.xml @@ -276,6 +276,12 @@ ${powermock.version} test + + com.github.stefanbirkner + system-rules + 1.16.0 + test + io.reactivex.rxjava2 rxjava 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 index 884ea31..574432c 100644 --- a/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java +++ b/rulemgt/src/main/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTask.java @@ -53,6 +53,26 @@ public class ConfigFileScanningTask implements Runnable { @Override public void run() { + List deployedRules = null; + boolean isRuleQueryAvailable = true; + + try { + deployedRules = getExistingRules(); + } catch (Exception e) { + LOGGER.warn("Failed to get existing rules for comparison.", e); + isRuleQueryAvailable = false; + } + + // If it fails to load rule through API, it means that something must be wrong with the + // holmes-rule-mgmt service. Hence, there's no need to go on with remaining steps. + if (!isRuleQueryAvailable) { + return; + } + + for (RuleResult4API ruleResult4API : deployedRules) { + configInEffect.put(ruleResult4API.getLoopControlName(), ruleResult4API.getContent()); + } + if (null == configFileScanner) { configFileScanner = new ConfigFileScanner(); } @@ -60,8 +80,6 @@ public class ConfigFileScanningTask implements Runnable { try { 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()); @@ -69,15 +87,14 @@ public class ConfigFileScanningTask implements Runnable { .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 + final List existingRules = deployedRules; existingKeys.stream().filter(key -> !newKeys.contains(key)).forEach(key -> { - if (deleteRule(find(deployedRules, key))) { - configInEffect.remove(key); + if (deleteRule(find(existingRules, key))) { LOGGER.info("Rule '{}' has been removed.", key); } }); @@ -85,10 +102,8 @@ public class ConfigFileScanningTask implements Runnable { // 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); + if (deleteRule(find(existingRules, key))) { deployRule(key, newConfig.get(key)); - configInEffect.put(key, newConfig.get(key)); LOGGER.info("Rule '{}' has been updated.", key); } } 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 index d6d93a9..75f60b6 100644 --- a/rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java +++ b/rulemgt/src/test/java/org/onap/holmes/rulemgt/dcae/ConfigFileScanningTaskTest.java @@ -17,7 +17,9 @@ package org.onap.holmes.rulemgt.dcae; import org.easymock.EasyMock; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.SystemOutRule; import org.junit.runner.RunWith; import org.onap.holmes.common.ConfigFileScanner; import org.onap.holmes.common.utils.FileUtils; @@ -33,8 +35,8 @@ 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.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertThat; @RunWith(PowerMockRunner.class) @@ -42,13 +44,14 @@ import static org.junit.Assert.assertThat; @SuppressStaticInitializationFor({"org.onap.holmes.common.utils.JerseyClient"}) public class ConfigFileScanningTaskTest { + @Rule + public final SystemOutRule systemOut = new SystemOutRule().enableLog(); + @Test - public void run_add_rules() throws Exception { + public void run_failed_to_get_existing_rules() throws Exception { System.setProperty("ENABLE_ENCRYPT", "true"); - 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); @@ -56,60 +59,49 @@ public class ConfigFileScanningTaskTest { // 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(""); + EasyMock.expect(jcMock.get(EasyMock.anyString(), EasyMock.anyObject())).andThrow(new RuntimeException()); PowerMock.replayAll(); cfst.run(); PowerMock.verifyAll(); - Map config = Whitebox.getInternalState(cfst, "configInEffect"); - assertThat(config.size(), is(1)); - - System.clearProperty("ENABLE_ENCRYPT"); + assertThat(systemOut.getLog(), containsString("Failed to get existing rules for comparison.")); } @Test - public void run_remove_rules_normal() throws Exception { - System.setProperty("ENABLE_ENCRYPT", "false"); + public void run_add_rules() throws Exception { + System.setProperty("ENABLE_ENCRYPT", "true"); 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); + 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 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(0)); + assertThat(systemOut.getLog(), containsString("Rule 'ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b' has been deployed.")); System.clearProperty("ENABLE_ENCRYPT"); } @Test - public void run_remove_rules_delete_null_pointer() throws Exception { + public void run_remove_rules_normal() throws Exception { + System.setProperty("ENABLE_ENCRYPT", "false"); + String clName = "ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b"; String indexPath = getFilePath("index-add.json"); String contents = FileUtils.readTextFile(indexPath); @@ -117,22 +109,26 @@ public class ConfigFileScanningTaskTest { configInEffect.put(clName, contents); ConfigFileScanningTask cfst = new ConfigFileScanningTask(new ConfigFileScanner()); - Whitebox.setInternalState(cfst, "configFile", indexPath); + 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("a-non-existing-rule", contents)); + 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(1)); + assertThat(systemOut.getLog(), containsString("Rule 'ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b' has been removed.")); + + System.clearProperty("ENABLE_ENCRYPT"); } @Test @@ -140,12 +136,9 @@ public class ConfigFileScanningTaskTest { 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); @@ -161,8 +154,7 @@ public class ConfigFileScanningTaskTest { cfst.run(); PowerMock.verifyAll(); - Map config = Whitebox.getInternalState(cfst, "configInEffect"); - assertThat(config.size(), is(1)); + assertThat(systemOut.getLog(), containsString("Failed to delete rule, the rule id is: ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b")); } @Test @@ -170,12 +162,9 @@ public class ConfigFileScanningTaskTest { 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); @@ -195,11 +184,7 @@ public class ConfigFileScanningTaskTest { 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")))); + assertThat(systemOut.getLog(), containsString("Rule 'ControlLoop-VOLTE-2179b738-fd36-4843-a71a-a8c24c70c55b' has been updated.")); } @Test @@ -207,12 +192,9 @@ public class ConfigFileScanningTaskTest { 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); @@ -225,11 +207,7 @@ public class ConfigFileScanningTaskTest { 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")))); + assertThat(systemOut.getLog(), not(containsString("has been updated."))); } private String getFilePath(String fileName) { @@ -246,6 +224,4 @@ public class ConfigFileScanningTaskTest { ruleResult4API.setEnabled(1); return ruleResult4API; } - - } \ No newline at end of file -- 2.16.6