summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--a1-policy-management/config/application.yaml1
-rw-r--r--a1-policy-management/config/application_configuration.json6
-rw-r--r--a1-policy-management/pom.xml8
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java4
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParser.java41
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java17
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java2
-rw-r--r--a1-policy-management/src/main/resources/application_configuration_schema.json151
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParserTest.java22
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationControllerTest.java7
-rw-r--r--a1-policy-management/src/test/resources/test_application_configuration.json6
-rw-r--r--a1-policy-management/src/test/resources/test_application_configuration_with_dmaap_config.json1
-rw-r--r--csit/scripts/healthcheck/config/application_configuration.json.nosdnc6
13 files changed, 252 insertions, 20 deletions
diff --git a/a1-policy-management/config/application.yaml b/a1-policy-management/config/application.yaml
index a40f172f..e1a778c3 100644
--- a/a1-policy-management/config/application.yaml
+++ b/a1-policy-management/config/application.yaml
@@ -74,4 +74,5 @@ app:
http.proxy-type: HTTP
# path where the service can store data
vardata-directory: /var/policy-management-service
+ config-file-schema-path:
diff --git a/a1-policy-management/config/application_configuration.json b/a1-policy-management/config/application_configuration.json
index 6c21b166..6187c866 100644
--- a/a1-policy-management/config/application_configuration.json
+++ b/a1-policy-management/config/application_configuration.json
@@ -1,6 +1,6 @@
{
- "config": {
- "//description": "Application configuration",
+ "description": "Application configuration",
+ "config": {
"controller": [
{
"name": "controller1",
@@ -21,4 +21,4 @@
}
]
}
-} \ No newline at end of file
+}
diff --git a/a1-policy-management/pom.xml b/a1-policy-management/pom.xml
index 4e3a9bd7..221cc081 100644
--- a/a1-policy-management/pom.xml
+++ b/a1-policy-management/pom.xml
@@ -223,6 +223,12 @@
<version>${commons-io.version}</version>
<scope>test</scope>
</dependency>
+ <!-- https://mvnrepository.com/artifact/com.github.erosb/everit-json-schema -->
+ <dependency>
+ <groupId>com.github.erosb</groupId>
+ <artifactId>everit-json-schema</artifactId>
+ <version>1.13.0</version>
+ </dependency>
</dependencies>
<build>
<plugins>
@@ -427,4 +433,4 @@
</plugin>
</plugins>
</build>
-</project>
+</project> \ No newline at end of file
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
index 3a245190..40988e44 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
@@ -45,6 +45,10 @@ public class ApplicationConfig {
private String localConfigurationFilePath;
@Getter
+ @Value("${app.config-file-schema-path:\"\"}")
+ private String configurationFileSchemaPath;
+
+ @Getter
@Value("${app.vardata-directory:null}")
private String vardataDirectory;
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParser.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParser.java
index a6af2023..3cab8aa0 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParser.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParser.java
@@ -24,6 +24,10 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -38,6 +42,7 @@ import javax.validation.constraints.NotNull;
import org.immutables.gson.Gson;
import org.immutables.value.Value;
+import org.json.JSONObject;
import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,6 +55,11 @@ public class ApplicationConfigParser {
private static final String CONFIG = "config";
private static final String CONTROLLER = "controller";
+ private final ApplicationConfig applicationConfig;
+
+ public ApplicationConfigParser(ApplicationConfig applicationConfig) {
+ this.applicationConfig = applicationConfig;
+ }
@Value.Immutable
@Gson.TypeAdapters
@@ -66,6 +76,8 @@ public class ApplicationConfigParser {
public ConfigParserResult parse(JsonObject root) throws ServiceException {
+ validateJsonObjectAgainstSchema(root);
+
String dmaapProducerTopicUrl = "";
String dmaapConsumerTopicUrl = "";
@@ -97,6 +109,35 @@ public class ApplicationConfigParser {
.build();
}
+ private void validateJsonObjectAgainstSchema(Object object) throws ServiceException {
+ if (applicationConfig.getConfigurationFileSchemaPath() == null
+ || applicationConfig.getConfigurationFileSchemaPath().isEmpty()) {
+ return;
+ }
+
+ try {
+ String schemaAsString = readSchemaFile();
+
+ JSONObject schemaJSON = new JSONObject(schemaAsString);
+ var schema = org.everit.json.schema.loader.SchemaLoader.load(schemaJSON);
+
+ String objectAsString = object.toString();
+ JSONObject json = new JSONObject(objectAsString);
+ schema.validate(json);
+ } catch (Exception e) {
+ throw new ServiceException("Json schema validation failure: " + e.toString());
+ }
+ }
+
+ private String readSchemaFile() throws IOException {
+ ClassLoader classLoader = getClass().getClassLoader();
+ String filePath = applicationConfig.getConfigurationFileSchemaPath();
+ URL url = classLoader.getResource(filePath);
+ File file = new File(url.getFile());
+ return new String(Files.readAllBytes(file.toPath()));
+
+ }
+
private void checkConfigurationConsistency(List<RicConfig> ricConfigs,
Map<String, ControllerConfig> controllerConfigs) throws ServiceException {
Set<String> ricUrls = new HashSet<>();
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java
index b677a405..e07ea284 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java
@@ -33,6 +33,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import java.io.IOException;
import java.util.Optional;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfigParser;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ConfigurationFile;
import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse;
@@ -57,11 +58,17 @@ public class ConfigurationController {
public static final String API_NAME = "Management of configuration";
public static final String API_DESCRIPTION = "";
- @Autowired
- ConfigurationFile configurationFile;
+ private final ConfigurationFile configurationFile;
+ private final RefreshConfigTask refreshConfigTask;
+ private final ApplicationConfig applicationConfig;
- @Autowired
- RefreshConfigTask refreshConfigTask;
+ ConfigurationController(@Autowired ConfigurationFile configurationFile,
+ @Autowired RefreshConfigTask refreshConfigTask, @Autowired ApplicationConfig applicationConfig) {
+ this.configurationFile = configurationFile;
+ this.refreshConfigTask = refreshConfigTask;
+ this.applicationConfig = applicationConfig;
+
+ }
private static Gson gson = new GsonBuilder() //
.create(); //
@@ -85,7 +92,7 @@ public class ConfigurationController {
validateConfigFileIsUsed();
String configAsString = gson.toJson(configuration);
JsonObject configJson = JsonParser.parseString(configAsString).getAsJsonObject();
- ApplicationConfigParser configParser = new ApplicationConfigParser();
+ ApplicationConfigParser configParser = new ApplicationConfigParser(applicationConfig);
configParser.parse(configJson);
configurationFile.writeFile(configJson);
logger.info("Configuration changed through REST call.");
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java
index 30279815..6177ee1b 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshConfigTask.java
@@ -189,7 +189,7 @@ public class RefreshConfigTask {
private Mono<ApplicationConfigParser.ConfigParserResult> parseConfiguration(JsonObject jsonObject) {
try {
- ApplicationConfigParser parser = new ApplicationConfigParser();
+ ApplicationConfigParser parser = new ApplicationConfigParser(this.appConfig);
return Mono.just(parser.parse(jsonObject));
} catch (Exception e) {
String str = e.toString();
diff --git a/a1-policy-management/src/main/resources/application_configuration_schema.json b/a1-policy-management/src/main/resources/application_configuration_schema.json
new file mode 100644
index 00000000..05135e7c
--- /dev/null
+++ b/a1-policy-management/src/main/resources/application_configuration_schema.json
@@ -0,0 +1,151 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "config": {
+ "type": "object",
+ "properties": {
+ "//description": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "controller": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "baseUrl": {
+ "type": "string"
+ },
+ "userName": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "baseUrl",
+ "userName",
+ "password"
+ ],
+ "additionalProperties": false
+ }
+ ]
+ },
+ "ric": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "baseUrl": {
+ "type": "string"
+ },
+ "controller": {
+ "type": "string"
+ },
+ "managedElementIds": {
+ "type": "array",
+ "items": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "baseUrl",
+ "managedElementIds"
+ ],
+ "additionalProperties": false
+ }
+ ]
+ },
+ "streams_publishes": {
+ "type": "object",
+ "properties": {
+ "dmaap_publisher": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "dmaap_info": {
+ "type": "object",
+ "properties": {
+ "topic_url": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "topic_url"
+ ]
+ }
+ },
+ "required": [
+ "type",
+ "dmaap_info"
+ ]
+ }
+ },
+ "required": [
+ "dmaap_publisher"
+ ]
+ },
+ "streams_subscribes": {
+ "type": "object",
+ "properties": {
+ "dmaap_subscriber": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "dmaap_info": {
+ "type": "object",
+ "properties": {
+ "topic_url": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "topic_url"
+ ]
+ }
+ },
+ "required": [
+ "type",
+ "dmaap_info"
+ ]
+ }
+ },
+ "required": [
+ "dmaap_subscriber"
+ ]
+ }
+ },
+ "required": [
+ "ric"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "config"
+ ]
+} \ No newline at end of file
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParserTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParserTest.java
index 5e218582..d12fd6bc 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParserTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfigParserTest.java
@@ -20,8 +20,11 @@
package org.onap.ccsdk.oran.a1policymanagementservice.configuration;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
@@ -44,12 +47,16 @@ import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException
class ApplicationConfigParserTest {
- ApplicationConfigParser parserUnderTest = new ApplicationConfigParser();
+ ApplicationConfig applicationConfigMock = spy(new ApplicationConfig());
+ ApplicationConfigParser parserUnderTest = new ApplicationConfigParser(applicationConfigMock);
@Test
void whenCorrectConfig() throws Exception {
JsonObject jsonRootObject = getJsonRootObject();
+ when(applicationConfigMock.getConfigurationFileSchemaPath())
+ .thenReturn("application_configuration_schema.json");
+
ApplicationConfigParser.ConfigParserResult result = parserUnderTest.parse(jsonRootObject);
String topicUrl = result.dmaapProducerTopicUrl();
@@ -153,6 +160,19 @@ class ApplicationConfigParserTest {
assertEquals(message, actualException.getMessage(), "Wrong error message when wrong member name in object");
}
+ @Test
+ void schemaValidationError() throws Exception {
+ when(applicationConfigMock.getConfigurationFileSchemaPath())
+ .thenReturn("application_configuration_schema.json");
+ JsonObject jsonRootObject = getJsonRootObject();
+ JsonObject json = jsonRootObject.getAsJsonObject("config");
+ json.remove("ric");
+
+ Exception actualException = assertThrows(ServiceException.class, () -> parserUnderTest.parse(jsonRootObject));
+
+ assertThat(actualException.getMessage()).contains("Json schema validation failure");
+ }
+
JsonObject getDmaapInfo(JsonObject jsonRootObject, String streamsPublishesOrSubscribes,
String dmaapPublisherOrSubscriber) throws Exception {
return jsonRootObject.getAsJsonObject("config").getAsJsonObject(streamsPublishesOrSubscribes)
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationControllerTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationControllerTest.java
index adb29a70..d2805556 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationControllerTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationControllerTest.java
@@ -60,7 +60,9 @@ import reactor.test.StepVerifier;
@TestPropertySource(properties = { //
"server.ssl.key-store=./config/keystore.jks", //
"app.webclient.trust-store=./config/truststore.jks", //
- "app.vardata-directory=./target"})
+ "app.vardata-directory=./target", //
+ "app.config-file-schema-path=application_configuration_schema.json" //
+})
class ConfigurationControllerTest {
@Autowired
ApplicationContext context;
@@ -135,8 +137,7 @@ class ConfigurationControllerTest {
String url = "a1-policy/v2/configuration";
// Valid JSON but invalid configuration.
- testErrorCode(restClient().put(url, "{\"error\":\"error\"}"), HttpStatus.BAD_REQUEST,
- "Missing root configuration");
+ testErrorCode(restClient().put(url, "{\"error\":\"error\"}"), HttpStatus.BAD_REQUEST, "");
}
private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
diff --git a/a1-policy-management/src/test/resources/test_application_configuration.json b/a1-policy-management/src/test/resources/test_application_configuration.json
index 3cbc371c..959f53fd 100644
--- a/a1-policy-management/src/test/resources/test_application_configuration.json
+++ b/a1-policy-management/src/test/resources/test_application_configuration.json
@@ -1,6 +1,6 @@
-{
+{
"config": {
- "//description": "Application configuration",
+ "description": "Application configuration",
"ric": [
{
"name": "ric1",
@@ -36,4 +36,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/a1-policy-management/src/test/resources/test_application_configuration_with_dmaap_config.json b/a1-policy-management/src/test/resources/test_application_configuration_with_dmaap_config.json
index ed1501dd..b00720c3 100644
--- a/a1-policy-management/src/test/resources/test_application_configuration_with_dmaap_config.json
+++ b/a1-policy-management/src/test/resources/test_application_configuration_with_dmaap_config.json
@@ -1,5 +1,6 @@
{
"config": {
+ "//description" : "Test",
"controller": [
{
"name": "controller1",
diff --git a/csit/scripts/healthcheck/config/application_configuration.json.nosdnc b/csit/scripts/healthcheck/config/application_configuration.json.nosdnc
index deb88a08..800a54ec 100644
--- a/csit/scripts/healthcheck/config/application_configuration.json.nosdnc
+++ b/csit/scripts/healthcheck/config/application_configuration.json.nosdnc
@@ -1,6 +1,6 @@
{
- "config":{
- "//description":"Application configuration",
+ "description":"Application configuration",
+ "config":{
"ric":[
{
"name":"ric1",
@@ -36,4 +36,4 @@
}
}
}
- } \ No newline at end of file
+ }