You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by ce...@apache.org on 2017/03/02 20:51:54 UTC
[08/10] incubator-metron git commit: METRON-503: Metron REST API this
closes apache/incubator-metron#316
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorEnrichmentConfigServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorEnrichmentConfigServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorEnrichmentConfigServiceImplTest.java
new file mode 100644
index 0000000..d292948
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorEnrichmentConfigServiceImplTest.java
@@ -0,0 +1,256 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.DeleteBuilder;
+import org.apache.curator.framework.api.GetChildrenBuilder;
+import org.apache.curator.framework.api.GetDataBuilder;
+import org.apache.curator.framework.api.SetDataBuilder;
+import org.apache.metron.common.configuration.ConfigurationType;
+import org.apache.metron.common.configuration.enrichment.EnrichmentConfig;
+import org.apache.metron.common.configuration.enrichment.SensorEnrichmentConfig;
+import org.apache.metron.common.configuration.enrichment.threatintel.ThreatIntelConfig;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.service.SensorEnrichmentConfigService;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class SensorEnrichmentConfigServiceImplTest {
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ ObjectMapper objectMapper;
+ CuratorFramework curatorFramework;
+ SensorEnrichmentConfigService sensorEnrichmentConfigService;
+
+ /**
+ {
+ "enrichment" : {
+ "fieldMap": {
+ "geo": ["ip_dst_addr"]
+ }
+ },
+ "threatIntel": {
+ "fieldMap": {
+ "hbaseThreatIntel": ["ip_src_addr"]
+ },
+ "fieldToTypeMap": {
+ "ip_src_addr" : ["malicious_ip"]
+ }
+ }
+ }
+ */
+ @Multiline
+ public static String broJson;
+
+ @Before
+ public void setUp() throws Exception {
+ objectMapper = mock(ObjectMapper.class);
+ curatorFramework = mock(CuratorFramework.class);
+ sensorEnrichmentConfigService = new SensorEnrichmentConfigServiceImpl(objectMapper, curatorFramework);
+ }
+
+
+ @Test
+ public void deleteShouldProperlyCatchNoNodeExceptionAndReturnFalse() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ assertFalse(sensorEnrichmentConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldProperlyCatchNonNoNodeExceptionAndThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ assertFalse(sensorEnrichmentConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldReturnTrueWhenClientSuccessfullyCallsDelete() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenReturn(null);
+
+ assertTrue(sensorEnrichmentConfigService.delete("bro"));
+
+ verify(curatorFramework).delete();
+ }
+
+ @Test
+ public void findOneShouldProperlyReturnSensorEnrichmentConfig() throws Exception {
+ final SensorEnrichmentConfig sensorEnrichmentConfig = getTestSensorEnrichmentConfig();
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(getTestSensorEnrichmentConfig(), sensorEnrichmentConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldReturnNullWhenNoNodeExceptionIsThrown() throws Exception {
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertNull(sensorEnrichmentConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ sensorEnrichmentConfigService.findOne("bro");
+ }
+
+ @Test
+ public void getAllTypesShouldProperlyReturnTypes() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }}, sensorEnrichmentConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldReturnNullWhenNoNodeExceptionIsThrown() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot())).thenThrow(KeeperException.NoNodeException.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList<>(), sensorEnrichmentConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot())).thenThrow(Exception.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ sensorEnrichmentConfigService.getAllTypes();
+ }
+
+ @Test
+ public void getAllShouldProperlyReturnSensorEnrichmentConfigs() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ final SensorEnrichmentConfig sensorEnrichmentConfig = getTestSensorEnrichmentConfig();
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(new HashMap() {{ put("bro", sensorEnrichmentConfig);}}, sensorEnrichmentConfigService.getAll());
+ }
+
+ @Test
+ public void saveShouldWrapExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro", broJson.getBytes())).thenThrow(Exception.class);
+
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ sensorEnrichmentConfigService.save("bro", new SensorEnrichmentConfig());
+ }
+
+ @Test
+ public void saveShouldReturnSameConfigThatIsPassedOnSuccessfulSave() throws Exception {
+ final SensorEnrichmentConfig sensorEnrichmentConfig = getTestSensorEnrichmentConfig();
+
+ when(objectMapper.writeValueAsString(sensorEnrichmentConfig)).thenReturn(broJson);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro", broJson.getBytes())).thenReturn(new Stat());
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ assertEquals(sensorEnrichmentConfig, sensorEnrichmentConfigService.save("bro", sensorEnrichmentConfig));
+ verify(setDataBuilder).forPath(eq(ConfigurationType.ENRICHMENT.getZookeeperRoot() + "/bro"), eq(broJson.getBytes()));
+ }
+
+ @Test
+ public void getAvailableEnrichmentsShouldReturnEnrichments() throws Exception {
+ assertEquals(new ArrayList<String>() {{
+ add("geo");
+ add("host");
+ add("whois");
+ }}, sensorEnrichmentConfigService.getAvailableEnrichments());
+ }
+
+ private SensorEnrichmentConfig getTestSensorEnrichmentConfig() {
+ SensorEnrichmentConfig sensorEnrichmentConfig = new SensorEnrichmentConfig();
+ EnrichmentConfig enrichmentConfig = new EnrichmentConfig();
+ enrichmentConfig.setFieldMap(new HashMap() {{ put("geo", Arrays.asList("ip_dst_addr")); }});
+ sensorEnrichmentConfig.setEnrichment(enrichmentConfig);
+ ThreatIntelConfig threatIntelConfig = new ThreatIntelConfig();
+ threatIntelConfig.setFieldMap(new HashMap() {{ put("hbaseThreatIntel", Arrays.asList("ip_src_addr")); }});
+ threatIntelConfig.setFieldToTypeMap(new HashMap() {{ put("ip_src_addr", Arrays.asList("malicious_ip")); }});
+ sensorEnrichmentConfig.setThreatIntel(threatIntelConfig);
+ return sensorEnrichmentConfig;
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorIndexingConfigServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorIndexingConfigServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorIndexingConfigServiceImplTest.java
new file mode 100644
index 0000000..43ca0f7
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorIndexingConfigServiceImplTest.java
@@ -0,0 +1,234 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.DeleteBuilder;
+import org.apache.curator.framework.api.GetChildrenBuilder;
+import org.apache.curator.framework.api.GetDataBuilder;
+import org.apache.curator.framework.api.SetDataBuilder;
+import org.apache.metron.common.configuration.ConfigurationType;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.service.SensorIndexingConfigService;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class SensorIndexingConfigServiceImplTest {
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ ObjectMapper objectMapper;
+ CuratorFramework curatorFramework;
+ SensorIndexingConfigService sensorIndexingConfigService;
+
+ /**
+ {
+ "hdfs" : {
+ "index": "bro",
+ "batchSize": 5,
+ "enabled" : true
+ }
+ }
+ */
+ @Multiline
+ public static String broJson;
+
+ @Before
+ public void setUp() throws Exception {
+ objectMapper = mock(ObjectMapper.class);
+ curatorFramework = mock(CuratorFramework.class);
+ sensorIndexingConfigService = new SensorIndexingConfigServiceImpl(objectMapper, curatorFramework);
+ }
+
+
+ @Test
+ public void deleteShouldProperlyCatchNoNodeExceptionAndReturnFalse() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ assertFalse(sensorIndexingConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldProperlyCatchNonNoNodeExceptionAndThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ assertFalse(sensorIndexingConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldReturnTrueWhenClientSuccessfullyCallsDelete() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenReturn(null);
+
+ assertTrue(sensorIndexingConfigService.delete("bro"));
+
+ verify(curatorFramework).delete();
+ }
+
+ @Test
+ public void findOneShouldProperlyReturnSensorEnrichmentConfig() throws Exception {
+ final Map<String, Object> sensorIndexingConfig = getTestSensorIndexingConfig();
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(getTestSensorIndexingConfig(), sensorIndexingConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldReturnNullWhenNoNodeExceptionIsThrown() throws Exception {
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertNull(sensorIndexingConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ sensorIndexingConfigService.findOne("bro");
+ }
+
+ @Test
+ public void getAllTypesShouldProperlyReturnTypes() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }}, sensorIndexingConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldReturnNullWhenNoNodeExceptionIsThrown() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot())).thenThrow(KeeperException.NoNodeException.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList<>(), sensorIndexingConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot())).thenThrow(Exception.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ sensorIndexingConfigService.getAllTypes();
+ }
+
+ @Test
+ public void getAllShouldProperlyReturnSensorEnrichmentConfigs() throws Exception {
+ final Map<String, Object> sensorIndexingConfig = getTestSensorIndexingConfig();
+
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(new HashMap() {{ put("bro", sensorIndexingConfig);}}, sensorIndexingConfigService.getAll());
+ }
+
+ @Test
+ public void saveShouldWrapExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro", broJson.getBytes())).thenThrow(Exception.class);
+
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ sensorIndexingConfigService.save("bro", new HashMap<>());
+ }
+
+ @Test
+ public void saveShouldReturnSameConfigThatIsPassedOnSuccessfulSave() throws Exception {
+ final Map<String, Object> sensorIndexingConfig = getTestSensorIndexingConfig();
+
+ when(objectMapper.writeValueAsString(sensorIndexingConfig)).thenReturn(broJson);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro", broJson.getBytes())).thenReturn(new Stat());
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ assertEquals(sensorIndexingConfig, sensorIndexingConfigService.save("bro", sensorIndexingConfig));
+ verify(setDataBuilder).forPath(eq(ConfigurationType.INDEXING.getZookeeperRoot() + "/bro"), eq(broJson.getBytes()));
+ }
+
+ private Map<String, Object> getTestSensorIndexingConfig() {
+ Map<String, Object> sensorIndexingConfig = new HashMap<>();
+ sensorIndexingConfig.put("hdfs", new HashMap(){{
+ put("index", "bro");
+ put("batchSize", 5);
+ put("enabled", true);
+ }});
+ return sensorIndexingConfig;
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorParserConfigServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorParserConfigServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorParserConfigServiceImplTest.java
new file mode 100644
index 0000000..d35a48c
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/SensorParserConfigServiceImplTest.java
@@ -0,0 +1,344 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.DeleteBuilder;
+import org.apache.curator.framework.api.GetChildrenBuilder;
+import org.apache.curator.framework.api.GetDataBuilder;
+import org.apache.curator.framework.api.SetDataBuilder;
+import org.apache.metron.common.configuration.ConfigurationType;
+import org.apache.metron.common.configuration.SensorParserConfig;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.model.ParseMessageRequest;
+import org.apache.metron.rest.service.GrokService;
+import org.apache.metron.rest.service.SensorParserConfigService;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.data.Stat;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.core.env.Environment;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class SensorParserConfigServiceImplTest {
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ Environment environment;
+ ObjectMapper objectMapper;
+ CuratorFramework curatorFramework;
+ GrokService grokService;
+ SensorParserConfigService sensorParserConfigService;
+
+ /**
+ {
+ "parserClassName": "org.apache.metron.parsers.GrokParser",
+ "sensorTopic": "squid",
+ "parserConfig": {
+ "grokPath": "/patterns/squid",
+ "patternLabel": "SQUID_DELIMITED",
+ "timestampField": "timestamp"
+ }
+ }
+ */
+ @Multiline
+ public static String squidJson;
+
+ /**
+ {
+ "parserClassName":"org.apache.metron.parsers.bro.BasicBroParser",
+ "sensorTopic":"bro",
+ "parserConfig": {}
+ }
+ */
+ @Multiline
+ public static String broJson;
+
+ @Before
+ public void setUp() throws Exception {
+ objectMapper = mock(ObjectMapper.class);
+ curatorFramework = mock(CuratorFramework.class);
+ grokService = mock(GrokService.class);
+ sensorParserConfigService = new SensorParserConfigServiceImpl(objectMapper, curatorFramework, grokService);
+ }
+
+
+ @Test
+ public void deleteShouldProperlyCatchNoNodeExceptionAndReturnFalse() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ assertFalse(sensorParserConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldProperlyCatchNonNoNodeExceptionAndThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ assertFalse(sensorParserConfigService.delete("bro"));
+ }
+
+ @Test
+ public void deleteShouldReturnTrueWhenClientSuccessfullyCallsDelete() throws Exception {
+ DeleteBuilder builder = mock(DeleteBuilder.class);
+
+ when(curatorFramework.delete()).thenReturn(builder);
+ when(builder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenReturn(null);
+
+ assertTrue(sensorParserConfigService.delete("bro"));
+
+ verify(curatorFramework).delete();
+ }
+
+ @Test
+ public void findOneShouldProperlyReturnSensorEnrichmentConfig() throws Exception {
+ final SensorParserConfig sensorParserConfig = getTestBroSensorParserConfig();
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(getTestBroSensorParserConfig(), sensorParserConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldReturnNullWhenNoNodeExceptionIsThrown() throws Exception {
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenThrow(KeeperException.NoNodeException.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertNull(sensorParserConfigService.findOne("bro"));
+ }
+
+ @Test
+ public void findOneShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenThrow(Exception.class);
+
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ sensorParserConfigService.findOne("bro");
+ }
+
+ @Test
+ public void getAllTypesShouldProperlyReturnTypes() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }}, sensorParserConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldReturnEmptyListWhenNoNodeExceptionIsThrown() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot())).thenThrow(KeeperException.NoNodeException.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ assertEquals(new ArrayList<>(), sensorParserConfigService.getAllTypes());
+ }
+
+ @Test
+ public void getAllTypesShouldWrapNonNoNodeExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot())).thenThrow(Exception.class);
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ sensorParserConfigService.getAllTypes();
+ }
+
+ @Test
+ public void getAllShouldProperlyReturnSensorParserConfigs() throws Exception {
+ GetChildrenBuilder getChildrenBuilder = mock(GetChildrenBuilder.class);
+ when(getChildrenBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot()))
+ .thenReturn(new ArrayList() {{
+ add("bro");
+ add("squid");
+ }});
+ when(curatorFramework.getChildren()).thenReturn(getChildrenBuilder);
+
+ final SensorParserConfig broSensorParserConfig = getTestBroSensorParserConfig();
+ final SensorParserConfig squidSensorParserConfig = getTestSquidSensorParserConfig();
+ GetDataBuilder getDataBuilder = mock(GetDataBuilder.class);
+ when(getDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro")).thenReturn(broJson.getBytes());
+ when(getDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/squid")).thenReturn(squidJson.getBytes());
+ when(curatorFramework.getData()).thenReturn(getDataBuilder);
+
+ assertEquals(new ArrayList() {{
+ add(getTestBroSensorParserConfig());
+ add(getTestSquidSensorParserConfig());
+ }}, sensorParserConfigService.getAll());
+ }
+
+ @Test
+ public void saveShouldWrapExceptionInRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro", broJson.getBytes())).thenThrow(Exception.class);
+
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ final SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.setSensorTopic("bro");
+ sensorParserConfigService.save(sensorParserConfig);
+ }
+
+ @Test
+ public void saveShouldReturnSameConfigThatIsPassedOnSuccessfulSave() throws Exception {
+ final SensorParserConfig sensorParserConfig = getTestBroSensorParserConfig();
+
+ when(objectMapper.writeValueAsString(sensorParserConfig)).thenReturn(broJson);
+
+ SetDataBuilder setDataBuilder = mock(SetDataBuilder.class);
+ when(setDataBuilder.forPath(ConfigurationType.PARSER.getZookeeperRoot() + "/bro", broJson.getBytes())).thenReturn(new Stat());
+ when(curatorFramework.setData()).thenReturn(setDataBuilder);
+
+ assertEquals(getTestBroSensorParserConfig(), sensorParserConfigService.save(sensorParserConfig));
+ verify(setDataBuilder).forPath(eq(ConfigurationType.PARSER.getZookeeperRoot() + "/bro"), eq(broJson.getBytes()));
+ }
+
+ @Test
+ public void reloadAvailableParsersShouldReturnParserClasses() throws Exception {
+ Map<String, String> availableParsers = sensorParserConfigService.reloadAvailableParsers();
+ assertTrue(availableParsers.size() > 0);
+ assertEquals("org.apache.metron.parsers.GrokParser", availableParsers.get("Grok"));
+ assertEquals("org.apache.metron.parsers.bro.BasicBroParser", availableParsers.get("Bro"));
+ }
+
+ @Test
+ public void parseMessageShouldProperlyReturnParsedResults() throws Exception {
+ final SensorParserConfig sensorParserConfig = getTestSquidSensorParserConfig();
+ String grokStatement = "SQUID_DELIMITED %{NUMBER:timestamp}[^0-9]*%{INT:elapsed} %{IP:ip_src_addr} %{WORD:action}/%{NUMBER:code} %{NUMBER:bytes} %{WORD:method} %{NOTSPACE:url}[^0-9]*(%{IP:ip_dst_addr})?";
+ String sampleData = "1461576382.642 161 127.0.0.1 TCP_MISS/200 103701 GET http://www.cnn.com/ - DIRECT/199.27.79.73 text/html";
+ ParseMessageRequest parseMessageRequest = new ParseMessageRequest();
+ parseMessageRequest.setSensorParserConfig(sensorParserConfig);
+ parseMessageRequest.setGrokStatement(grokStatement);
+ parseMessageRequest.setSampleData(sampleData);
+
+ File patternFile = new File("./target/squidTest");
+ FileWriter writer = new FileWriter(patternFile);
+ writer.write(grokStatement);
+ writer.close();
+
+ when(grokService.saveTemporary(grokStatement, "squid")).thenReturn(patternFile);
+
+ assertEquals(new HashMap() {{
+ put("elapsed", 161);
+ put("code", 200);
+ put("ip_dst_addr", "199.27.79.73");
+ put("ip_src_addr", "127.0.0.1");
+ put("action", "TCP_MISS");
+ put("bytes", 103701);
+ put("method", "GET");
+ put("url", "http://www.cnn.com/");
+ put("timestamp", 1461576382642L);
+ put("original_string", "1461576382.642 161 127.0.0.1 TCP_MISS/200 103701 GET http://www.cnn.com/ - DIRECT/199.27.79.73 text/html");
+ }}, sensorParserConfigService.parseMessage(parseMessageRequest));
+
+ }
+
+ @Test
+ public void missingSensorParserConfigShouldThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ ParseMessageRequest parseMessageRequest = new ParseMessageRequest();
+ sensorParserConfigService.parseMessage(parseMessageRequest);
+ }
+
+ @Test
+ public void missingParserClassShouldThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ final SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.setSensorTopic("squid");
+ ParseMessageRequest parseMessageRequest = new ParseMessageRequest();
+ parseMessageRequest.setSensorParserConfig(sensorParserConfig);
+ sensorParserConfigService.parseMessage(parseMessageRequest);
+ }
+
+ @Test
+ public void invalidParserClassShouldThrowRestException() throws Exception {
+ exception.expect(RestException.class);
+
+ final SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.setSensorTopic("squid");
+ sensorParserConfig.setParserClassName("bad.class.package.BadClassName");
+ ParseMessageRequest parseMessageRequest = new ParseMessageRequest();
+ parseMessageRequest.setSensorParserConfig(sensorParserConfig);
+ sensorParserConfigService.parseMessage(parseMessageRequest);
+ }
+
+ private SensorParserConfig getTestBroSensorParserConfig() {
+ SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.setSensorTopic("bro");
+ sensorParserConfig.setParserClassName("org.apache.metron.parsers.bro.BasicBroParser");
+ return sensorParserConfig;
+ }
+
+ private SensorParserConfig getTestSquidSensorParserConfig() {
+ SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ sensorParserConfig.setSensorTopic("squid");
+ sensorParserConfig.setParserClassName("org.apache.metron.parsers.GrokParser");
+ sensorParserConfig.setParserConfig(new HashMap() {{
+ put("grokPath", "/patterns/squid");
+ put("patternLabel", "SQUID_DELIMITED");
+ put("timestampField", "timestamp");
+ }});
+ return sensorParserConfig;
+ }
+
+ }
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StellarServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StellarServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StellarServiceImplTest.java
new file mode 100644
index 0000000..3ddbf56
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StellarServiceImplTest.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.metron.common.configuration.FieldTransformer;
+import org.apache.metron.common.configuration.SensorParserConfig;
+import org.apache.metron.rest.model.SensorParserContext;
+import org.apache.metron.rest.service.StellarService;
+import org.apache.storm.shade.com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class StellarServiceImplTest {
+
+ private StellarService stellarService;
+
+ @Before
+ public void setUp() throws Exception {
+ stellarService = new StellarServiceImpl();
+ }
+
+ @Test
+ public void validateRulesShouldProperlyValidateRules() {
+ List<String> rules = Arrays.asList("TO_LOWER(test)", "BAD_FUNCTION(test)");
+ Map<String, Boolean> results = stellarService.validateRules(rules);
+ assertEquals(2, results.size());
+ assertEquals(true, results.get("TO_LOWER(test)"));
+ assertEquals(false, results.get("BAD_FUNCTION(test)"));
+ }
+
+ @Test
+ public void applyTransformationsShouldProperlyTransformData() {
+ SensorParserConfig sensorParserConfig = new SensorParserConfig();
+ FieldTransformer fieldTransformater = new FieldTransformer();
+ fieldTransformater.setOutput("url_host");
+ fieldTransformater.setTransformation("STELLAR");
+ fieldTransformater.setConfig(new LinkedHashMap<String, Object>() {{
+ put("url_host", "TO_LOWER(URL_TO_HOST(url))");
+ }});
+ sensorParserConfig.setFieldTransformations(ImmutableList.of(fieldTransformater));
+ SensorParserContext sensorParserContext = new SensorParserContext();
+ sensorParserContext.setSensorParserConfig(sensorParserConfig);
+ sensorParserContext.setSampleData(new HashMap<String, Object>() {{
+ put("url", "https://caseystella.com/blog");
+ }});
+ Map<String, Object> results = stellarService.applyTransformations(sensorParserContext);
+ assertEquals(2, results.size());
+ assertEquals("https://caseystella.com/blog", results.get("url"));
+ assertEquals("caseystella.com", results.get("url_host"));
+ }
+
+ @Test
+ public void getTransformationsShouldReturnTransformation() {
+ assertTrue(stellarService.getTransformations().length > 0);
+ }
+
+ @Test
+ public void getStellarFunctionsShouldReturnFunctions() {
+ assertTrue(stellarService.getStellarFunctions().size() > 0);
+ }
+
+ @Test
+ public void getSimpleStellarFunctionsShouldReturnFunctions() {
+ assertEquals(1, stellarService.getSimpleStellarFunctions().stream()
+ .filter(stellarFunctionDescription -> stellarFunctionDescription.getName().equals("TO_LOWER")).count());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormAdminServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormAdminServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormAdminServiceImplTest.java
new file mode 100644
index 0000000..d83a74c
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormAdminServiceImplTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.metron.common.configuration.SensorParserConfig;
+import org.apache.metron.rest.model.TopologyResponse;
+import org.apache.metron.rest.model.TopologyStatusCode;
+import org.apache.metron.rest.service.GlobalConfigService;
+import org.apache.metron.rest.service.SensorParserConfigService;
+import org.apache.metron.rest.service.StormAdminService;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class StormAdminServiceImplTest {
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ StormCLIWrapper stormCLIClientWrapper;
+ StormAdminService stormAdminService;
+ GlobalConfigService globalConfigService;
+ SensorParserConfigService sensorParserConfigService;
+
+ @Before
+ public void setUp() throws Exception {
+ stormCLIClientWrapper = mock(StormCLIWrapper.class);
+ globalConfigService = mock(GlobalConfigService.class);
+ sensorParserConfigService = mock(SensorParserConfigService.class);
+ stormAdminService = new StormAdminServiceImpl(stormCLIClientWrapper, globalConfigService, sensorParserConfigService);
+ }
+
+ @Test
+ public void startParserTopologyShouldProperlyReturnSuccessTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.startParserTopology("bro")).thenReturn(0);
+ when(globalConfigService.get()).thenReturn(new HashMap<String, Object>());
+ when(sensorParserConfigService.findOne("bro")).thenReturn(new SensorParserConfig());
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.STARTED.toString());
+ TopologyResponse actual = stormAdminService.startParserTopology("bro");
+
+ assertEquals(expected, actual);
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
+ @Test
+ public void startParserTopologyShouldReturnGlobalConfigMissingError() throws Exception {
+ when(globalConfigService.get()).thenReturn(null);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage(TopologyStatusCode.GLOBAL_CONFIG_MISSING.toString());
+
+ assertEquals(expected, stormAdminService.startParserTopology("bro"));
+ }
+
+ @Test
+ public void startParserTopologyShouldReturnSensorParserConfigMissingError() throws Exception {
+ when(globalConfigService.get()).thenReturn(new HashMap<String, Object>());
+ when(sensorParserConfigService.findOne("bro")).thenReturn(null);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage(TopologyStatusCode.SENSOR_PARSER_CONFIG_MISSING.toString());
+
+ assertEquals(expected, stormAdminService.startParserTopology("bro"));
+ }
+
+ @Test
+ public void stopParserTopologyShouldProperlyReturnErrorTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.stopParserTopology("bro", false)).thenReturn(1);
+ when(globalConfigService.get()).thenReturn(new HashMap<String, Object>());
+ when(sensorParserConfigService.findOne("bro")).thenReturn(new SensorParserConfig());
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage(TopologyStatusCode.STOP_ERROR.toString());
+
+ assertEquals(expected, stormAdminService.stopParserTopology("bro", false));
+ }
+
+ @Test
+ public void startEnrichmentTopologyShouldProperlyReturnSuccessTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.startEnrichmentTopology()).thenReturn(0);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.STARTED.toString());
+
+ assertEquals(expected, stormAdminService.startEnrichmentTopology());
+ }
+
+ @Test
+ public void stopEnrichmentTopologyShouldProperlyReturnSuccessTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.stopEnrichmentTopology(false)).thenReturn(0);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.STOPPED.toString());
+
+ assertEquals(expected, stormAdminService.stopEnrichmentTopology(false));
+ }
+
+ @Test
+ public void startIndexingTopologyShouldProperlyReturnSuccessTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.startIndexingTopology()).thenReturn(0);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.STARTED.toString());
+
+ assertEquals(expected, stormAdminService.startIndexingTopology());
+ }
+
+ @Test
+ public void stopIndexingTopologyShouldProperlyReturnSuccessTopologyResponse() throws Exception {
+ when(stormCLIClientWrapper.stopIndexingTopology(false)).thenReturn(0);
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.STOPPED.toString());
+
+ assertEquals(expected, stormAdminService.stopIndexingTopology(false));
+ }
+
+ @Test
+ public void getStormClientStatusShouldProperlyReturnStatus() throws Exception {
+ final Map<String, String> status = new HashMap() {{
+ put("status", "statusValue");
+ }};
+ when(stormCLIClientWrapper.getStormClientStatus()).thenReturn(status);
+
+ assertEquals(new HashMap() {{
+ put("status", "statusValue");
+ }}, stormAdminService.getStormClientStatus());
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormCLIWrapperTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormCLIWrapperTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormCLIWrapperTest.java
new file mode 100644
index 0000000..cb26783
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormCLIWrapperTest.java
@@ -0,0 +1,216 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.metron.rest.MetronRestConstants;
+import org.apache.metron.rest.RestException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.core.env.Environment;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyVararg;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+
+@SuppressWarnings("unchecked")
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({DockerStormCLIWrapper.class, ProcessBuilder.class})
+public class StormCLIWrapperTest {
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ private ProcessBuilder processBuilder;
+ private Environment environment;
+ private Process process;
+ private StormCLIWrapper stormCLIWrapper;
+
+ @Before
+ public void setUp() throws Exception {
+ processBuilder = mock(ProcessBuilder.class);
+ environment = mock(Environment.class);
+ process = mock(Process.class);
+ stormCLIWrapper = new StormCLIWrapper();
+ stormCLIWrapper.setEnvironment(environment);
+ }
+
+ @Test
+ public void startParserTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(environment.getProperty(MetronRestConstants.PARSER_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_parser");
+ when(environment.getProperty(MetronRestConstants.KAFKA_BROKER_URL_SPRING_PROPERTY)).thenReturn("kafka_broker_url");
+ when(environment.getProperty(MetronRestConstants.ZK_URL_SPRING_PROPERTY)).thenReturn("zookeeper_url");
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.startParserTopology("bro"));
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("/start_parser", "-k", "kafka_broker_url", "-z", "zookeeper_url", "-s", "bro");
+ }
+
+ @Test
+ public void stopParserTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.stopParserTopology("bro", false));
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("storm", "kill", "bro");
+ }
+
+ @Test
+ public void stopParserTopologyNowShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.stopParserTopology("bro", true));
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("storm", "kill", "bro", "-w", "0");
+ }
+
+ @Test
+ public void startEnrichmentTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(environment.getProperty(MetronRestConstants.ENRICHMENT_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_enrichment");
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.startEnrichmentTopology());
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("/start_enrichment");
+
+ }
+
+ @Test
+ public void stopEnrichmentTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.stopEnrichmentTopology(false));
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("storm", "kill", MetronRestConstants.ENRICHMENT_TOPOLOGY_NAME);
+ }
+
+ @Test
+ public void startIndexingTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(environment.getProperty(MetronRestConstants.INDEXING_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_indexing");
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.startIndexingTopology());
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("/start_indexing");
+
+ }
+
+ @Test
+ public void stopIndexingTopologyShouldRunCommandProperly() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ when(processBuilder.start()).thenReturn(process);
+ when(process.exitValue()).thenReturn(0);
+
+ assertEquals(0, stormCLIWrapper.stopIndexingTopology(false));
+ verify(process).waitFor();
+ verifyNew(ProcessBuilder.class).withArguments("storm", "kill", MetronRestConstants.INDEXING_TOPOLOGY_NAME);
+ }
+
+ @Test
+ public void getStormClientStatusShouldReturnCorrectStatus() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ Process process = mock(Process.class);
+ InputStream inputStream = new ByteArrayInputStream("\nStorm 1.1".getBytes(UTF_8));
+
+ when(processBuilder.start()).thenReturn(process);
+
+ when(process.getInputStream()).thenReturn(inputStream);
+ when(environment.getProperty(MetronRestConstants.PARSER_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_parser");
+ when(environment.getProperty(MetronRestConstants.ENRICHMENT_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_enrichment");
+ when(environment.getProperty(MetronRestConstants.INDEXING_SCRIPT_PATH_SPRING_PROPERTY)).thenReturn("/start_indexing");
+
+
+ Map<String, String> actual = stormCLIWrapper.getStormClientStatus();
+ assertEquals(new HashMap<String, String>() {{
+ put("parserScriptPath", "/start_parser");
+ put("enrichmentScriptPath", "/start_enrichment");
+ put("indexingScriptPath", "/start_indexing");
+ put("stormClientVersionInstalled", "1.1");
+
+ }}, actual);
+ verifyNew(ProcessBuilder.class).withArguments("storm", "version");
+ }
+
+ @Test
+ public void stormClientVersionInstalledShouldReturnDefault() throws Exception {
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+
+ Process process = mock(Process.class);
+ InputStream inputStream = new ByteArrayInputStream("".getBytes(UTF_8));
+
+ when(processBuilder.start()).thenReturn(process);
+ when(process.getInputStream()).thenReturn(inputStream);
+ assertEquals("Storm client is not installed", stormCLIWrapper.stormClientVersionInstalled());
+ }
+
+ @Test
+ public void runCommandShouldReturnRestExceptionOnError() throws Exception {
+ exception.expect(RestException.class);
+
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+ when(processBuilder.start()).thenThrow(new IOException());
+
+ stormCLIWrapper.runCommand(new String[]{"storm", "kill"});
+ }
+
+ @Test
+ public void stormClientVersionInstalledShouldReturnRestExceptionOnError() throws Exception {
+ exception.expect(RestException.class);
+
+ whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg()).thenReturn(processBuilder);
+ when(processBuilder.start()).thenThrow(new IOException());
+
+ stormCLIWrapper.stormClientVersionInstalled();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormStatusServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormStatusServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormStatusServiceImplTest.java
new file mode 100644
index 0000000..db2cb7f
--- /dev/null
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/StormStatusServiceImplTest.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.metron.rest.model.TopologyResponse;
+import org.apache.metron.rest.model.TopologyStatus;
+import org.apache.metron.rest.model.TopologyStatusCode;
+import org.apache.metron.rest.model.TopologySummary;
+import org.apache.metron.rest.service.StormStatusService;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.core.env.Environment;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.metron.rest.MetronRestConstants.STORM_UI_SPRING_PROPERTY;
+import static org.apache.metron.rest.MetronRestConstants.TOPOLOGY_SUMMARY_URL;
+import static org.apache.metron.rest.MetronRestConstants.TOPOLOGY_URL;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class StormStatusServiceImplTest {
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ Environment environment;
+ RestTemplate restTemplate;
+ StormStatusService stormStatusService;
+
+ @Before
+ public void setUp() throws Exception {
+ environment = mock(Environment.class);
+ restTemplate = mock(RestTemplate.class);
+ stormStatusService = new StormStatusServiceImpl(environment, restTemplate);
+ }
+
+ @Test
+ public void getTopologySummaryShouldReturnTopologySummary() throws Exception {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setStatus(TopologyStatusCode.STARTED);
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+
+ TopologyStatus expectedStatus = new TopologyStatus();
+ expectedStatus.setStatus(TopologyStatusCode.STARTED);
+ expectedStatus.setName("bro");
+ expectedStatus.setId("bro_id");
+ TopologySummary expected = new TopologySummary();
+ expected.setTopologies(new TopologyStatus[]{expectedStatus});
+
+ TopologySummary actual = stormStatusService.getTopologySummary();
+ assertEquals(expected, actual);
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
+ @Test
+ public void getTopologyStatusShouldReturnTopologyStatus() throws Exception {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setStatus(TopologyStatusCode.STARTED);
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id", TopologyStatus.class)).thenReturn(topologyStatus);
+
+ TopologyStatus expected = new TopologyStatus();
+ expected.setStatus(TopologyStatusCode.STARTED);
+ expected.setName("bro");
+ expected.setId("bro_id");
+
+ TopologyStatus actual = stormStatusService.getTopologyStatus("bro");
+ assertEquals(expected, actual);
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
+ @Test
+ public void getAllTopologyStatusShouldReturnAllTopologyStatus() {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setStatus(TopologyStatusCode.STARTED);
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id", TopologyStatus.class)).thenReturn(topologyStatus);
+
+ TopologyStatus expected = new TopologyStatus();
+ expected.setStatus(TopologyStatusCode.STARTED);
+ expected.setName("bro");
+ expected.setId("bro_id");
+
+ assertEquals(new ArrayList() {{ add(expected); }}, stormStatusService.getAllTopologyStatus());
+ }
+
+
+ @Test
+ public void activateTopologyShouldReturnActiveTopologyResponse() {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.postForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id/activate", null, Map.class))
+ .thenReturn(new HashMap() {{ put("status", "success"); }});
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.ACTIVE.toString());
+ assertEquals(expected, stormStatusService.activateTopology("bro"));
+ }
+
+ @Test
+ public void activateTopologyShouldReturnErrorTopologyResponse() {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.postForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id/activate", null, Map.class))
+ .thenReturn(new HashMap() {{ put("status", "error message"); }});
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage("error message");
+ assertEquals(expected, stormStatusService.activateTopology("bro"));
+ }
+
+ @Test
+ public void activateTopologyShouldReturnTopologyNotFoundTopologyResponse() {
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(new TopologySummary());
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage(TopologyStatusCode.TOPOLOGY_NOT_FOUND.toString());
+ assertEquals(expected, stormStatusService.activateTopology("bro"));
+ }
+
+ @Test
+ public void deactivateTopologyShouldReturnActiveTopologyResponse() {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.postForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id/deactivate", null, Map.class))
+ .thenReturn(new HashMap() {{ put("status", "success"); }});
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setSuccessMessage(TopologyStatusCode.INACTIVE.toString());
+ assertEquals(expected, stormStatusService.deactivateTopology("bro"));
+ }
+
+ @Test
+ public void deactivateTopologyShouldReturnErrorTopologyResponse() {
+ final TopologyStatus topologyStatus = new TopologyStatus();
+ topologyStatus.setName("bro");
+ topologyStatus.setId("bro_id");
+ final TopologySummary topologySummary = new TopologySummary();
+ topologySummary.setTopologies(new TopologyStatus[]{topologyStatus});
+
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(topologySummary);
+ when(restTemplate.postForObject("http://storm_ui" + TOPOLOGY_URL + "/bro_id/deactivate", null, Map.class))
+ .thenReturn(new HashMap() {{ put("status", "error message"); }});
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage("error message");
+ assertEquals(expected, stormStatusService.deactivateTopology("bro"));
+ }
+
+ @Test
+ public void deactivateTopologyShouldReturnTopologyNotFoundTopologyResponse() {
+ when(environment.getProperty(STORM_UI_SPRING_PROPERTY)).thenReturn("storm_ui");
+ when(restTemplate.getForObject("http://storm_ui" + TOPOLOGY_SUMMARY_URL, TopologySummary.class)).thenReturn(new TopologySummary());
+
+ TopologyResponse expected = new TopologyResponse();
+ expected.setErrorMessage(TopologyStatusCode.TOPOLOGY_NOT_FOUND.toString());
+ assertEquals(expected, stormStatusService.deactivateTopology("bro"));
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/metron-rest/src/test/resources/README.vm
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/resources/README.vm b/metron-interface/metron-rest/src/test/resources/README.vm
index f259a91..99f4286 100644
--- a/metron-interface/metron-rest/src/test/resources/README.vm
+++ b/metron-interface/metron-rest/src/test/resources/README.vm
@@ -1,66 +1,83 @@
-#[[#]]# Metron REST and Configuration UI
+#[[#]]# Metron REST
-This UI exposes and aids in sensor configuration.
+This module provides a RESTful API for interacting with Metron.
#[[##]]# Prerequisites
* A running Metron cluster
-* A running instance of MySQL
* Java 8 installed
* Storm CLI and Metron topology scripts (start_parser_topology.sh, start_enrichment_topology.sh, start_elasticsearch_topology.sh) installed
#[[##]]# Installation
-1. Package the Application with Maven:
- ```
- mvn clean package
- ```
+1. Package the application with Maven:
+```
+mvn clean package
+```
1. Untar the archive in the target directory. The directory structure will look like:
- ```
- bin
- start.sh
- lib
- metron-rest-version.jar
- ```
+```
+bin
+ start_metron_rest.sh
+lib
+ metron-rest-$METRON_VERSION.jar
+```
-1. Install Hibernate by downloading version 5.0.11.Final from (http://hibernate.org/orm/downloads/). Unpack the archive and set the HIBERNATE_HOME environment variable to the absolute path of the top level directory.
- ```
- export HIBERNATE_HOME=/path/to/hibernate-release-5.0.11.Final
- ```
+1. Create an `application.yml` file with the contents of [application-docker.yml](src/main/resources/application-docker.yml). Substitute the appropriate Metron service urls (Kafka, Zookeeper, Storm, etc) in properties containing `${docker.host.address}` and update the `spring.datasource.*` properties as needed (see the [Security](#security) section for more details).
-1. Install the MySQL client by downloading version 5.1.40 from (https://dev.mysql.com/downloads/connector/j/). Unpack the archive and set the MYSQL_CLIENT_HOME environment variable to the absolute path of the top level directory.
- ```
- export MYSQL_CLIENT_HOME=/path/to/mysql-connector-java-5.1.40
- ```
+1. Start the application with this command:
+```
+./bin/start_metron_rest.sh /path/to/application.yml
+```
-1. Create a MySQL user for the Config UI (http://dev.mysql.com/doc/refman/5.7/en/adding-users.html).
+#[[##]]# Usage
-1. Create a Config UI database in MySQL with this command:
- ```
- CREATE DATABASE IF NOT EXISTS metronrest
- ```
+The exposed REST endpoints can be accessed with the Swagger UI at http://host:port/swagger-ui.html#/. The default port is 8080 but can be changed in application.yml by setting "server.port" to the desired port.
-1. Create an `application.yml` file with the contents of [application-docker.yml](src/main/resources/application-docker.yml). Substitute the appropriate Metron service urls (Kafka, Zookeeper, Storm, etc) in properties containing `${docker.host.address}` and update the `spring.datasource.username` and `spring.datasource.password` properties using the MySQL credentials from step 4.
+#[[##]]# Security
-1. Start the UI with this command:
- ```
- ./bin/start.sh /path/to/application.yml
- ```
+The metron-rest module uses [Spring Security](http://projects.spring.io/spring-security/) for authentication and stores user credentials in a relational database. The H2 database is configured by default and is intended only for development purposes. The "dev" profile can be used to automatically load test users:
+```
+./bin/start_metron_rest.sh /path/to/application.yml --spring.profiles.active=dev
+```
-#[[##]]# Usage
+For [production use](http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-connect-to-production-database), a relational database should be configured. For example, configuring MySQL would be done as follows:
+
+1. Create a MySQL user for the Metron REST application (http://dev.mysql.com/doc/refman/5.7/en/adding-users.html).
+
+1. Connect to MySQL and create a Metron REST database:
+```
+CREATE DATABASE IF NOT EXISTS metronrest
+```
-The exposed REST endpoints can be accessed with the Swagger UI at http://host:port/swagger-ui.html#/. The default port is 8080 but can be changed in application.yml by setting "server.port" to the desired port. Users can be added with this SQL statement:
+1. Add users:
```
use metronrest;
insert into users (username, password, enabled) values ('your_username','your_password',1);
insert into authorities (username, authority) values ('your_username', 'ROLE_USER');
```
-Users can be added to additional groups with this SQL statement:
+
+1. Replace the H2 connection information in the application.yml file with MySQL connection information:
+```
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://mysql_host:3306/metronrest
+ username: metron_rest_user
+ password: metron_rest_password
+ platform: mysql
```
-use metronrest;
-insert into authorities (username, authority) values ('your_username', 'your_group');
+
+1. Add a dependency for the MySQL JDBC connector in the metron-rest pom.xml:
+```
+<dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>${mysql.client.version}</version>
+</dependency>
```
+1. Follow the steps in the [Installation](#installation) section
+
#[[##]]# API
Request and Response objects are JSON formatted. The JSON schemas are available in the Swagger UI.
@@ -86,6 +103,38 @@ Request and Response objects are JSON formatted. The JSON schemas are available
#end
#end
+#[[##]]# Testing
+
+Profiles are includes for both the metron-docker and Quick Dev environments.
+
+#[[###]]# metron-docker
+
+Start the [metron-docker](../../metron-docker) environment. Build the metron-rest module and start it with the Spring Boot Maven plugin:
+```
+mvn clean package
+mvn spring-boot:run -Drun.profiles=docker,dev
+```
+The metron-rest application will be available at http://localhost:8080/swagger-ui.html#/.
+
+#[[###]]# Quick Dev
+
+Start the [Quick Dev](../../metron-deployment/vagrant/quick-dev-platform) environment. Build the metron-rest module and start it with the Spring Boot Maven plugin:
+```
+mvn clean package
+mvn spring-boot:run -Drun.profiles=vagrant,dev
+```
+The metron-rest application will be available at http://localhost:8080/swagger-ui.html#/.
+
+To run the application locally on the Quick Dev host, package the application and scp the archive to node1:
+```
+mvn clean package
+scp ./target/metron-rest-$METRON_VERSION-archive.tar.gz root@node1:~/
+```
+Login to node1 and unarchive the metron-rest application. Start the application on a different port to avoid conflicting with Ambari:
+```
+java -jar ./lib/metron-rest-$METRON_VERSION.jar --spring.profiles.active=vagrant,dev --server.port=8082
+```
+The metron-rest application will be available at http://node1:8082/swagger-ui.html#/.
#[[##]]# License
http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/e6628499/metron-interface/pom.xml
----------------------------------------------------------------------
diff --git a/metron-interface/pom.xml b/metron-interface/pom.xml
index 078da19..805c024 100644
--- a/metron-interface/pom.xml
+++ b/metron-interface/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.apache.metron</groupId>
<artifactId>Metron</artifactId>
- <version>0.3.0</version>
+ <version>0.3.1</version>
</parent>
<description>Interfaces for Metron</description>
<url>https://metron.incubator.apache.org/</url>