summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorawudzins <adam.wudzinski@nokia.com>2020-01-13 11:43:08 +0100
committerawudzins <adam.wudzinski@nokia.com>2020-01-17 14:39:20 +0100
commitab6421bcf7b480f9955b6b4376554ec9677e71ed (patch)
tree347d29e9629a04888daf1fd216284f15b72a7149
parent7e5a7d1d8cd74e42c8549e02724ec2df589e4117 (diff)
Changed EventTransformation schema to be loaded only once
Issue-ID: DCAEGEN2-1774 Signed-off-by: adamwudzinski <adam.wudzinski@nokia.com> Change-Id: I50f3da2c11201a40be948ab199aaca89bbbb38db
-rw-r--r--pom.xml6
-rw-r--r--src/main/java/org/onap/dcae/ApplicationSettings.java53
-rw-r--r--src/main/java/org/onap/dcae/VesApplication.java23
-rw-r--r--src/main/java/org/onap/dcae/common/EventTransformation.java (renamed from src/main/java/org/onap/dcae/common/Event.java)5
-rw-r--r--src/main/java/org/onap/dcae/common/EventUpdater.java28
-rw-r--r--src/main/java/org/onap/dcae/common/HeaderUtils.java2
-rw-r--r--src/main/java/org/onap/dcae/restapi/EventValidator.java8
-rw-r--r--src/test/java/org/onap/dcae/ApplicationSettingsTest.java8
-rw-r--r--src/test/java/org/onap/dcae/restapi/EventValidatorTest.java29
-rw-r--r--src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java159
-rw-r--r--src/test/resources/api_version_config.json7
-rw-r--r--src/test/resources/eventTransform.json396
12 files changed, 653 insertions, 71 deletions
diff --git a/pom.xml b/pom.xml
index 5dfcaf48..4bdad84f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -439,6 +439,12 @@
<artifactId>api-custom-header</artifactId>
<version>1.1.4</version>
</dependency>
+ <dependency>
+ <groupId>org.functionaljava</groupId>
+ <artifactId>functionaljava</artifactId>
+ <version>4.8.1</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<repositories>
<repository>
diff --git a/src/main/java/org/onap/dcae/ApplicationSettings.java b/src/main/java/org/onap/dcae/ApplicationSettings.java
index 1e9ae698..8458df8d 100644
--- a/src/main/java/org/onap/dcae/ApplicationSettings.java
+++ b/src/main/java/org/onap/dcae/ApplicationSettings.java
@@ -3,7 +3,7 @@
* PROJECT
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright (C) 2018 - 2019 Nokia. All rights reserved.s
+ * Copyright (C) 2018 - 2020 Nokia. All rights reserved.s
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,21 +21,28 @@
package org.onap.dcae;
+import static java.lang.String.format;
+
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
import com.networknt.schema.JsonSchema;
import io.vavr.Function1;
import io.vavr.collection.HashMap;
-import io.vavr.collection.List;
import io.vavr.collection.Map;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import javax.annotation.Nullable;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
+import org.onap.dcae.common.EventTransformation;
import org.onap.dcae.common.configuration.AuthMethodType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import static java.lang.String.format;
/**
* Abstraction over application configuration.
@@ -43,13 +50,16 @@ import static java.lang.String.format;
*/
public class ApplicationSettings {
+ private static final String EVENT_TRANSFORM_FILE_PATH = "./etc/eventTransform.json";
+ private static final String COULD_NOT_FIND_FILE = "Couldn't find file " + EVENT_TRANSFORM_FILE_PATH;
+
private static final Logger log = LoggerFactory.getLogger(ApplicationSettings.class);
private static final String FALLBACK_VES_VERSION = "v5";
private final String appInvocationDir;
private final String configurationFileLocation;
private final PropertiesConfiguration properties = new PropertiesConfiguration();
- private final JSonSchemasSupplier jSonSchemasSupplier = new JSonSchemasSupplier();
private final Map<String, JsonSchema> loadedJsonSchemas;
+ private final List<EventTransformation> eventTransformations;
public ApplicationSettings(String[] args, Function1<String[], Map<String, String>> argsParser) {
this(args, argsParser, System.getProperty("user.dir"));
@@ -64,7 +74,8 @@ public class ApplicationSettings {
parsedArgs.filterKeys(k -> !"c".equals(k)).forEach(this::addOrUpdate);
String collectorSchemaFile = properties.getString("collector.schema.file",
format("{\"%s\":\"etc/CommonEventFormat_28.4.1.json\"}", FALLBACK_VES_VERSION));
- loadedJsonSchemas = jSonSchemasSupplier.loadJsonSchemas(collectorSchemaFile);
+ loadedJsonSchemas = new JSonSchemasSupplier().loadJsonSchemas(collectorSchemaFile);
+ eventTransformations = loadEventTransformations();
}
public void reloadProperties() {
@@ -76,22 +87,22 @@ public class ApplicationSettings {
throw new ApplicationException(ex);
}
}
+
public Map<String, String> validAuthorizationCredentials() {
return prepareUsersMap(properties.getString("header.authlist", null));
}
-
public Path configurationFileLocation() {
return Paths.get(configurationFileLocation);
}
- public boolean jsonSchemaValidationEnabled() {
+ public boolean eventSchemaValidationEnabled() {
return properties.getInt("collector.schema.checkflag", -1) > 0;
}
public JsonSchema jsonSchema(String version) {
return loadedJsonSchemas.get(version)
- .orElse(loadedJsonSchemas.get(FALLBACK_VES_VERSION))
- .getOrElseThrow(() -> new IllegalStateException("No fallback schema present in application."));
+ .orElse(loadedJsonSchemas.get(FALLBACK_VES_VERSION))
+ .getOrElseThrow(() -> new IllegalStateException("No fallback schema present in application."));
}
public boolean isVersionSupported(String version){
@@ -159,6 +170,10 @@ public class ApplicationSettings {
}
}
+ public List<EventTransformation> getEventTransformations() {
+ return eventTransformations;
+ }
+
private void loadPropertiesFromFile() {
try {
properties.load(configurationFileLocation);
@@ -182,7 +197,7 @@ public class ApplicationSettings {
private Map<String, String> prepareUsersMap(@Nullable String allowedUsers) {
return allowedUsers == null ? HashMap.empty()
- : List.of(allowedUsers.split("\\|"))
+ : io.vavr.collection.List.of(allowedUsers.split("\\|"))
.map(t->t.split(","))
.toMap(t-> t[0].trim(), t -> t[1].trim());
}
@@ -205,6 +220,18 @@ public class ApplicationSettings {
return filePath;
}
+ private List<EventTransformation> loadEventTransformations() {
+ Type EVENT_TRANSFORM_LIST_TYPE = new TypeToken<List<EventTransformation>>() {}.getType();
+
+ try (FileReader fr = new FileReader(EVENT_TRANSFORM_FILE_PATH)) {
+ log.info("parse " + EVENT_TRANSFORM_FILE_PATH + " file");
+ return new Gson().fromJson(fr, EVENT_TRANSFORM_LIST_TYPE);
+ } catch (IOException e) {
+ log.error(COULD_NOT_FIND_FILE, e);
+ throw new ApplicationException(COULD_NOT_FIND_FILE, e);
+ }
+ }
+
@VisibleForTesting
String getStringDirectly(String key) {
return properties.getString(key);
diff --git a/src/main/java/org/onap/dcae/VesApplication.java b/src/main/java/org/onap/dcae/VesApplication.java
index e3340820..bc5b1a8f 100644
--- a/src/main/java/org/onap/dcae/VesApplication.java
+++ b/src/main/java/org/onap/dcae/VesApplication.java
@@ -3,6 +3,7 @@
* PROJECT
* ================================================================================
* Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020 Nokia. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +48,7 @@ public class VesApplication {
private static final Logger incomingRequestsLogger = LoggerFactory.getLogger("org.onap.dcae.common.input");
private static final Logger oplog = LoggerFactory.getLogger("org.onap.dcae.common.output");
private static final Logger errorLog = LoggerFactory.getLogger("org.onap.dcae.common.error");
- private static ApplicationSettings properties;
+ private static ApplicationSettings applicationSettings;
private static ConfigurableApplicationContext context;
private static ConfigLoader configLoader;
private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
@@ -57,7 +58,7 @@ public class VesApplication {
public static void main(String[] args) {
app = new SpringApplication(VesApplication.class);
- properties = new ApplicationSettings(args, CLIUtils::processCmdLine);
+ applicationSettings = new ApplicationSettings(args, CLIUtils::processCmdLine);
scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
init();
app.setAddCommandLineProperties(true);
@@ -68,7 +69,7 @@ public class VesApplication {
public static void restartApplication() {
Thread thread = new Thread(() -> {
context.close();
- properties.reloadProperties();
+ applicationSettings.reloadProperties();
scheduleFeatures.cancel(true);
init();
context = SpringApplication.run(VesApplication.class);
@@ -89,32 +90,32 @@ public class VesApplication {
private static void createSchedulePoolExecutor() {
scheduleFeatures = scheduledThreadPoolExecutor.scheduleAtFixedRate(configLoader::updateConfig,
- properties.configurationUpdateFrequency(),
- properties.configurationUpdateFrequency(),
+ applicationSettings.configurationUpdateFrequency(),
+ applicationSettings.configurationUpdateFrequency(),
TimeUnit.MINUTES);
}
private static void createConfigLoader() {
configLoader = ConfigLoader.create(getEventPublisher()::reconfigure,
- Paths.get(properties.dMaaPConfigurationFileLocation()),
- properties.configurationFileLocation());
+ Paths.get(applicationSettings.dMaaPConfigurationFileLocation()),
+ applicationSettings.configurationFileLocation());
}
private static EventPublisher getEventPublisher() {
return EventPublisher.createPublisher(oplog, DMaaPConfigurationParser
- .parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get());
+ .parseToDomainMapping(Paths.get(applicationSettings.dMaaPConfigurationFileLocation())).get());
}
private static Map<String, PublisherConfig> getDmapConfig() {
return DMaaPConfigurationParser
- .parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get();
+ .parseToDomainMapping(Paths.get(applicationSettings.dMaaPConfigurationFileLocation())).get();
}
@Bean
@Lazy
public ApplicationSettings applicationSettings() {
- return properties;
+ return applicationSettings;
}
@Bean
@@ -132,7 +133,7 @@ public class VesApplication {
@Bean
@Qualifier("eventSender")
public EventSender eventSender() {
- return new EventSender(eventPublisher,properties);
+ return new EventSender(eventPublisher, applicationSettings);
}
}
diff --git a/src/main/java/org/onap/dcae/common/Event.java b/src/main/java/org/onap/dcae/common/EventTransformation.java
index 1fa8179e..f85fd2de 100644
--- a/src/main/java/org/onap/dcae/common/Event.java
+++ b/src/main/java/org/onap/dcae/common/EventTransformation.java
@@ -3,6 +3,7 @@
* PROJECT
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020 Nokia. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,11 +24,11 @@ import com.google.gson.JsonObject;
import java.util.List;
-class Event {
+public class EventTransformation {
final JsonObject filter;
final List<Processor> processors;
- Event(JsonObject filter, List<Processor> processors) {
+ EventTransformation(JsonObject filter, List<Processor> processors) {
this.filter = filter;
this.processors = processors;
}
diff --git a/src/main/java/org/onap/dcae/common/EventUpdater.java b/src/main/java/org/onap/dcae/common/EventUpdater.java
index 1caa4f18..1469d47e 100644
--- a/src/main/java/org/onap/dcae/common/EventUpdater.java
+++ b/src/main/java/org/onap/dcae/common/EventUpdater.java
@@ -3,7 +3,7 @@
* PROJECT
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright (C) 2019 Nokia. All rights reserved.s
+ * Copyright (C) 2020 Nokia. All rights reserved.s
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,18 +21,12 @@
package org.onap.dcae.common;
-import com.google.common.reflect.TypeToken;
-import com.google.gson.Gson;
-import java.io.FileReader;
-import java.io.IOException;
-import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONObject;
-import org.onap.dcae.ApplicationException;
import org.onap.dcae.ApplicationSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,12 +37,9 @@ public class EventUpdater {
private static final String EVENT = "event";
private static final String VES_UNIQUE_ID = "VESuniqueId";
private static final String VES_VERSION = "VESversion";
- private static final String COULD_NOT_FIND_FILE = "Couldn't find file ./etc/eventTransform.json";
- private static final Type EVENT_LIST_TYPE = new TypeToken<List<Event>>() {}.getType();
private static final Logger log = LoggerFactory.getLogger(EventSender.class);
private static final String EVENT_LITERAL = "event";
private static final String COMMON_EVENT_HEADER = "commonEventHeader";
- private static final String EVENT_TRANSFORM = "./etc/eventTransform.json";
private ApplicationSettings settings;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MM dd yyyy hh:mm:ss z");
@@ -87,18 +78,15 @@ public class EventUpdater {
private JSONObject overrideEvent(JSONObject event) {
JSONObject jsonObject = addCurrentTimeToEvent(event);
+
if (settings.eventTransformingEnabled()) {
- try (FileReader fr = new FileReader(EVENT_TRANSFORM)) {
- log.info("parse " + EVENT_TRANSFORM + " file");
- List<Event> events = new Gson().fromJson(fr, EVENT_LIST_TYPE);
- parseEventsJson(events, new ConfigProcessorAdapter(new ConfigProcessors(jsonObject)));
- } catch (IOException e) {
- log.error(COULD_NOT_FIND_FILE, e);
- throw new ApplicationException(COULD_NOT_FIND_FILE, e);
- }
+ List<EventTransformation> eventTransformations = settings.getEventTransformations();
+ applyMatchingTransformations(eventTransformations, new ConfigProcessorAdapter(new ConfigProcessors(jsonObject)));
}
+
if (jsonObject.has(VES_VERSION))
jsonObject.remove(VES_VERSION);
+
log.debug("Modified event:" + jsonObject);
return jsonObject;
}
@@ -112,8 +100,8 @@ public class EventUpdater {
return event;
}
- private void parseEventsJson(List<Event> eventsTransform, ConfigProcessorAdapter configProcessorAdapter) {
- for (Event eventTransform : eventsTransform) {
+ private void applyMatchingTransformations(List<EventTransformation> eventsTransforms, ConfigProcessorAdapter configProcessorAdapter) {
+ for (EventTransformation eventTransform : eventsTransforms) {
JSONObject filterObj = new JSONObject(eventTransform.filter.toString());
if (configProcessorAdapter.isFilterMet(filterObj)) {
callProcessorsMethod(configProcessorAdapter, eventTransform.processors);
diff --git a/src/main/java/org/onap/dcae/common/HeaderUtils.java b/src/main/java/org/onap/dcae/common/HeaderUtils.java
index a5703091..c046fb4c 100644
--- a/src/main/java/org/onap/dcae/common/HeaderUtils.java
+++ b/src/main/java/org/onap/dcae/common/HeaderUtils.java
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
* @author nil
*/
@Component
-public final class HeaderUtils {
+public class HeaderUtils {
public String getApiVerFilePath(String fileName) {
return Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource(fileName))
diff --git a/src/main/java/org/onap/dcae/restapi/EventValidator.java b/src/main/java/org/onap/dcae/restapi/EventValidator.java
index 009247c0..3261c3b3 100644
--- a/src/main/java/org/onap/dcae/restapi/EventValidator.java
+++ b/src/main/java/org/onap/dcae/restapi/EventValidator.java
@@ -3,7 +3,7 @@
* PROJECT
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright (C) 2019 Nokia. All rights reserved.s
+ * Copyright (C) 2020 Nokia. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,12 +20,10 @@
*/
package org.onap.dcae.restapi;
+import java.util.Optional;
import org.json.JSONObject;
import org.onap.dcae.ApplicationSettings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
-import java.util.Optional;
public class EventValidator {
private final SchemaValidator schemaValidator = new SchemaValidator();
@@ -36,7 +34,7 @@ public class EventValidator {
}
public Optional<ResponseEntity<String>> validate(JSONObject jsonObject, String type, String version){
- if (applicationSettings.jsonSchemaValidationEnabled()) {
+ if (applicationSettings.eventSchemaValidationEnabled()) {
if (jsonObject.has(type)) {
if (!schemaValidator.conformsToSchema(jsonObject, applicationSettings.jsonSchema(version))) {
return errorResponse(ApiException.SCHEMA_VALIDATION_FAILED);
diff --git a/src/test/java/org/onap/dcae/ApplicationSettingsTest.java b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java
index c4ba586e..3d8a1a1e 100644
--- a/src/test/java/org/onap/dcae/ApplicationSettingsTest.java
+++ b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* org.onap.dcaegen2.collectors.ves
* ================================================================================
- * Copyright (C) 2018 - 2019 Nokia. All rights reserved.
+ * Copyright (C) 2018 - 2020 Nokia. All rights reserved.
* Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -244,7 +244,7 @@ public class ApplicationSettingsTest {
public void shouldTellIfSchemaValidationIsEnabled() throws IOException {
// when
boolean jsonSchemaValidationEnabled = fromTemporaryConfiguration("collector.schema.checkflag=1")
- .jsonSchemaValidationEnabled();
+ .eventSchemaValidationEnabled();
// then
assertTrue(jsonSchemaValidationEnabled);
@@ -253,7 +253,7 @@ public class ApplicationSettingsTest {
@Test
public void shouldByDefaultSchemaValidationBeDisabled() throws IOException {
// when
- boolean jsonSchemaValidationEnabled = fromTemporaryConfiguration().jsonSchemaValidationEnabled();
+ boolean jsonSchemaValidationEnabled = fromTemporaryConfiguration().eventSchemaValidationEnabled();
// then
assertFalse(jsonSchemaValidationEnabled);
@@ -422,4 +422,4 @@ public class ApplicationSettingsTest {
private String sanitizePath(String path) {
return Paths.get(path).toString();
}
-} \ No newline at end of file
+}
diff --git a/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java b/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java
index 4ac3c487..53595100 100644
--- a/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java
+++ b/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* org.onap.dcaegen2.collectors.ves
* ================================================================================
- * Copyright (C) 2019 Nokia. All rights reserved.
+ * Copyright (C) 2020 Nokia. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,13 @@
package org.onap.dcae.restapi;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
+import java.util.Optional;
import org.json.JSONObject;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -32,13 +37,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.onap.dcae.ApplicationSettings;
import org.springframework.http.ResponseEntity;
-import java.io.IOException;
-import java.util.Optional;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
@ExtendWith(MockitoExtension.class)
public class EventValidatorTest {
private static final String DUMMY_SCHEMA_VERSION = "v5";
@@ -60,7 +58,7 @@ public class EventValidatorTest {
@Test
public void shouldReturnEmptyOptionalOnJsonSchemaValidationDisabled() {
//given
- when(settings.jsonSchemaValidationEnabled()).thenReturn(false);
+ when(settings.eventSchemaValidationEnabled()).thenReturn(false);
//when
Optional<ResponseEntity<String>> result = sut.validate(jsonObject, DUMMY_TYPE, DUMMY_SCHEMA_VERSION);
@@ -73,7 +71,7 @@ public class EventValidatorTest {
@Test
public void shouldReturnInvalidJsonErrorOnWrongType() {
//given
- when(settings.jsonSchemaValidationEnabled()).thenReturn(true);
+ when(settings.eventSchemaValidationEnabled()).thenReturn(true);
//when
Optional<ResponseEntity<String>> result = sut.validate(jsonObject, "wrongType", DUMMY_SCHEMA_VERSION);
@@ -83,11 +81,11 @@ public class EventValidatorTest {
}
@Test
- public void shouldReturnSchemaValidationFailedErrorOnInvalidJsonObjectSchema() throws IOException {
+ public void shouldReturnSchemaValidationFailedErrorOnInvalidJsonObjectSchema() {
//given
String schemaRejectingEverything = "{\"not\":{}}";
mockJsonSchema(schemaRejectingEverything);
- when(settings.jsonSchemaValidationEnabled()).thenReturn(true);
+ when(settings.eventSchemaValidationEnabled()).thenReturn(true);
//when
Optional<ResponseEntity<String>> result = sut.validate(jsonObject, DUMMY_TYPE, DUMMY_SCHEMA_VERSION);
@@ -97,11 +95,11 @@ public class EventValidatorTest {
}
@Test
- public void shouldReturnEmptyOptionalOnValidJsonObjectSchema() throws IOException {
+ public void shouldReturnEmptyOptionalOnValidJsonObjectSchema() {
//given
String schemaAcceptingEverything = "{}";
mockJsonSchema(schemaAcceptingEverything);
- when(settings.jsonSchemaValidationEnabled()).thenReturn(true);
+ when(settings.eventSchemaValidationEnabled()).thenReturn(true);
//when
Optional<ResponseEntity<String>> result = sut.validate(jsonObject, DUMMY_TYPE, DUMMY_SCHEMA_VERSION);
@@ -110,6 +108,7 @@ public class EventValidatorTest {
assertEquals(Optional.empty(), result);
}
+
private void mockJsonSchema(String jsonSchemaContent) {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance();
@@ -121,4 +120,4 @@ public class EventValidatorTest {
return Optional.of(ResponseEntity.status(schemaValidationFailed.httpStatusCode)
.body(schemaValidationFailed.toJSON().toString()));
}
-} \ No newline at end of file
+}
diff --git a/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java b/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java
new file mode 100644
index 00000000..444e28e6
--- /dev/null
+++ b/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java
@@ -0,0 +1,159 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.s
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.restapi;
+
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONArray;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.dcae.ApplicationSettings;
+import org.onap.dcae.common.EventSender;
+import org.onap.dcae.common.EventTransformation;
+import org.onap.dcae.common.HeaderUtils;
+import org.slf4j.Logger;
+import org.springframework.http.ResponseEntity;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VesRestControllerTest {
+
+ private static final String EVENT_TRANSFORM_FILE_PATH = "/eventTransform.json";
+
+ @InjectMocks
+ VesRestController vesRestController;
+
+ @Mock
+ ApplicationSettings applicationSettings;
+
+ @Mock
+ Logger logger;
+
+ @Mock
+ EventSender eventSender;
+
+ @Mock
+ HeaderUtils headerUtils;
+
+ @Test
+ public void shouldReportThatApiVersionIsNotSupported() {
+ // given
+ when(applicationSettings.isVersionSupported("v20")).thenReturn(false);
+ MockHttpServletRequest request = givenMockHttpServletRequest();
+
+ // when
+ final ResponseEntity<String> event = vesRestController.event("", "v20", request);
+
+ // then
+ assertThat(event.getStatusCodeValue()).isEqualTo(400);
+ assertThat(event.getBody()).isEqualTo("API version v20 is not supported");
+ verify(eventSender, never()).send(any(JSONArray.class));
+ }
+
+ @Test
+ public void shouldTransformEventAccordingToEventTransformFile() throws IOException {
+ //given
+ configureEventTransformations();
+ configureHeadersForEventListener();
+
+ MockHttpServletRequest request = givenMockHttpServletRequest();
+
+ String validEvent = new String(
+ Files.readAllBytes(Paths.get(this.getClass().getResource("/ves7_valid.json").getPath()))
+ );
+
+ //when
+ final ResponseEntity<String> response = vesRestController.event(validEvent, "v7", request);
+
+ //then
+ assertThat(response.getStatusCodeValue()).isEqualTo(202);
+ assertThat(response.getBody()).isEqualTo("Accepted");
+ verifyThatTransformedEventWasSend(eventSender, validEvent);
+ }
+
+ private void configureEventTransformations() throws IOException {
+ final List<EventTransformation> eventTransformations = loadEventTransformations();
+ when(applicationSettings.isVersionSupported("v7")).thenReturn(true);
+ when(applicationSettings.eventTransformingEnabled()).thenReturn(true);
+ when(applicationSettings.getEventTransformations()).thenReturn(eventTransformations);
+ }
+
+ private void configureHeadersForEventListener() {
+ when(headerUtils.getRestApiIdentify(anyString())).thenReturn("eventListener");
+ when(headerUtils.getApiVerFilePath(anyString())).thenReturn(
+ this.getClass().getResource("/api_version_config.json").getPath()
+ );
+ }
+
+ private void verifyThatTransformedEventWasSend(EventSender eventSender, String eventBeforeTransformation) {
+ // event before transformation
+ assertThat(eventBeforeTransformation).contains("\"version\": \"4.0.1\"");
+ assertThat(eventBeforeTransformation).contains("\"faultFieldsVersion\": \"4.0\"");
+
+ ArgumentCaptor<JSONArray> argument = ArgumentCaptor.forClass(JSONArray.class);
+ verify(eventSender).send(argument.capture());
+
+ final String transformedEvent = argument.getValue().toString();
+
+ // event after transformation
+ assertThat(transformedEvent).contains("\"priority\":\"High\",\"version\":3,");
+ assertThat(transformedEvent).contains(",\"faultFieldsVersion\":3,\"specificProblem");
+ }
+
+ @NotNull
+ private MockHttpServletRequest givenMockHttpServletRequest() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setContentType("application/json");
+
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+ return request;
+ }
+
+ private List<EventTransformation> loadEventTransformations() throws IOException {
+ Type EVENT_TRANSFORM_LIST_TYPE = new TypeToken<List<EventTransformation>>() {
+ }.getType();
+
+ try (FileReader fr = new FileReader(this.getClass().getResource(EVENT_TRANSFORM_FILE_PATH).getPath())) {
+ return new Gson().fromJson(fr, EVENT_TRANSFORM_LIST_TYPE);
+ }
+ }
+}
diff --git a/src/test/resources/api_version_config.json b/src/test/resources/api_version_config.json
new file mode 100644
index 00000000..23f585f9
--- /dev/null
+++ b/src/test/resources/api_version_config.json
@@ -0,0 +1,7 @@
+{
+ "apiVersion":
+ {
+ "eventListener": ["4.7.2","5.4.1","7.0.1"],
+ "eventListener_eventBatch": ["4.7.2","5.4.1","7.0.1"]
+ }
+}
diff --git a/src/test/resources/eventTransform.json b/src/test/resources/eventTransform.json
new file mode 100644
index 00000000..ab37a6eb
--- /dev/null
+++ b/src/test/resources/eventTransform.json
@@ -0,0 +1,396 @@
+[
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "heartbeat",
+ "VESversion": "v7"
+ },
+ "processors": [
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.version",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.heartbeatFields.heartbeatFieldsVersion",
+ "value": "2.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.heartbeatFields.additionalFields",
+ "mapType": "HashmapToNameValueArray"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "fault",
+ "VESversion": "v7"
+ },
+ "processors": [
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.version",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.faultFields.faultFieldsVersion",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.faultFields.alarmAdditionalInformation",
+ "mapType": "HashmapToNameValueArray"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "thresholdCrossingAlert",
+ "VESversion": "v7"
+ },
+ "processors": [
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.version",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.thresholdCrossingFields.thresholdCrossingFieldsVersion",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.thresholdCrossingFields.additionalFields",
+ "mapType": "HashmapToNameValueArray"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "measurement",
+ "VESversion": "v7"
+ },
+ "processors": [
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.version",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "removeAttribute",
+ "args": {
+ "field": "event.measurementFields.measurementFieldsVersion"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.measurementFields.measurementsForVfScalingVersion",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementFields.vNicPerformanceArray[]",
+ "oldField": "event.measurementFields.nicPerformanceArray[]",
+ "attrMap": {
+ "nicIdentifier": "vNicIdentifier"
+ }
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementFields.additionalFields",
+ "oldField": "event.measurementFields.additionalFields",
+ "mapType": "hashmapToNameValueArray"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields",
+ "oldField": "event.measurementFields",
+ "mapType": "renameObject"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.domain",
+ "value": "measurementsForVfScaling"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "heartbeat",
+ "VESversion": "v4"
+ },
+ "processors": [
+ {
+ "functionName": "concatenateValue",
+ "args": {
+ "field": "event.commonEventHeader.eventName",
+ "concatenate": [
+ "$event.commonEventHeader.domain",
+ "$event.commonEventHeader.eventType",
+ "$event.faultFields.alarmCondition"
+ ],
+ "delimiter": "_"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.heartbeatFields.heartbeatFieldsVersion",
+ "value": "1.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.heartbeatFields.heartbeatInterval",
+ "value": "0",
+ "fieldType": "integer"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.commonEventHeader.nfNamingCode",
+ "oldField": "event.commonEventHeader.functionalRole"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "fault",
+ "VESversion": "v4"
+ },
+ "processors": [
+ {
+ "functionName": "concatenateValue",
+ "args": {
+ "field": "event.commonEventHeader.eventName",
+ "concatenate": [
+ "$event.commonEventHeader.domain",
+ "$event.commonEventHeader.eventType",
+ "$event.faultFields.alarmCondition"
+ ],
+ "delimiter": "_"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.faultFields.faultFieldsVersion",
+ "value": "2.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.commonEventHeader.version",
+ "value": "3.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.commonEventHeader.nfNamingCode",
+ "oldField": "event.commonEventHeader.functionalRole"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "thresholdCrossingAlert",
+ "VESversion": "v4"
+ },
+ "processors": [
+ {
+ "functionName": "concatenateValue",
+ "args": {
+ "field": "event.commonEventHeader.eventName",
+ "concatenate": [
+ "$event.commonEventHeader.domain",
+ "$event.commonEventHeader.elementType",
+ "$event.faultFields.alertDescription"
+ ],
+ "delimiter": "_"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.commonEventHeader.nfNamingCode",
+ "oldField": "event.commonEventHeader.functionalRole"
+ }
+ }
+ ]
+ },
+ {
+ "filter": {
+ "event.commonEventHeader.domain": "measurementsForVfScaling",
+ "VESversion": "v4",
+ "not": {
+ "event.commonEventHeader.reportingEntityName": "matches:.*ircc|irpr.*"
+ }
+ },
+ "processors": [
+ {
+ "functionName": "concatenateValue",
+ "args": {
+ "field": "event.commonEventHeader.eventName",
+ "concatenate": [
+ "$event.commonEventHeader.domain",
+ "$event.commonEventHeader.eventType",
+ "$event.faultFields.alarmCondition"
+ ],
+ "delimiter": "_"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.measurementsForVfScalingVersion",
+ "value": "2.0",
+ "fieldType": "number"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.additionalMeasurements[].arrayOfFields[]",
+ "oldField": "event.measurementsForVfScalingFields.additionalMeasurements[].measurements[]"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "oldField": "event.measurementsForVfScalingFields.aggregateCpuUsage",
+ "field": "event.measurementsForVfScalingFields.cpuUsageArray[0].percentUsage"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.cpuUsageArray[0].cpuIdentifier",
+ "value": "$event.commonEventHeader.sourceName"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.memoryUsageArray[0].memoryConfigured",
+ "oldField": "event.measurementsForVfScalingFields.memoryConfigured",
+ "operation": "convertMBtoKB"
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.memoryUsageArray[0].memoryUsed",
+ "oldField": "event.measurementsForVfScalingFields.memoryUsed",
+ "operation": "convertMBtoKB"
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.memoryUsageArray[0].vmIdentifier",
+ "value": "$event.commonEventHeader.sourceName"
+ }
+ },
+ {
+ "functionName": "subtractValue",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.memoryUsageArray[0].memoryFree",
+ "subtract": [
+ "$event.measurementsForVfScalingFields.memoryUsageArray[0].memoryConfigured",
+ "$event.measurementsForVfScalingFields.memoryUsageArray[0].memoryUsed"
+ ]
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.vNicPerformanceArray[]",
+ "oldField": "event.measurementsForVfScalingFields.vNicUsageArray[]",
+ "attrMap": {
+ "broadcastPacketsIn": "receivedBroadcastPacketsAccumulated",
+ "multicastPacketsIn": "receivedMulticastPacketsAccumulated",
+ "bytesIn": "receivedOctetsAccumulated",
+ "packetsIn": "receivedTotalPacketsAccumulated",
+ "unicastPacketsIn": "receivedUnicastPacketsAccumulated",
+ "broadcastPacketsOut": "transmittedBroadcastPacketsAccumulated",
+ "multicastPacketsOut": "transmittedMulticastPacketsAccumulated",
+ "bytesOut": "transmittedOctetsAccumulated",
+ "packetsOut": "transmittedTotalPacketsAccumulated",
+ "unicastPacketsOut": "transmittedUnicastPacketsAccumulated"
+ }
+ }
+ },
+ {
+ "functionName": "map",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.vNicPerformanceArray[]",
+ "oldField": "event.measurementsForVfScalingFields.errors",
+ "attrMap": {
+ "receiveDiscards": "receivedDiscardedPacketsAccumulated",
+ "receiveErrors": "receivedErrorPacketsAccumulated",
+ "transmitDiscards": "transmittedDiscardedPacketsAccumulated",
+ "transmitErrors": "transmittedErrorPacketsAccumulated"
+ }
+ }
+ },
+ {
+ "functionName": "addAttribute",
+ "args": {
+ "field": "event.measurementsForVfScalingFields.vNicPerformanceArray[0].valuesAreSuspect",
+ "value": "false"
+ }
+ }
+ ]
+ }
+]
+