diff options
author | PatrikBuhr <patrik.buhr@est.tech> | 2021-10-07 18:03:53 +0200 |
---|---|---|
committer | PatrikBuhr <patrik.buhr@est.tech> | 2021-10-15 15:48:52 +0200 |
commit | 3b916e4dc5777863cb4ee873b41ee460fb9aec27 (patch) | |
tree | da8003e728de8f9ca8d7a9a4369c20b16c1f6531 /a1-policy-management/src | |
parent | e81a9de40bc0acb4a15ecf9fd60500a6f71344e4 (diff) |
Improving searching for policy types - A1 Jakarta
The querying for supported policy types is enhanced so that an application can get a list of all policy types that are compatible with a given version.
This means added query parameters for GET types.
Simplified exception handling.
Issue-ID: CCSDK-3495
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
Change-Id: Iedc2267e4fe2b5e2c17d688e315893c354379930
Diffstat (limited to 'a1-policy-management/src')
17 files changed, 338 insertions, 162 deletions
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 0f10a8cf..236d4381 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 @@ -73,7 +73,7 @@ public class ApplicationConfig { @Value("${app.webclient.trust-store}") private String sslTrustStore = ""; - @Value("${app.webclient.http.proxy-host:\"\"}") + @Value("${app.webclient.http.proxy-host:}") private String httpProxyHost = ""; @Value("${app.webclient.http.proxy-port:0}") diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java index c2f6a48a..3d2b55a2 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/PolicyController.java @@ -138,10 +138,10 @@ public class PolicyController { } @GetMapping("/policy_types") - @Operation(summary = "Query policy type names") + @Operation(summary = "Query policy type identities") @ApiResponses(value = { // @ApiResponse(responseCode = "200", // - description = "Policy type names", // + description = "Policy type identities", // content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))), // @ApiResponse(responseCode = "404", // description = "Near-RT RIC is not found", // @@ -354,7 +354,7 @@ public class PolicyController { return new ResponseEntity<>("Near-RT RIC not found", HttpStatus.NOT_FOUND); } - String filteredPolicies = policiesToJson(filter(type, ric, service)); + String filteredPolicies = policiesToJson(policies.filterPolicies(type, ric, service, null)); return new ResponseEntity<>(filteredPolicies, HttpStatus.OK); } @@ -383,7 +383,7 @@ public class PolicyController { return new ResponseEntity<>("Near-RT RIC not found", HttpStatus.NOT_FOUND); } - String policyIdsJson = toPolicyIdsJson(filter(type, ric, service)); + String policyIdsJson = toPolicyIdsJson(policies.filterPolicies(type, ric, service, null)); return new ResponseEntity<>(policyIdsJson, HttpStatus.OK); } @@ -417,36 +417,6 @@ public class PolicyController { } } - private boolean include(String filter, String value) { - return filter == null || value.equals(filter); - } - - private Collection<Policy> filter(Collection<Policy> collection, String type, String ric, String service) { - if (type == null && ric == null && service == null) { - return collection; - } - List<Policy> filtered = new ArrayList<>(); - for (Policy p : collection) { - if (include(type, p.getType().getId()) && include(ric, p.getRic().id()) - && include(service, p.getOwnerServiceId())) { - filtered.add(p); - } - } - return filtered; - } - - private Collection<Policy> filter(String type, String ric, String service) { - if (type != null) { - return filter(policies.getForType(type), null, ric, service); - } else if (service != null) { - return filter(policies.getForService(service), type, ric, null); - } else if (ric != null) { - return filter(policies.getForRic(ric), type, null, service); - } else { - return policies.getAll(); - } - } - private String policiesToJson(Collection<Policy> policies) { List<PolicyInfo> v = new ArrayList<>(policies.size()); for (Policy p : policies) { diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/Consts.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/Consts.java index 3e6bda72..a79999e4 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/Consts.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/Consts.java @@ -27,6 +27,9 @@ public class Consts { public static final String SERVICE_ID_PARAM = "service_id"; public static final String TRANSIENT_PARAM = "transient"; public static final String MANAGED_ELEMENT_ID_PARAM = "managed_element_id"; + public static final String TYPE_NAME_PARAM = "type_name"; + public static final String COMPATIBLE_WITH_VERSION_PARAM = "compatible_with_version"; + public static final String REGEXP_PARAM = "regexp"; public static final String V2_API_ROOT = "/a1-policy/v2"; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ErrorResponse.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ErrorResponse.java index 78ba6b69..a6679e05 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ErrorResponse.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ErrorResponse.java @@ -60,7 +60,7 @@ public class ErrorResponse { this.status = status; } - @Schema(example = "503", + @Schema(example = "404", description = "The HTTP status code generated by the origin server for this occurrence of the problem. ") public Integer getStatus() { return status; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java index ab9b6692..036958d3 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java @@ -42,6 +42,7 @@ import lombok.Getter; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; @@ -129,16 +130,36 @@ public class PolicyController { content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // }) public ResponseEntity<Object> getPolicyTypes( // - @Parameter(name = Consts.RIC_ID_PARAM, required = false, - description = "The identity of the Near-RT RIC to get types for.") // - @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId) throws EntityNotFoundException { - if (ricId == null) { - Collection<PolicyType> types = this.policyTypes.getAll(); - return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK); - } else { - Collection<PolicyType> types = rics.getRic(ricId).getSupportedPolicyTypes(); - return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK); + @Parameter(name = Consts.RIC_ID_PARAM, required = false, // + description = "Select types for the given Near-RT RIC identity.") // + @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId, + + @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // + description = "Select types with the given type name (type identity has the format <typename_version>)") // + @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName, + + @Parameter(name = Consts.REGEXP_PARAM, required = false, // + description = "Select types with type identity that matches a regular expression.") // + @RequestParam(name = Consts.REGEXP_PARAM, required = false) String regexp, + + @Parameter(name = Consts.COMPATIBLE_WITH_VERSION_PARAM, required = false, // + description = "Select types that are compatible with the given version. This parameter is only applicable in conjunction with " + + Consts.TYPE_NAME_PARAM + + ". As an example version 1.9.1 is compatible with 1.0.0 but not the other way around.") // + @RequestParam(name = Consts.COMPATIBLE_WITH_VERSION_PARAM, required = false) String compatibleWithVersion + + ) throws ServiceException { + + if (compatibleWithVersion != null && typeName == null) { + throw new ServiceException("Parameter " + Consts.COMPATIBLE_WITH_VERSION_PARAM + " can only be used when " + + Consts.TYPE_NAME_PARAM + " is given", HttpStatus.BAD_REQUEST); } + + Collection<PolicyType> types = + ricId != null ? rics.getRic(ricId).getSupportedPolicyTypes() : this.policyTypes.getAll(); + + types = PolicyTypes.filterTypes(types, typeName, regexp, compatibleWithVersion); + return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK); } @GetMapping(path = Consts.V2_API_ROOT + "/policies/{policy_id:.+}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -307,24 +328,27 @@ public class PolicyController { }) public ResponseEntity<Object> getPolicyInstances( // @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, - description = "The identity of the policy type to get policies for.") // - @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String type, // + description = "Select policies with a given type identity.") // + @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String typeId, // @Parameter(name = Consts.RIC_ID_PARAM, required = false, - description = "The identity of the Near-RT RIC to get policies for.") // + description = "Select policies for a given Near-RT RIC identity.") // @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ric, // @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, - description = "The identity of the service to get policies for.") // - @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String service) + description = "Select policies owned by a given service.") // + @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String service, + @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // + description = "Select policies of a given type name (type identity has the format <typename_version>)") // + @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName) throws EntityNotFoundException // { - if ((type != null && this.policyTypes.get(type) == null)) { - throw new EntityNotFoundException("Policy type not found"); + if ((typeId != null && this.policyTypes.get(typeId) == null)) { + throw new EntityNotFoundException("Policy type identity not found"); } if ((ric != null && this.rics.get(ric) == null)) { throw new EntityNotFoundException("Near-RT RIC not found"); } - String filteredPolicies = policiesToJson(filter(type, ric, service)); + String filteredPolicies = policiesToJson(policies.filterPolicies(typeId, ric, service, typeName)); return new ResponseEntity<>(filteredPolicies, HttpStatus.OK); } @@ -339,15 +363,18 @@ public class PolicyController { content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // }) public ResponseEntity<Object> getPolicyIds( // - @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, - description = "The identity of the policy type to get policies for.") // + @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, // + description = "Select policies of a given policy type identity.") // @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String policyTypeId, // - @Parameter(name = Consts.RIC_ID_PARAM, required = false, - description = "The identity of the Near-RT RIC to get policies for.") // + @Parameter(name = Consts.RIC_ID_PARAM, required = false, // + description = "Select policies of a given Near-RT RIC identity.") // @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId, // - @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, - description = "The identity of the service to get policies for.") // - @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String serviceId) + @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, // + description = "Select policies owned by a given service.") // + @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String serviceId, + @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // + description = "Select policies of types with the given type name (type identity has the format <typename_version>)") // + @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName) throws EntityNotFoundException // { if ((policyTypeId != null && this.policyTypes.get(policyTypeId) == null)) { @@ -357,7 +384,7 @@ public class PolicyController { throw new EntityNotFoundException("Near-RT RIC not found"); } - String policyIdsJson = toPolicyIdsJson(filter(policyTypeId, ricId, serviceId)); + String policyIdsJson = toPolicyIdsJson(policies.filterPolicies(policyTypeId, ricId, serviceId, typeName)); return new ResponseEntity<>(policyIdsJson, HttpStatus.OK); } @@ -395,36 +422,6 @@ public class PolicyController { } } - private boolean include(String filter, String value) { - return filter == null || value.equals(filter); - } - - private Collection<Policy> filter(Collection<Policy> collection, String type, String ric, String service) { - if (type == null && ric == null && service == null) { - return collection; - } - List<Policy> filtered = new ArrayList<>(); - for (Policy p : collection) { - if (include(type, p.getType().getId()) && include(ric, p.getRic().id()) - && include(service, p.getOwnerServiceId())) { - filtered.add(p); - } - } - return filtered; - } - - private Collection<Policy> filter(String type, String ric, String service) { - if (type != null) { - return filter(policies.getForType(type), null, ric, service); - } else if (service != null) { - return filter(policies.getForService(service), type, ric, null); - } else if (ric != null) { - return filter(policies.getForRic(ric), type, null, service); - } else { - return policies.getAll(); - } - } - private PolicyInfo toPolicyInfo(Policy p) { PolicyInfo policyInfo = new PolicyInfo(); policyInfo.policyId = p.getId(); diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java index d8b98105..2e19a3de 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java @@ -51,7 +51,7 @@ public class PolicyInfo { @SerializedName("policy_data") public Object policyData; - @Schema(name = "service_id", description = "the name of the service owning the policy", required = true) + @Schema(name = "service_id", description = "the identity of the service owning the policy", required = true) @JsonProperty(value = "service_id", required = true) @SerializedName("service_id") public String serviceId; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EntityNotFoundException.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EntityNotFoundException.java index ee9b7bf2..c0a1553c 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EntityNotFoundException.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EntityNotFoundException.java @@ -20,15 +20,14 @@ package org.onap.ccsdk.oran.a1policymanagementservice.exceptions; +import org.springframework.http.HttpStatus; + public class EntityNotFoundException extends ServiceException { private static final long serialVersionUID = 1L; public EntityNotFoundException(String message) { - super(message); + super(message, HttpStatus.NOT_FOUND); } - public EntityNotFoundException(String message, Exception originalException) { - super(message, originalException); - } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EnvironmentLoaderException.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EnvironmentLoaderException.java deleted file mode 100644 index 4e1009f0..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/EnvironmentLoaderException.java +++ /dev/null @@ -1,30 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. 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. - * 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.ccsdk.oran.a1policymanagementservice.exceptions; - -public class EnvironmentLoaderException extends ServiceException { - - private static final long serialVersionUID = 1L; - - public EnvironmentLoaderException(String message) { - super(message); - } -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java index 9d20d33f..547cd6b0 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java @@ -21,6 +21,8 @@ package org.onap.ccsdk.oran.a1policymanagementservice.exceptions; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2.ErrorResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -31,13 +33,16 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep @ControllerAdvice(annotations = RestController.class) public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler(EntityNotFoundException.class) - public final ResponseEntity<Object> handleNotFoundException(EntityNotFoundException ex) { - return ErrorResponse.create(ex, HttpStatus.NOT_FOUND); + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(ServiceException.class) + public final ResponseEntity<Object> handleServiceException(ServiceException ex) { + return ErrorResponse.create(ex, ex.getHttpStatus()); } - @ExceptionHandler(InvalidRequestException.class) - public final ResponseEntity<Object> handleInvalidRequestException(InvalidRequestException ex) { - return ErrorResponse.create(ex, HttpStatus.BAD_REQUEST); + @ExceptionHandler(RuntimeException.class) + public final ResponseEntity<Object> handleRuntimeException(RuntimeException ex) { + logger.error("Runtime exception {}", ex.getMessage()); + return ErrorResponse.create(ex, HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/InvalidRequestException.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/InvalidRequestException.java index 6ffd216b..50b17d22 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/InvalidRequestException.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/InvalidRequestException.java @@ -20,15 +20,14 @@ package org.onap.ccsdk.oran.a1policymanagementservice.exceptions; +import org.springframework.http.HttpStatus; + public class InvalidRequestException extends ServiceException { private static final long serialVersionUID = 1L; public InvalidRequestException(String message) { - super(message); + super(message, HttpStatus.BAD_REQUEST); } - public InvalidRequestException(String message, Exception originalException) { - super(message, originalException); - } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java index 45aa57e4..ef924748 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java @@ -30,8 +30,10 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; @@ -47,6 +49,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.util.FileSystemUtils; +import reactor.util.annotation.Nullable; @SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally @Configuration @@ -149,6 +152,20 @@ public class Policies { } } + public Collection<Policy> filterPolicies(@Nullable String typeId, @Nullable String ricId, + @Nullable String serviceId, @Nullable String typeName) { + + if (typeId != null) { + return filter(this.getForType(typeId), null, ricId, serviceId, typeName); + } else if (serviceId != null) { + return filter(this.getForService(serviceId), typeId, ricId, null, typeName); + } else if (ricId != null) { + return filter(this.getForRic(ricId), typeId, null, serviceId, typeName); + } else { + return filter(this.getAll(), typeId, ricId, serviceId, typeName); + } + } + public synchronized int size() { return policiesId.size(); } @@ -178,6 +195,29 @@ public class Policies { } } + private boolean isMatch(String filterValue, String actualValue) { + return filterValue == null || actualValue.equals(filterValue); + } + + private boolean isTypeMatch(Policy policy, @Nullable String typeName) { + return (typeName == null) || policy.getType().getTypeId().getName().equals(typeName); + } + + private Collection<Policy> filter(Collection<Policy> collection, String typeId, String ricId, String serviceId, + String typeName) { + if (typeId == null && ricId == null && serviceId == null && typeName == null) { + return collection; + } + List<Policy> filtered = new ArrayList<>(collection.size()); + for (Policy p : collection) { + if (isMatch(typeId, p.getType().getId()) && isMatch(ricId, p.getRic().id()) + && isMatch(serviceId, p.getOwnerServiceId()) && isTypeMatch(p, typeName)) { + filtered.add(p); + } + } + return filtered; + } + private File getFile(Policy policy) throws ServiceException { return getPath(policy).toFile(); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java index 9fbae6dd..3a5bdd95 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyType.java @@ -23,10 +23,79 @@ package org.onap.ccsdk.oran.a1policymanagementservice.repository; import lombok.Builder; import lombok.Getter; -@Getter +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; +import org.springframework.http.HttpStatus; + @Builder public class PolicyType { + @Getter private String id; - + @Getter private String schema; + + @Getter + public static class Version { + public final int major; + public final int minor; + public final int patch; + + public Version(int major, int minor, int patch) { + this.major = major; + this.minor = minor; + this.patch = patch; + } + + public static Version ofString(String version) throws ServiceException { + String[] versionTokenized = version.split("\\."); + if (versionTokenized.length != 3) { + throw new ServiceException("Version must contain major.minor.patch code: " + version, + HttpStatus.BAD_REQUEST); + } + + try { + return new Version( // + Integer.parseInt(versionTokenized[0]), // + Integer.parseInt(versionTokenized[1]), // + Integer.parseInt(versionTokenized[2]) // + ); + } catch (Exception e) { + throw new ServiceException("Syntax error in " + version, HttpStatus.BAD_REQUEST); + } + } + } + + @Getter + public static class TypeId { + private final String name; + private final String version; + + public TypeId(String name, String version) { + this.name = name; + this.version = version; + } + + public static TypeId ofString(String typeId) { + StringBuilder name = new StringBuilder(); + String version = ""; + String[] tokens = typeId.split("_"); + + if (tokens.length >= 2) { + version = tokens[tokens.length - 1]; // Last token + for (int i = 0; i < tokens.length - 1; ++i) { + if (i != 0) { + name.append("_"); + } + name.append(tokens[i]); // All other tokens + } + return new TypeId(name.toString(), version); + } else { + return new TypeId(typeId, ""); + } + } + } + + public TypeId getTypeId() { + return TypeId.ofString(getId()); + } + } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java index 3248f214..c2a93cc6 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/PolicyTypes.java @@ -30,11 +30,15 @@ import java.io.PrintStream; import java.lang.invoke.MethodHandles; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jetbrains.annotations.Nullable; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; @@ -46,7 +50,7 @@ import org.springframework.util.FileSystemUtils; @Configuration public class PolicyTypes { - private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private Map<String, PolicyType> types = new HashMap<>(); private final ApplicationConfig appConfig; private static Gson gson = new GsonBuilder().create(); @@ -81,6 +85,32 @@ public class PolicyTypes { return new Vector<>(types.values()); } + /** + * Filter out types matching criterias + * + * @param types the types to select from + * @param typeName select types with given type name + * @param regexp select types where the ID matches a regular + * expression + * @param compatibleWithVersion select types that are compatible with given + * version string (major.minor.patch) + * @return the types that matches given criterias + * @throws ServiceException if there are errors in the given input + */ + public static Collection<PolicyType> filterTypes(Collection<PolicyType> types, @Nullable String typeName, + @Nullable String regexp, @Nullable String compatibleWithVersion) throws ServiceException { + if (typeName != null) { + types = filterTypeName(types, typeName); + } + if (regexp != null) { + types = filterRegexp(types, regexp); + } + if (compatibleWithVersion != null) { + types = filterCompatibleWithVersion(types, compatibleWithVersion); + } + return types; + } + public synchronized int size() { return types.size(); } @@ -137,4 +167,51 @@ public class PolicyTypes { private Path getDatabasePath() throws ServiceException { return Path.of(getDatabaseDirectory()); } + + private static Collection<PolicyType> filterRegexp(Collection<PolicyType> types, String regexp) { + Collection<PolicyType> result = new ArrayList<>(); + Pattern pattern = Pattern.compile(regexp); + for (PolicyType type : types) { + Matcher matcher = pattern.matcher(type.getId()); + if (matcher.find()) { + result.add(type); + } + } + return result; + } + + private static Collection<PolicyType> filterTypeName(Collection<PolicyType> types, String typeName) { + Collection<PolicyType> result = new ArrayList<>(); + for (PolicyType type : types) { + PolicyType.TypeId nameVersion = type.getTypeId(); + if (nameVersion.getName().equals(typeName)) { + result.add(type); + } + } + return result; + } + + private static boolean isTypeCompatibleWithVersion(PolicyType type, PolicyType.Version version) { + try { + PolicyType.TypeId typeId = type.getTypeId(); + PolicyType.Version typeVersion = PolicyType.Version.ofString(typeId.getVersion()); + return (typeVersion.major == version.major && typeVersion.minor >= version.minor); + } catch (Exception e) { + logger.warn("Ignoring type with syntactically incorrect type ID: {}", type.getId()); + return false; + } + } + + private static Collection<PolicyType> filterCompatibleWithVersion(Collection<PolicyType> types, String versionStr) + throws ServiceException { + Collection<PolicyType> result = new ArrayList<>(); + PolicyType.Version otherVersion = PolicyType.Version.ofString(versionStr); + for (PolicyType type : types) { + if (isTypeCompatibleWithVersion(type, otherVersion)) { + result.add(type); + } + } + return result; + } + } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java index f9af2393..8eca6be9 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Ric.java @@ -123,12 +123,12 @@ public class Ric { /** * Checks if a type is supported by this Ric. * - * @param typeName the name of the type to check if it is supported. + * @param typeId the identity of the type to check if it is supported. * * @return true if the given type is supported by this Ric, false otherwise. */ - public synchronized boolean isSupportingType(String typeName) { - return supportedPolicyTypes.containsKey(typeName); + public synchronized boolean isSupportingType(String typeId) { + return supportedPolicyTypes.containsKey(typeId); } @Override diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessor.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessor.java index ba81d222..3a4abcf2 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessor.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessor.java @@ -23,7 +23,7 @@ package org.onap.ccsdk.oran.a1policymanagementservice.tasks; import java.util.Optional; import java.util.Properties; -import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EnvironmentLoaderException; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties; import org.slf4j.Logger; @@ -51,16 +51,16 @@ class EnvironmentProcessor { .cbsName(getConfigBindingService(systemEnvironment)) // .appName(getService(systemEnvironment)) // .build(); - } catch (EnvironmentLoaderException e) { + } catch (ServiceException e) { return Mono.error(e); } logger.trace("Evaluated environment system variables {}", envProperties); return Mono.just(envProperties); } - private static String getConsulHost(Properties systemEnvironments) throws EnvironmentLoaderException { + private static String getConsulHost(Properties systemEnvironments) throws ServiceException { return Optional.ofNullable(systemEnvironments.getProperty("CONSUL_HOST")) - .orElseThrow(() -> new EnvironmentLoaderException("$CONSUL_HOST environment has not been defined")); + .orElseThrow(() -> new ServiceException("$CONSUL_HOST environment has not been defined")); } private static Integer getConsultPort(Properties systemEnvironments) { @@ -69,17 +69,16 @@ class EnvironmentProcessor { .orElseGet(EnvironmentProcessor::getDefaultPortOfConsul); } - private static String getConfigBindingService(Properties systemEnvironments) throws EnvironmentLoaderException { + private static String getConfigBindingService(Properties systemEnvironments) throws ServiceException { return Optional.ofNullable(systemEnvironments.getProperty("CONFIG_BINDING_SERVICE")) // - .orElseThrow(() -> new EnvironmentLoaderException( - "$CONFIG_BINDING_SERVICE environment has not been defined")); + .orElseThrow(() -> new ServiceException("$CONFIG_BINDING_SERVICE environment has not been defined")); } - private static String getService(Properties systemEnvironments) throws EnvironmentLoaderException { + private static String getService(Properties systemEnvironments) throws ServiceException { return Optional .ofNullable(Optional.ofNullable(systemEnvironments.getProperty("HOSTNAME")) .orElse(systemEnvironments.getProperty("SERVICE_NAME"))) - .orElseThrow(() -> new EnvironmentLoaderException( + .orElseThrow(() -> new ServiceException( "Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment")); } diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java index 08350f81..f18953c4 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java @@ -597,22 +597,55 @@ class ApplicationTest { @Test void testGetPolicyTypes() throws Exception { - addPolicyType("type1", "ric1"); - addPolicyType("type2", "ric2"); + String TYPE_ID_1 = "A_type1_1.9.0"; + String TYPE_ID_2 = "A_type1_2.0.0"; + String TYPE_ID_3 = "A_type1_1.5.0"; + String TYPE_ID_4 = "type3_1.9.0"; + addPolicyType(TYPE_ID_1, "ric1"); + addPolicyType(TYPE_ID_2, "ric2"); + addPolicyType(TYPE_ID_3, "ric2"); + addPolicyType(TYPE_ID_4, "ric2"); + + addPolicyType("junk", "ric2"); + addPolicyType("junk_a.b.c", "ric2"); String url = "/policy-types"; String rsp = restClient().get(url).block(); - String expResp = createPolicyTypesJson("type2", "type1"); - assertThat(rsp).isEqualTo(expResp); + assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2); url = "/policy-types?ric_id=ric1"; rsp = restClient().get(url).block(); - expResp = createPolicyTypesJson("type1"); + String expResp = createPolicyTypesJson(TYPE_ID_1); assertThat(rsp).isEqualTo(expResp); // Get policy types for non existing RIC url = "/policy-types?ric_id=ric1XXX"; testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); + + // All types with a type_name + url = "/policy-types?type_name=A_type1"; + rsp = restClient().get(url).block(); + assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2); + + // All types compatible with type1_1.5.0 (which is type1_1.9.0) + url = "/policy-types?type_name=A_type1&&compatible_with_version=1.5.0"; + rsp = restClient().get(url).block(); + expResp = createPolicyTypesJson(TYPE_ID_3, TYPE_ID_1); + assertThat(rsp).isEqualTo(expResp); + + url = "/policy-types?type_name=A_type1&&compatible_with_version=junk"; + testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Version must contain major.minor.patch code"); + + url = "/policy-types?type_name=A_type1&&compatible_with_version=a.b.c"; + testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Syntax error in"); + + url = "/policy-types?compatible_with_version=1.5.0"; + testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "type_name"); + + url = "/policy-types?regexp=type3_.*"; + rsp = restClient().get(url).block(); + expResp = createPolicyTypesJson(TYPE_ID_4); + assertThat(rsp).isEqualTo(expResp); } @Test @@ -636,6 +669,7 @@ class ApplicationTest { addPolicy("id1", "type1", "service1"); addPolicy("id2", "type1", "service2"); addPolicy("id3", "type2", "service1"); + addPolicy("id4", "type1_1.0.0", "service1"); String url = "/policy-instances?policytype_id=type1"; String rsp = restClient().get(url).block(); @@ -651,6 +685,13 @@ class ApplicationTest { .contains("id2") // .doesNotContain("id3"); + url = "/policy-instances?type_name=type1"; + rsp = restClient().get(url).block(); + assertThat(rsp).contains("id1") // + .contains("id2") // + .doesNotContain("id3") // + .contains("id4"); + // Test get policies for non existing type url = "/policy-instances?policytype_id=type1XXX"; testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); @@ -665,6 +706,7 @@ class ApplicationTest { addPolicy("id1", "type1", "service1", "ric1"); addPolicy("id2", "type1", "service2", "ric1"); addPolicy("id3", "type2", "service1", "ric1"); + addPolicy("id4", "type1_1.0.0", "service1"); String url = "/policies?policytype_id=type1"; String rsp = restClient().get(url).block(); @@ -678,6 +720,13 @@ class ApplicationTest { PolicyIdList respList = gson.fromJson(rsp, PolicyIdList.class); assertThat(respList.policyIds.iterator().next()).isEqualTo("id1"); + url = "/policies?policytype_name=type1&service_id=service1"; + rsp = restClient().get(url).block(); + assertThat(rsp).contains("id1") // + .contains("id3") // + .contains("id4"); + assertThat(gson.fromJson(rsp, PolicyIdList.class).policyIds).hasSize(3); + // Test get policy ids for non existing type url = "/policies?policytype_id=type1XXX"; testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessorTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessorTest.java index 5a1dbea7..64a7a19e 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessorTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/EnvironmentProcessorTest.java @@ -29,7 +29,7 @@ import ch.qos.logback.core.read.ListAppender; import java.util.Properties; import org.junit.jupiter.api.Test; -import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EnvironmentLoaderException; +import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; import org.onap.ccsdk.oran.a1policymanagementservice.utils.LoggingUtils; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties; @@ -70,7 +70,7 @@ class EnvironmentProcessorTest { Properties systemEnvironment = new Properties(); StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment)) - .expectErrorMatches(throwable -> throwable instanceof EnvironmentLoaderException + .expectErrorMatches(throwable -> throwable instanceof ServiceException && throwable.getMessage().equals("$CONSUL_HOST environment has not been defined")) .verify(); } @@ -106,7 +106,7 @@ class EnvironmentProcessorTest { systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE); StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment)) - .expectErrorMatches(throwable -> throwable instanceof EnvironmentLoaderException + .expectErrorMatches(throwable -> throwable instanceof ServiceException && throwable.getMessage().equals("$CONFIG_BINDING_SERVICE environment has not been defined")) .verify(); } @@ -138,9 +138,8 @@ class EnvironmentProcessorTest { systemEnvironment.put(CONFIG_BINDING_SERVICE, CONFIG_BINDING_SERVICE_VALUE); StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment)) - .expectErrorMatches( - throwable -> throwable instanceof EnvironmentLoaderException && throwable.getMessage() - .equals("Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment")) + .expectErrorMatches(throwable -> throwable instanceof ServiceException && throwable.getMessage() + .equals("Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment")) .verify(); } } |