From 083ee56fa85a9217dc8bdffe98764d33c5851016 Mon Sep 17 00:00:00 2001 From: "Betzer, Rony (rb844h)" Date: Tue, 25 Sep 2018 16:03:09 +0300 Subject: update code to latest - ammend previous commit update code to latest - ammend previous commit Change-Id: Ia4f55789689b5f2ddd004a4fe89a63f72cecc27f Issue-ID: DCAEGEN2-819 Signed-off-by: Betzer, Rony (rb844h) --- .../controller/RuleEditorController.java | 42 +++- .../composition/impl/RuleEditorBusinessLogic.java | 212 ++++++++++++++++++++- .../org/onap/sdc/dcae/errormng/ActionStatus.java | 2 + .../dcae/rule/editor/impl/RulesBusinessLogic.java | 17 +- .../editor/translators/MappingRulesTranslator.java | 34 +--- .../rule/editor/translators/RuleTranslator.java | 37 ++++ .../dcae/rule/editor/utils/RulesPayloadUtils.java | 10 +- .../rule/editor/validators/ConditionValidator.java | 7 +- .../editor/validators/MappingRulesValidator.java | 31 ++- .../config/dcae-be/error-configuration.yaml | 12 ++ .../impl/RuleEditorBusinessLogicTest.java | 132 +++++++++++-- .../rule/editor/impl/RulesBusinessLogicTest.java | 9 +- 12 files changed, 461 insertions(+), 84 deletions(-) (limited to 'dcaedt_be/src') diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java index 1e93cf5..f929c30 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/RuleEditorController.java @@ -1,8 +1,13 @@ package org.onap.sdc.dcae.composition.controller; +import com.google.gson.JsonParseException; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.impl.RuleEditorBusinessLogic; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRulesResponse; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.TranslateRequest; +import org.onap.sdc.dcae.errormng.ActionStatus; +import org.onap.sdc.dcae.errormng.ErrConfMgr; +import org.onap.sdc.dcae.rule.editor.utils.RulesPayloadUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.http.MediaType; @@ -61,6 +66,19 @@ public class RuleEditorController extends BaseController { } + @RequestMapping(value = "/applyFilter", method = {RequestMethod.POST}, produces = "application/json") + public ResponseEntity applyFilter(@RequestBody String json, @ModelAttribute("requestId") String requestId, @RequestHeader("USER_ID") String userId) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting applyFilter", json); + return ruleEditorBusinessLogic.applyFilter(json, requestId, userId); + } + + @RequestMapping(value = "/deleteFilter", method = {RequestMethod.POST}, produces = "application/json") + public ResponseEntity deleteFilter(@RequestBody String json, @ModelAttribute("requestId") String requestId, @RequestHeader("USER_ID") String userId) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting deleteFilter", json); + return ruleEditorBusinessLogic.deleteFilter(json, requestId, userId); + } + + /** * This endpoint functions as a 'fetch' service for the rule editor UI * @@ -94,17 +112,35 @@ public class RuleEditorController extends BaseController { return ruleEditorBusinessLogic.downloadRules(vfcmtUuid, dcaeCompLabel, nid, configParam, requestId); } - @RequestMapping(value = "/import/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam:.*}", method = {RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(value = "/import/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}/{supportGroups}", method = {RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity importRules( @RequestBody String json, @ModelAttribute("requestId") String requestId, @RequestHeader("USER_ID") String userId, @PathVariable("vfcmtUuid") String vfcmtUuid, @PathVariable("dcaeCompLabel") String dcaeCompLabel, @PathVariable("nid") String nid, - @PathVariable("configParam") String configParam) { + @PathVariable("configParam") String configParam, + @PathVariable boolean supportGroups) { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting importRules", json); - return ruleEditorBusinessLogic.importRules(json, requestId, userId, vfcmtUuid, dcaeCompLabel, nid, configParam); + MappingRulesResponse mappingRules; + try { + mappingRules = RulesPayloadUtils.parsePayloadToMappingRules(json); + if(!ruleEditorBusinessLogic.validateEditorVersion(mappingRules, supportGroups)) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", "The imported rules artifact version is not compatible with the current rule engine"); + } + } catch (JsonParseException je) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Rule format is invalid: {}", je); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", je.getMessage()); + } + return ruleEditorBusinessLogic.importRules(mappingRules, requestId, userId, vfcmtUuid, dcaeCompLabel, nid, configParam); + } + + @RequestMapping(value = "/importPhase", method = {RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity importPhase(@RequestBody String json, @ModelAttribute("requestId") String requestId, @RequestHeader("USER_ID") String userId) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting importPhase", json); + return ruleEditorBusinessLogic.importPhase(json, requestId, userId); } /** diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogic.java index 94133e4..42807ae 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogic.java @@ -16,6 +16,7 @@ import org.onap.sdc.dcae.errormng.ServiceException; import org.onap.sdc.dcae.rule.editor.impl.RulesBusinessLogic; import org.onap.sdc.dcae.rule.editor.utils.RulesPayloadUtils; import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; +import org.onap.sdc.dcae.rule.editor.validators.MappingRulesValidator; import org.onap.sdc.dcae.utils.Normalizers; import org.onap.sdc.dcae.utils.SdcRestClientUtils; import org.onap.sdc.dcae.ves.VesDataItemsDefinition; @@ -41,6 +42,8 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { @Autowired private RulesBusinessLogic rulesBusinessLogic; + private MappingRulesValidator mappingRulesValidator = MappingRulesValidator.getInstance(); + private static final String EXCEPTION = "Exception {}"; public ResponseEntity saveRule(String json, String requestId, String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam) { @@ -91,6 +94,58 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } } + public ResponseEntity applyFilter(String json, String requestId, String userId) { + + try { + ApplyFilterRequest request = RulesPayloadUtils.convertFromPayload(json, ApplyFilterRequest.class); + if (null == request) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_CONTENT); + } + if(!validateMandatoryRequestFields(request)) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid apply filter request. request: {}", request); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.RULE_OPERATION_FAILED_MISSING_PARAMS); + } + List errors = rulesBusinessLogic.validateFilter(request.getFilter()); + if (!errors.isEmpty()) { + // this will return the first violation found by the validator to the UI view as a regular error and all violations to the console view + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, errors.stream().map(ServiceException::getFormattedErrorMessage).collect(Collectors.joining(", ")), errors.get(0).getFormattedErrorMessage()); + } + + ResourceDetailed vfcmt = getSdcRestClient().getResource(request.getVfcmtUuid(), requestId); + checkVfcmtType(vfcmt); + + if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED); + } + + String artifactLabel = Normalizers.normalizeArtifactLabel(request.getDcaeCompLabel() + request.getNid() + request.getConfigParam()); + + // check for MappingRules artifact in existing artifacts + Artifact artifactFound = vfcmt.getArtifacts().stream() + .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))) + .findAny().orElse(null); + + // new mappingRules artifact, validate nid exists in composition before creating new artifact + if (null == artifactFound) { + if (cdumpContainsNid(vfcmt, request.getNid(), requestId)) { + MappingRules body = new MappingRules(request); + saveNewRulesArtifact(body, vfcmt.getUuid(), generateMappingRulesFileName(request.getDcaeCompLabel(),request.getNid(), request.getConfigParam()), artifactLabel, userId, requestId); + return checkInAndReturnSaveArtifactResult(request.getFilter(), vfcmt.getUuid(), userId, requestId); + } + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.NODE_NOT_FOUND, "", request.getDcaeCompLabel()); + } + + //update artifact flow - apply filter to existing artifact + return applyFilterToExistingArtifact(request, userId, artifactFound, requestId); + + } catch (JsonParseException je) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: request format is invalid: {}", je); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", je.getMessage()); + } catch (Exception e) { + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); + } + } + public ResponseEntity getRulesAndSchema(String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String requestId) { try { @@ -180,6 +235,53 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } } + public ResponseEntity deleteFilter(String json, String requestId, String userId) { + + try { + RuleEditorRequest request = RulesPayloadUtils.convertFromPayload(json, RuleEditorRequest.class); + if (null == request) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_CONTENT); + } + if(!validateMandatoryRequestFields(request)) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid delete filter request. request: {}", request); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.RULE_OPERATION_FAILED_MISSING_PARAMS); + } + ResourceDetailed vfcmt = getSdcRestClient().getResource(request.getVfcmtUuid(), requestId); + if (null == vfcmt.getArtifacts()) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "VFCMT {} doesn't have artifacts", vfcmt.getUuid()); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.FILTER_NOT_FOUND); + } + String artifactLabel = Normalizers.normalizeArtifactLabel(request.getDcaeCompLabel() + request.getNid() + request.getConfigParam()); + + // check for MappingRules artifact in existing artifacts + Artifact mappingRuleFile = vfcmt.getArtifacts().stream() + .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))) + .findAny().orElse(null); + + if (null == mappingRuleFile) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "{} doesn't exist for VFCMT {}", artifactLabel, vfcmt.getUuid()); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.FILTER_NOT_FOUND); + } + + String payload = getSdcRestClient().getResourceArtifact(vfcmt.getUuid(), mappingRuleFile.getArtifactUUID(), requestId); + MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); + BaseCondition deletedFilter = rules.getFilter(); + if (null == deletedFilter) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Filter not found."); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.FILTER_NOT_FOUND); + } + if (rules.isEmpty()) { // if the file doesn't contain any rules -> let's delete the file + getSdcRestClient().deleteResourceArtifact(userId, vfcmt.getUuid(), mappingRuleFile.getArtifactUUID(), requestId); + } else { + rules.setFilter(null); + updateRulesArtifact(vfcmt.getUuid(), userId, mappingRuleFile, rules, requestId); + } + return checkInAndReturnSaveArtifactResult(deletedFilter, vfcmt.getUuid(), userId, requestId); + } catch (Exception e) { + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); + } + } + public ResponseEntity deleteGroupOfRules(String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String groupId, String requestId) { try { @@ -222,7 +324,7 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { public ResponseEntity translateRules(TranslateRequest request, String requestId) { try { - if(!rulesBusinessLogic.validateTranslateRequestFields(request)) { + if(!validateTranslateRequestFields(request)) { errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid translate request. request: {}", request); return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "please enter valid request parameters"); } @@ -260,9 +362,12 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } } - public ResponseEntity importRules(String json, String requestId, String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam) { + public ResponseEntity importRules(MappingRulesResponse mappingRules, String requestId, String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam) { try { - MappingRulesResponse mappingRules = RulesPayloadUtils.parsePayloadToMappingRules(json); + if(!mappingRulesValidator.validateVersionAndType(mappingRules)) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid or missing VES version definition"); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "Invalid or missing VES version definitions", "The imported rules artifact is unsupported"); + } List errors = rulesBusinessLogic.validateImportedRules(mappingRules); if (!errors.isEmpty()) { // this will return the first violation found by the validator to the UI view as a regular error and all violations to the console view @@ -301,7 +406,81 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } catch (Exception e) { return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); } + } + + public ResponseEntity importPhase(String json, String requestId, String userId) { + + MappingRulesResponse allRules; + try { + ImportPhaseRequest request = RulesPayloadUtils.convertFromPayload(json, ImportPhaseRequest.class); + if (null == request) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_CONTENT); + } + if(!validateImportPhaseRequestFields(request)) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid import phase request. request: {}", request); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.RULE_OPERATION_FAILED_MISSING_PARAMS); + } + if(!validateVesVersionAndEventDomainMatch(request)) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Invalid ves definitions, {} != {} or {} != {}", request.getEventType(), request.getPayload().getEventType(), request.getVersion(), request.getPayload().getVersion()); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", "The Imported rules VES version is not compatible with the current rules VES version"); + } + MappingRulesResponse inputRules = request.getPayload(); + if(!validateEditorVersion(inputRules, false)) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", "The imported rules artifact version is not compatible with the current rule engine"); + } + + // set the groupId and phase to be saved + inputRules.getRules().forEach((k,v) -> { + v.setGroupId(request.getGroupId()); + v.setPhase(request.getPhase()); + }); + List errors = rulesBusinessLogic.validateImportedRules(inputRules); + if (!errors.isEmpty()) { + // this will return the first violation found by the validator to the UI view as a regular error and all violations to the console view + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, errors.stream().map(ServiceException::getFormattedErrorMessage).collect(Collectors.joining(", ")), errors.get(0).getFormattedErrorMessage()); + } + + ResourceDetailed vfcmt = getSdcRestClient().getResource(request.getVfcmtUuid(), requestId); + checkVfcmtType(vfcmt); + + if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED); + } + + String artifactLabel = Normalizers.normalizeArtifactLabel(request.getDcaeCompLabel() + request.getNid() + request.getConfigParam()); + + // check for MappingRules artifact in existing artifacts + Artifact artifactFound = vfcmt.getArtifacts().stream() + .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))) + .findAny().orElse(null); + + // new mappingRules artifact, validate nid exists in composition before creating new artifact + if (null == artifactFound) { + if (!cdumpContainsNid(vfcmt, request.getNid(), requestId)) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.NODE_NOT_FOUND, "", request.getDcaeCompLabel()); + } + saveNewRulesArtifact(inputRules, vfcmt.getUuid(), generateMappingRulesFileName(request.getDcaeCompLabel(), request.getNid(), request.getConfigParam()), artifactLabel, userId, requestId); + allRules = inputRules; + } else { + allRules = RulesPayloadUtils.parsePayloadToMappingRules(getSdcRestClient().getResourceArtifact(vfcmt.getUuid(), artifactFound.getArtifactUUID(), requestId)); + allRules.getRules().putAll(inputRules.getRules()); + updateRulesArtifact(vfcmt.getUuid(), userId, artifactFound, allRules, requestId); + } + allRules.setSchema(getEventTypeDefinitionUIs(allRules.getVersion(), allRules.getEventType())); + return checkInAndReturnSaveArtifactResult(allRules, vfcmt.getUuid(), userId, requestId); + + } catch (JsonParseException je) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Rule format is invalid: {}", je); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", je.getMessage()); + } catch (Exception e) { + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); + } + } + + // when importing a rules file all rules must match the declared format (supportGroups) + public boolean validateEditorVersion(MappingRules rules, boolean supportGroups) { + return supportGroups ? mappingRulesValidator.validateGroupDefinitions(rules) : rules.getRules().values().stream().noneMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId())); } public ResponseEntity getExistingRuleTargets(String vfcmtUuid, String requestId, String dcaeCompLabel, String nid) { @@ -404,6 +583,16 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return checkInAndReturnSaveArtifactResult(rule.toJson(), vfcmtUuid, userId, requestId); } + private ResponseEntity applyFilterToExistingArtifact(ApplyFilterRequest request, String userId, Artifact rulesArtifact, String requestId) throws JsonProcessingException { + String payload = getSdcRestClient().getResourceArtifact(request.getVfcmtUuid(), rulesArtifact.getArtifactUUID(), requestId); + MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); + rules.setEntryPhase(request.getEntryPhase()); + rules.setPublishPhase(request.getPublishPhase()); + rules.setFilter(request.getFilter()); + updateRulesArtifact(request.getVfcmtUuid(), userId, rulesArtifact, rules, requestId); + return checkInAndReturnSaveArtifactResult(request.getFilter(), request.getVfcmtUuid(), userId, requestId); + } + // regardless of check in result, return save artifact success private ResponseEntity checkInAndReturnSaveArtifactResult(Object response, String vfcmtUuid, String userId, String requestId) { try { @@ -422,6 +611,23 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { getSdcRestClient().updateResourceArtifact(userId, vfcmtUuid, artifactInfo, requestId); } + private boolean validateTranslateRequestFields(TranslateRequest request) { + return validateMandatoryRequestFields(request) && Stream.of(request.getPublishPhase(), request.getEntryPhase()).allMatch(ValidationUtils::validateNotEmpty) + && !request.getEntryPhase().equalsIgnoreCase(request.getPublishPhase()); + } + + private boolean validateImportPhaseRequestFields(ImportPhaseRequest request) { + return validateMandatoryRequestFields(request) && Stream.of(request.getGroupId(), request.getPhase(), request.getVersion(), request.getEventType()).allMatch(ValidationUtils::validateNotEmpty) && null != request.getPayload(); + } + + private boolean validateMandatoryRequestFields(RuleEditorRequest request) { + return Stream.of(request.getVfcmtUuid(), request.getDcaeCompLabel(), request.getNid(), request.getConfigParam()).allMatch(ValidationUtils::validateNotEmpty); + } + + private boolean validateVesVersionAndEventDomainMatch(ImportPhaseRequest request) { + return request.getPayload().getVersion().equalsIgnoreCase(request.getVersion()) && request.getPayload().getEventType().equalsIgnoreCase(request.getEventType()); + } + /** * @param eventMapStream diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java index cac92f5..b06b5b1 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ActionStatus.java @@ -40,6 +40,8 @@ public enum ActionStatus { RULE_DEPENDENCY, NODE_NOT_FOUND, DELETE_RULE_FAILED, + FILTER_NOT_FOUND, + RULE_OPERATION_FAILED_MISSING_PARAMS, TRANSLATE_FAILED, CATALOG_NOT_AVAILABLE, AUTH_ERROR, diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java index 468a6d5..ced922b 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogic.java @@ -10,6 +10,7 @@ import org.onap.sdc.dcae.errormng.ActionStatus; import org.onap.sdc.dcae.errormng.ErrConfMgr; import org.onap.sdc.dcae.errormng.ResponseFormat; import org.onap.sdc.dcae.errormng.ServiceException; +import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType; import org.onap.sdc.dcae.rule.editor.translators.MappingRulesTranslator; import org.onap.sdc.dcae.rule.editor.utils.EmptyStringTranslationSerializer; import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; @@ -22,7 +23,6 @@ import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; @Component public class RulesBusinessLogic { @@ -33,6 +33,13 @@ public class RulesBusinessLogic { private MappingRulesTranslator mappingRulesTranslator = MappingRulesTranslator.getInstance(); private static Gson gsonTranslator = new GsonBuilder().registerTypeAdapter(String.class, new EmptyStringTranslationSerializer()).enableComplexMapKeySerialization().create(); + + public List validateFilter(BaseCondition filter) { + List errors = new ArrayList<>(); + RuleEditorElementType.getElementTypeByName(filter.getClass().getSimpleName()).getValidator().validate(filter, errors); + return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList()); + } + public List validateRule(Rule rule) { List errors = new ArrayList<>(); if(ruleValidator.validate(rule, errors)) { @@ -43,7 +50,7 @@ public class RulesBusinessLogic { public List validateImportedRules(MappingRules rules) { List errors = new ArrayList<>(); - if(mappingRulesValidator.validate(rules, errors)){ + if(mappingRulesValidator.validate(rules, errors)) { rules.getRules().forEach((k,v) -> { v.setUid(k); detectAndResolveActionDependencies(v, errors); @@ -80,6 +87,7 @@ public class RulesBusinessLogic { } + // when saving a single rule its declared format (supportGroups) must match the existing rules format (a single match is enough as all previously saved rules were already validated) public boolean validateGroupDefinitions(MappingRules rules, boolean supportGroups) { return supportGroups == rules.getRules().values().stream().anyMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId())); } @@ -184,11 +192,6 @@ public class RulesBusinessLogic { rules.setRules(rulesMap); } - public boolean validateTranslateRequestFields(TranslateRequest request) { - return Stream.of(request.getVfcmtUuid(), request.getDcaeCompLabel(), request.getNid(), request.getConfigParam(), request.getPublishPhase(), request.getEntryPhase()).allMatch(ValidationUtils::validateNotEmpty) - && !request.getEntryPhase().equalsIgnoreCase(request.getPublishPhase()); - } - public void updateGlobalTranslationFields(MappingRules mappingRules, TranslateRequest request, String vfcmtName) { mappingRules.setEntryPhase(request.getEntryPhase()); mappingRules.setPublishPhase(request.getPublishPhase()); diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java index cefb429..06f0bab 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MappingRulesTranslator.java @@ -19,7 +19,6 @@ public class MappingRulesTranslator implements IRuleElementTranslator { } } + private class EntryPhaseTranslation extends RuleTranslation { + + private EntryPhaseTranslation(String phaseName, String runPhase) { + phase = phaseName; + processors.add(new RunPhaseProcessorsTranslation(runPhase)); + } + + private EntryPhaseTranslation(String phaseName, String runPhase, BaseCondition entryPhaseFilter) { + this(phaseName, runPhase); + if("snmp_map".equals(phaseName)) { + processors.add(0, new SnmpConvertor()); + } + if(null != entryPhaseFilter) { + filter = getConditionTranslator(entryPhaseFilter).translateToHpJson(entryPhaseFilter); + } + } + } + + // hardcoded SNMP processor + + private class SnmpConvertor extends ProcessorTranslation { + private String array = "varbinds"; + private String datacolumn = "varbind_value"; + private String keycolumn = "varbind_oid"; + + private SnmpConvertor() { + clazz = "SnmpConvertor"; + } + } + public Object translateToHpJson(Rule rule) { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Start translating rule {}", rule.getUid()); Object translation = new ActionRuleTranslation(rule); @@ -37,6 +67,13 @@ public class RuleTranslator implements IRuleElementTranslator { return translation; } + public Object entryPhaseTranslation(String entryPhase, String runPhase, BaseCondition entryPhaseFilter) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Start translating entry phase {}", entryPhase); + Object translation = new EntryPhaseTranslation(entryPhase, runPhase, entryPhaseFilter); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished translation for entry phase {}. Result: {}", entryPhase, new Gson().toJson(translation)); + return translation; + } + private IRuleElementTranslator getConditionTranslator(BaseCondition condition){ return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() : getSimpleConditionTranslator((Condition) condition); diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java index 8391d76..4422da5 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/RulesPayloadUtils.java @@ -22,15 +22,19 @@ public class RulesPayloadUtils { private RulesPayloadUtils(){} public static Rule parsePayloadToRule(String payload) { - return gson.fromJson(payload, Rule.class); + return convertFromPayload(payload, Rule.class); } public static MappingRules parseMappingRulesArtifactPayload(String payload) { - return gson.fromJson(payload, MappingRules.class); + return convertFromPayload(payload, MappingRules.class); } public static MappingRulesResponse parsePayloadToMappingRules(String payload) { - return gson.fromJson(payload, MappingRulesResponse.class); + return convertFromPayload(payload, MappingRulesResponse.class); + } + + public static T convertFromPayload(String payload, Class type) { + return gson.fromJson(payload, type); } public static SchemaInfo extractInfoFromDescription(Artifact rulesArtifact) { diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java index 9ba4479..4fa32a3 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionValidator.java @@ -1,12 +1,12 @@ package org.onap.sdc.dcae.rule.editor.validators; +import org.apache.commons.lang.StringUtils; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition; import org.onap.sdc.dcae.errormng.ActionStatus; import org.onap.sdc.dcae.errormng.ErrConfMgr; import org.onap.sdc.dcae.errormng.ResponseFormat; import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum; import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; -import org.springframework.util.CollectionUtils; import java.util.List; @@ -32,10 +32,11 @@ public class ConditionValidator extends BaseConditionValidator { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "left")); } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getTypeByName(condition.getOperator()); + OperatorTypeEnum operatorTypeEnum = StringUtils.isNotEmpty(condition.getOperator()) ? OperatorTypeEnum.getTypeByName(condition.getOperator()) : null; if(null == operatorTypeEnum) { valid = false; - errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_OPERATOR, null, condition.getOperator())); + String operatorValue = StringUtils.isNotEmpty(condition.getOperator()) ? condition.getOperator() : "empty"; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_OPERATOR, null, operatorValue)); } if(OperatorTypeEnum.ASSIGNED != operatorTypeEnum && OperatorTypeEnum.UNASSIGNED != operatorTypeEnum && (condition.getRight().isEmpty() || !condition.getRight().stream().allMatch(ValidationUtils::validateNotEmpty))) { valid = false; diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MappingRulesValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MappingRulesValidator.java index 90fda4d..baaff9e 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MappingRulesValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MappingRulesValidator.java @@ -1,6 +1,5 @@ package org.onap.sdc.dcae.rule.editor.validators; -import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRules; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Rule; import org.onap.sdc.dcae.errormng.ActionStatus; @@ -27,31 +26,23 @@ public class MappingRulesValidator implements IRuleElementValidator errors) { - return validateVersionAndType(rules, errors) && validateImportedGroupDefinitions(rules, errors) && rules.getRules().values().stream().map(r -> ruleValidator.validate(r, errors)) - .reduce(true, (x,y) -> x && y); - // TODO consider using 'allMatch' which will stop on the first error + boolean valid = true; + if(rules.isEmpty()) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, "", "no rules found")); + } + return rules.getRules().values().stream().map(r -> ruleValidator.validate(r, errors)) + .reduce(true, (x,y) -> x && y) && valid; + // TODO consider using 'allMatch' which will stop on the first error } - private boolean validateVersionAndType(MappingRules rules, List errors) { + public boolean validateVersionAndType(MappingRules rules) { Map> supportedVersions = VesStructureLoader.getAvailableVersionsAndEventTypes(); - boolean valid = ValidationUtils.validateNotEmpty(rules.getVersion()) && supportedVersions.containsKey(rules.getVersion()) && ValidationUtils.validateNotEmpty(rules.getEventType()) && supportedVersions.get(rules.getVersion()).contains(rules.getEventType()); - errLogger.log(LogLevel.INFO, this.getClass().getName(), "validate mapping rules fields: eventType/version {}", valid); - if(!valid) { - errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.VES_SCHEMA_NOT_FOUND, null)); - } - return valid; + return ValidationUtils.validateNotEmpty(rules.getVersion()) && supportedVersions.containsKey(rules.getVersion()) && ValidationUtils.validateNotEmpty(rules.getEventType()) && supportedVersions.get(rules.getVersion()).contains(rules.getEventType()); } - private boolean validateImportedGroupDefinitions(MappingRules rules, List errors) { - boolean valid = !rules.isEmpty() && (rules.getRules().values().stream().noneMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId()) || ValidationUtils.validateNotEmpty(r.getPhase())) || validateGroupDefinitions(rules)); - errLogger.log(LogLevel.INFO, this.getClass().getName(), "validate group definitions {}", valid); - if(!valid) { - errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, null, "invalid phase definitions")); - } - return valid; - } - private boolean validateGroupDefinitions(MappingRules rules) { + public boolean validateGroupDefinitions(MappingRules rules) { return rules.getRules().values().stream().allMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId()) && ValidationUtils.validateNotEmpty(r.getPhase())) && rules.getRules().values().stream().collect(Collectors.groupingBy(Rule::getGroupId, Collectors.mapping(Rule::getPhase, Collectors.toSet()))).values().stream().allMatch(p -> 1 == p.size()); } diff --git a/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/error-configuration.yaml b/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/error-configuration.yaml index c60465c..dba2454 100644 --- a/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/error-configuration.yaml +++ b/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/error-configuration.yaml @@ -283,4 +283,16 @@ errors: code: 400, message: "The request was partially successful. Removing the attached Blueprint from the service has failed. You must manually delete the artifact.", messageId: "SVC6118" + } +#---------SVC6119----------------------------- + FILTER_NOT_FOUND: { + code: 404, + message: "Filter to delete not found", + messageId: "SVC6119" + } +#---------SVC6120----------------------------- + RULE_OPERATION_FAILED_MISSING_PARAMS: { + code: 404, + message: "One or more parameters is missing in the sent JSON", + messageId: "SVC6120" } \ No newline at end of file diff --git a/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogicTest.java b/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogicTest.java index 3c6d1dd..4a03845 100644 --- a/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogicTest.java +++ b/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/RuleEditorBusinessLogicTest.java @@ -8,6 +8,7 @@ import org.mockito.MockitoAnnotations; import org.onap.sdc.dcae.catalog.asdc.ASDCException; import org.onap.sdc.dcae.client.ISdcClient; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRules; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRulesResponse; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Rule; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.SchemaInfo; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; @@ -102,17 +103,11 @@ public class RuleEditorBusinessLogicTest { @Test - public void invalidRuleFormatImportRulesFailureTest() throws Exception { - String invalidInput = "{rules:[blahblahblah]}"; - String expectedError = "Error - Rule format is invalid: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 9 path $.rules[0]."; - ResponseEntity result = ruleEditorBusinessLogic.importRules(invalidInput, requestId, userId, vfcmtUuid, dcaeCompLabel, nId, configParam); - assertEquals(400,result.getStatusCodeValue()); - assertEquals(expectedError, result.getBody().getRequestError().getServiceException().getFormattedErrorMessage()); - verify(rulesBusinessLogic, times(0)).validateImportedRules(any()); - verify(sdcClientMock, times(0)).getResource(anyString(), anyString()); - verify(sdcClientMock, times(0)).createResourceArtifact(anyString(), anyString(), any(), anyString()); - verify(sdcClientMock, times(0)).updateResourceArtifact(anyString(), anyString(), any(), anyString()); - verify(sdcClientMock, times(0)).changeResourceLifecycleState(anyString(), anyString(), anyString(), anyString(), anyString()); + public void incompatibleEditorVersionFailureTest() throws Exception { + Rule rule = new Rule(); + rule.setGroupId("id_1"); + MappingRules rules = new MappingRules(rule); + assertFalse(ruleEditorBusinessLogic.validateEditorVersion(rules, false)); } @Test @@ -194,6 +189,121 @@ public class RuleEditorBusinessLogicTest { assertEquals(200,result.getStatusCodeValue()); } + private static final String BODY_JSON = "{\n" + + " \"version\": \"4.1\",\n" + + " \"eventType\": \"syslogFields\",\n" + + " \"filter\": {\n" + + " \"name\": \"condition\",\n" + + " \"left\": \"a\",\n" + + " \"right\": [\n" + + " \"b\"\n" + + " ],\n" + + " \"operator\": \"contains\",\n" + + " \"level\": 1,\n" + + " \"emptyIsAssigned\": false,\n" + + " \"id\": 6439610383188\n" + + " },\n" + + " \"vfcmtUuid\": \"6fcb27c8-3e87-4a04-b032-4de70fbd9d03\",\n" + + " \"dcaeCompLabel\": \"Highlandpark_18.06.006\",\n" + + " \"nid\": \"n.1532849382756.2\",\n" + + " \"configParam\": \"centralOrEdge\"\n" + + "}\n"; + + @Test + public void test_applyFilter_missingCompLabel() throws Exception { + String json = BODY_JSON.replaceAll("Highlandpark_18.06.006", ""); + + ResponseEntity result = ruleEditorBusinessLogic.applyFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_applyFilter_missingNid() throws Exception { + String json = BODY_JSON.replaceAll("n.1532849382756.2", ""); + + ResponseEntity result = ruleEditorBusinessLogic.applyFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_applyFilter_missingVfcmtUuid() throws Exception { + String json = BODY_JSON.replaceAll("6fcb27c8-3e87-4a04-b032-4de70fbd9d03", ""); + + ResponseEntity result = ruleEditorBusinessLogic.applyFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_applyFilter_missingConfigParam() throws Exception { + String json = BODY_JSON.replaceAll("centralOrEdge", ""); + + ResponseEntity result = ruleEditorBusinessLogic.applyFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_deleteFilter_missingCompLabel() throws Exception { + String json = BODY_JSON.replaceAll("Highlandpark_18.06.006", ""); + + ResponseEntity result = ruleEditorBusinessLogic.deleteFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_deleteFilter_missingNid() throws Exception { + String json = BODY_JSON.replaceAll("n.1532849382756.2", ""); + + ResponseEntity result = ruleEditorBusinessLogic.deleteFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_deleteFilter_missingVfcmtUuid() throws Exception { + String json = BODY_JSON.replaceAll("6fcb27c8-3e87-4a04-b032-4de70fbd9d03", ""); + + ResponseEntity result = ruleEditorBusinessLogic.deleteFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_deleteFilter_missingConfigParam() throws Exception { + String json = BODY_JSON.replaceAll("centralOrEdge", ""); + + ResponseEntity result = ruleEditorBusinessLogic.deleteFilter(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_importPhase_missingCompLabel() throws Exception { + String json = BODY_JSON.replaceAll("Highlandpark_18.06.006", ""); + + ResponseEntity result = ruleEditorBusinessLogic.importPhase(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_importPhase_missingNid() throws Exception { + String json = BODY_JSON.replaceAll("n.1532849382756.2", ""); + + ResponseEntity result = ruleEditorBusinessLogic.importPhase(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_importPhase_missingVfcmtUuid() throws Exception { + String json = BODY_JSON.replaceAll("6fcb27c8-3e87-4a04-b032-4de70fbd9d03", ""); + + ResponseEntity result = ruleEditorBusinessLogic.importPhase(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } + + @Test + public void test_importPhase_missingConfigParam() throws Exception { + String json = BODY_JSON.replaceAll("centralOrEdge", ""); + + ResponseEntity result = ruleEditorBusinessLogic.importPhase(json, requestId, userId); + assertEquals(404,result.getStatusCodeValue()); + } private void emulateMockListOfArtifacts(String dcaeCompLabel, String nid, String configParam, boolean isApprovedArtifact) { List listOfArtifactCompositionYml = new ArrayList<>(); diff --git a/dcaedt_be/src/test/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogicTest.java b/dcaedt_be/src/test/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogicTest.java index 3b7181d..f7d7ed0 100644 --- a/dcaedt_be/src/test/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogicTest.java +++ b/dcaedt_be/src/test/java/org/onap/sdc/dcae/rule/editor/impl/RulesBusinessLogicTest.java @@ -68,10 +68,17 @@ public class RulesBusinessLogicTest { rule.getActions().add(buildCopyAction("2.0","event.commonEventHeader.version")); rule.setDescription("description"); rule.setPhase("phase_1"); - rule.setNotifyId("someValue"); rule.setEntryPhase("foi_map"); rule.setPublishPhase("map_publish"); MappingRules mr = new MappingRules(rule); + Condition condition = new Condition(); + condition.setLeft("${notify OID}"); + condition.getRight().add("someValue"); + condition.setOperator("startsWith"); + condition.setId("id"); + condition.setLevel("4"); + condition.setName("3"); + mr.setFilter(condition); List errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); -- cgit 1.2.3-korg