diff options
author | Eran (ev672n), Vosk <ev672n@att.com> | 2018-08-06 17:02:39 +0300 |
---|---|---|
committer | Eran (ev672n), Vosk <ev672n@att.com> | 2018-08-06 17:02:39 +0300 |
commit | 86457ed120fc236b1485ad3251589aedad2401bd (patch) | |
tree | a473c2faf16ffbb34aad75d4fef8afc3b2541f21 | |
parent | 735b58119b37ead5013c40afd941d63ef28ca053 (diff) |
Changing the dcae dt main code
Updating DCAE-dt-main code for Dockerizing the DCAE-CI code
Change-Id: Ia50d24e60e9ddc9bbc58dd8651d7a4f7e0dc8270
Issue-ID: SDC-1605
Signed-off-by: Eran (ev672n), Vosk <ev672n@att.com>
130 files changed, 5845 insertions, 5951 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..d6bd195 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Composition +Composition Refactoring + +## Docker Build +```sh +$ docker login -u <user> -p <password> <docker_registry> +$ mkdir -p docker/target +$ cp dcaedt_be/target/dcae.war docker/target/dcae.war +$ cd docker +$ docker build --no-cache -t dcaed-be -f Dockerfile . +``` +## Environment Configuration +The environment file must include the following new definition under "override_attributes": + ``"SDC": { + "BE":{ + "fqdn" : "zldcrdm2sdc4cbe01.3f1a87.rdm2.tci.att.com" + } + },`` +The environment json file should be injected into the docker by one of the following ways: +1. Place the json file under ```<host>:/data/environments```. + Run the docker with volume: + ```--volume /data/environments:/root/chef-solo/environments``` +2. Use ``docker cp`` to copy the json file into the docker ```/root/chef-solo/environments``` +## Docker Run +```sh +$ docker run -dit -p 8444:8444 --restart="always" --name=dcaed-be \ + --env ENVNAME=<environment_name> \ + --env JAVA_OPTIONS="-XX:MaxPermSize=256m -Xmx4713m \ + -Dconfig.home=\${JETTY_BASE}/config \ + -Dlog.home=/opt/logs/be \ + -Dlogging.config=\${JETTY_BASE}/config/dcae-be/logback-spring.xml" \ + [ --volume /data/environments:/root/chef-solo/environments ] \ + dcaed-be:latest \ + /bin/sh +``` diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java index ee8f5c6..f6f2cd0 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/CompositionConfig.java @@ -53,7 +53,9 @@ public class CompositionConfig { public static class FlowType { + @JsonProperty("entryPhase") private String entryPointPhaseName; + @JsonProperty("publishPhase") private String lastPhaseName; public String getEntryPointPhaseName() { @@ -81,7 +83,7 @@ public class CompositionConfig { Type map = new TypeToken<Map<String, FlowType>>(){}.getType(); flowTypesMap = new Gson().fromJson(flowTypes, map); } catch (Exception e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error – Failed to read flow type definitions"); + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error – Failed to read flow type definitions. message: {}", e); } } }
\ No newline at end of file diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java index 0d638d9..5d5c1e0 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/BlueprintController.java @@ -25,7 +25,7 @@ public class BlueprintController extends BaseController { * @param requestId * @return ResponseEntity */ - @RequestMapping(value = "{context}/createBluePrint/{VFCMTUuid}/{serviceUuid}/{instanceName}", method = RequestMethod.POST) + @RequestMapping(value = "{context}/createBluePrint/{VFCMTUuid}/{serviceUuid}/{instanceName:.*}", method = RequestMethod.POST) public ResponseEntity createBlueprint( @RequestHeader("USER_ID") String userId, @PathVariable String context, @@ -37,7 +37,7 @@ public class BlueprintController extends BaseController { } @Deprecated - @RequestMapping(value = "/createBluePrint/{VFCMTUuid}/{serviceUuid}/{instanceName}/{monitoringFlowType}", method = RequestMethod.POST) + @RequestMapping(value = "/createBluePrint/{VFCMTUuid}/{serviceUuid}/{instanceName}/{monitoringFlowType:.*}", method = RequestMethod.POST) public ResponseEntity createBluePrintWithFlowType( @RequestHeader("USER_ID") String userId, @PathVariable("VFCMTUuid") String vfcmtUuid, diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java index dbcbcc9..aad0250 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java @@ -11,24 +11,15 @@ import org.onap.sdc.dcae.composition.restmodels.ReferenceUUID; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import org.onap.sdc.dcae.composition.util.DcaeBeConstants; -import org.onap.sdc.dcae.enums.LifecycleOperationType; -import org.onap.sdc.dcae.errormng.ActionStatus; -import org.onap.sdc.dcae.errormng.ErrConfMgr; import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - @RestController @EnableAutoConfiguration @CrossOrigin @@ -40,78 +31,77 @@ public class CompositionController extends BaseController { @Autowired private CompositionBusinessLogic compositionBusinessLogic; - @Deprecated - @RequestMapping(value = { "/utils/clone/{assetType}/{sourceId}/{targetId}" }, method = { RequestMethod.GET }, produces = { "application/json" }) - public ResponseEntity clone(@RequestHeader("USER_ID") String userId, - @PathVariable("assetType") String theAssetType, @PathVariable("sourceId") String theSourceId, @PathVariable("targetId") String theTargetId, @ModelAttribute("requestId") String requestId) { - MessageResponse response = new MessageResponse(); - - try { - // fetch the source and assert it is a vfcmt containing clone worthy artifacts (composition + rules) - ResourceDetailed sourceVfcmt = baseBusinessLogic.getSdcRestClient().getResource(theSourceId, requestId); - baseBusinessLogic.checkVfcmtType(sourceVfcmt); - List<Artifact> artifactsToClone = CollectionUtils.isEmpty(sourceVfcmt.getArtifacts()) ? - null : - sourceVfcmt.getArtifacts().stream().filter(p -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(p.getArtifactName()) || p.getArtifactName().endsWith(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX)) - .collect(Collectors.toList()); - if (CollectionUtils.isEmpty(artifactsToClone)) { - response.setSuccessResponse("Nothing to clone"); - return new ResponseEntity<>(response, HttpStatus.NO_CONTENT); - } - - // fetch the target - ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(theTargetId, requestId); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString()); - baseBusinessLogic.checkVfcmtType(vfcmt); - baseBusinessLogic.checkUserIfResourceCheckedOut(userId, vfcmt); - boolean isTargetNeed2Checkout = baseBusinessLogic.isNeedToCheckOut(vfcmt.getLifecycleState()); - if (isTargetNeed2Checkout) { - ResourceDetailed targetVfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKOUT.name(), "checking out VFCMT before clone", requestId); - if (null == targetVfcmt) { - return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR); - } - theTargetId = targetVfcmt.getUuid(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New targetVfcmt (for artifact clone) after checkoutVfcmt is: {}", theTargetId); - } - - Map<String, Artifact> currentArtifacts = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? new HashMap<>() : vfcmt.getArtifacts().stream().collect(Collectors.toMap(Artifact::getArtifactName, Function.identity())); - - //TODO target VFCMT rule artifacts should be removed - for (Artifact artifactToClone : artifactsToClone) { - String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(theSourceId, artifactToClone.getArtifactUUID(), requestId); - baseBusinessLogic.cloneArtifactToTarget(userId, theTargetId, payload, artifactToClone, currentArtifacts.get(artifactToClone.getArtifactName()), requestId); - } - - baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKIN.name(), "check in VFCMT after clone", requestId); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Cloning {} from {} has finished successfully", theSourceId, theTargetId); - response.setSuccessResponse("Clone VFCMT complete"); - return new ResponseEntity<>(response, HttpStatus.OK); - } catch (Exception e) { - return handleException(e, ApiType.CLONE_VFCMT); - } - } - - @RequestMapping(value = "/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") - public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest) { - return compositionCatalogBusinessLogic.getItems(theRequest); +// @Deprecated +// @RequestMapping(value = { "/utils/clone/{assetType}/{sourceId}/{targetId}" }, method = { RequestMethod.GET }, produces = { "application/json" }) +// public ResponseEntity clone(@RequestHeader("USER_ID") String userId, +// @PathVariable("assetType") String theAssetType, @PathVariable("sourceId") String theSourceId, @PathVariable("targetId") String theTargetId, @ModelAttribute("requestId") String requestId) { +// MessageResponse response = new MessageResponse(); +// +// try { +// // fetch the source and assert it is a vfcmt containing clone worthy artifacts (composition + rules) +// ResourceDetailed sourceVfcmt = baseBusinessLogic.getSdcRestClient().getResource(theSourceId, requestId); +// baseBusinessLogic.checkVfcmtType(sourceVfcmt); +// List<Artifact> artifactsToClone = CollectionUtils.isEmpty(sourceVfcmt.getArtifacts()) ? +// null : +// sourceVfcmt.getArtifacts().stream().filter(p -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(p.getArtifactName()) || p.getArtifactName().endsWith(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX)) +// .collect(Collectors.toList()); +// if (CollectionUtils.isEmpty(artifactsToClone)) { +// response.setSuccessResponse("Nothing to clone"); +// return new ResponseEntity<>(response, HttpStatus.NO_CONTENT); +// } +// +// // fetch the target +// ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(theTargetId, requestId); +// debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString()); +// baseBusinessLogic.checkVfcmtType(vfcmt); +// baseBusinessLogic.checkUserIfResourceCheckedOut(userId, vfcmt); +// boolean isTargetNeed2Checkout = baseBusinessLogic.isNeedToCheckOut(vfcmt.getLifecycleState()); +// if (isTargetNeed2Checkout) { +// ResourceDetailed targetVfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKOUT.name(), "checking out VFCMT before clone", requestId); +// if (null == targetVfcmt) { +// return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR); +// } +// theTargetId = targetVfcmt.getUuid(); +// debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New targetVfcmt (for artifact clone) after checkoutVfcmt is: {}", theTargetId); +// } +// +// Map<String, Artifact> currentArtifacts = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? new HashMap<>() : vfcmt.getArtifacts().stream().collect(Collectors.toMap(Artifact::getArtifactName, Function.identity())); +// +// //TODO target VFCMT rule artifacts should be removed +// for (Artifact artifactToClone : artifactsToClone) { +// String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(theSourceId, artifactToClone.getArtifactUUID(), requestId); +// baseBusinessLogic.cloneArtifactToTarget(userId, theTargetId, payload, artifactToClone, currentArtifacts.get(artifactToClone.getArtifactName()), requestId); +// } +// +// baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKIN.name(), "check in VFCMT after clone", requestId); +// debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Cloning {} from {} has finished successfully", theSourceId, theTargetId); +// response.setSuccessResponse("Clone VFCMT complete"); +// return new ResponseEntity<>(response, HttpStatus.OK); +// } catch (Exception e) { +// return handleException(e, ApiType.CLONE_VFCMT); +// } +// } + + @RequestMapping(value = "/{theItemId}/model", method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity model(@ModelAttribute("requestId") String requestId, @PathVariable String theItemId) { + return compositionCatalogBusinessLogic.getModelById(requestId, theItemId); } - @RequestMapping(value = "/{theItemId}/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") - public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest, @PathVariable String theItemId) { - return compositionCatalogBusinessLogic.getItemById(theRequest, theItemId); + @RequestMapping(value = "/{theItemId}/type/{theTypeName:.*}", method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity typeInfo(@ModelAttribute("requestId") String requestId, @PathVariable String theItemId, @PathVariable String theTypeName) { + return compositionCatalogBusinessLogic.getTypeInfo(theItemId, theTypeName); } - @RequestMapping(value = "/{theItemId}/model", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") - public DeferredResult model(@RequestBody(required = false) ElementRequest theRequest, @PathVariable String theItemId) { - return compositionCatalogBusinessLogic.getModelById(theRequest, theItemId); - } - - @RequestMapping(value = "/{theItemId}/type/{theTypeName}", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") - public DeferredResult<CatalogResponse> model(@RequestBody(required = false) ElementRequest theRequest, @PathVariable String theItemId, @PathVariable String theTypeName) { - return compositionCatalogBusinessLogic.getTypeInfo(theRequest, theItemId, theTypeName); + @RequestMapping(value = "/catalog", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getCatalog(@ModelAttribute("requestId") String requestId) { + try { + return new ResponseEntity<>(compositionCatalogBusinessLogic.getCatalog(requestId), HttpStatus.OK); + } catch (Exception e) { + return handleException(e, ApiType.GET_MODEL); + } } - @RequestMapping(value = { "/getComposition/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = { "application/json" }) + @RequestMapping(value = { "/getComposition/{vfcmtUuid}" }, method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getComposition(@PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId) { MessageResponse response = new MessageResponse(); try { @@ -131,7 +121,7 @@ public class CompositionController extends BaseController { } - @RequestMapping(value = { "/getMC/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = {"application/json" }) + @RequestMapping(value = { "/getMC/{vfcmtUuid}" }, method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getMC(@PathVariable String vfcmtUuid, @ModelAttribute String requestId) { try { return new ResponseEntity<>(compositionBusinessLogic.getDataAndComposition(vfcmtUuid, requestId), HttpStatus.OK); diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java index 65663f6..ffedde8 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/ConfigurationController.java @@ -13,10 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; @@ -59,5 +56,21 @@ public class ConfigurationController extends BaseController { } } + @RequestMapping(value = "/getPhases/{flowType}", method = RequestMethod.GET) + public ResponseEntity getPhasesByFlowType(@PathVariable String flowType) { + try { + CompositionConfig.FlowType phases = compositionConfig.getFlowTypesMap().get(flowType); + if(null == phases) { + phases = new CompositionConfig.FlowType(); + phases.setEntryPointPhaseName(""); + phases.setLastPhaseName(""); + } + return new ResponseEntity<>(phases, HttpStatus.OK); + } catch (Exception e) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"Exception:{}",e); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.FLOW_TYPES_CONFIGURATION_ERROR); + } + } + } 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 d7ddd6f..1e93cf5 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 @@ -2,8 +2,10 @@ package org.onap.sdc.dcae.composition.controller; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.impl.RuleEditorBusinessLogic; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.TranslateRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -76,10 +78,35 @@ public class RuleEditorController extends BaseController { @PathVariable("configParam") String configParam, @ModelAttribute("requestId") String requestId) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting getRules", vfcmtUuid); - return ruleEditorBusinessLogic.getRules(vfcmtUuid, dcaeCompLabel, nid, configParam, requestId); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting getRulesAndSchema", vfcmtUuid); + return ruleEditorBusinessLogic.getRulesAndSchema(vfcmtUuid, dcaeCompLabel, nid, configParam, requestId); } + @RequestMapping(value = "/export/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam:.*}", method = {RequestMethod.GET}, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public ResponseEntity downloadRules( + @PathVariable("vfcmtUuid") String vfcmtUuid, + @PathVariable("dcaeCompLabel") String dcaeCompLabel, + @PathVariable("nid") String nid, + @PathVariable("configParam") String configParam, + @ModelAttribute("requestId") String requestId) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting exportRules", vfcmtUuid); + return ruleEditorBusinessLogic.downloadRules(vfcmtUuid, dcaeCompLabel, nid, configParam, requestId); + } + + @RequestMapping(value = "/import/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam:.*}", 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) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting importRules", json); + return ruleEditorBusinessLogic.importRules(json, requestId, userId, vfcmtUuid, dcaeCompLabel, nid, configParam); + } + /** * This endpoint functions as a 'delete' service for the rule editor UI * @@ -104,30 +131,54 @@ public class RuleEditorController extends BaseController { return ruleEditorBusinessLogic.deleteRule(userId, vfcmtUuid, dcaeCompLabel, nid, configParam, ruleUid, requestId); } + + /** + * This endpoint functions as a 'delete' service for the rule editor UI + * + * @param vfcmtUuid - VFCMT that the rule editor ui is saved in + * @param dcaeCompLabel - the name of the DCAE Component which the group is applied to + * @param nid - A unique id of the DCAE Component which the group is applied to - exists also in the cdump + * @param configParam - the name of the DCAE Component configuration property the rules are linked to + * @param groupId - the unique id of the group to delete + * @return operation result + */ + @RequestMapping(value = "/group/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam}/{groupId}", method = {RequestMethod.DELETE}, produces = "application/json") + public ResponseEntity deleteGroup( + @RequestHeader("USER_ID") String userId, + @PathVariable("vfcmtUuid") String vfcmtUuid, + @PathVariable("dcaeCompLabel") String dcaeCompLabel, + @PathVariable("nid") String nid, + @PathVariable("configParam") String configParam, + @PathVariable("groupId") String groupId, + @ModelAttribute("requestId") String requestId) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting deleteRule", vfcmtUuid); + return ruleEditorBusinessLogic.deleteGroupOfRules(userId, vfcmtUuid, dcaeCompLabel, nid, configParam, groupId, requestId); + } + /** * This endpoint functions as a 'translate' service for the rule editor UI * - * @param vfcmtUuid - VFCMT that the rule editor ui is saved in - * @param dcaeCompLabel - the name of the DCAE Component which the rule is applied to - * @param nid - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump - * @param configParam - the name of the DCAE Component configuration property the rule is linked to - * @param flowType - the mapping rules flow type (SNMP,Syslog,FOI) + * @param body (vfcmtUuid) - VFCMT that the rule editor ui is saved in + * @param body (dcaeCompLabel) - the name of the DCAE Component which the rule is applied to + * @param body (nid) - A unique id of the DCAE Component which the rule is applied to - exists also in the cdump + * @param body (configParam) - the name of the DCAE Component configuration property the rule is linked to + * @param body (entryPhase) - the global entry phase name + * @param body (publishPhase) - the global publish phase name * @return translateJson representing the translated Rules * Validations: * 1. That the user is able to edit the VFCMT * 2. That the cdump holds a dcae component with such nid (to avoid orphan rules) * 3. Check that the fetched VFCMT is actually a VFCMT and not a regular VF */ - @RequestMapping(value = "/rule/translate/{vfcmtUuid}/{dcaeCompLabel}/{nid}/{configParam:.*}", method = {RequestMethod.GET}, produces = "application/json") - public ResponseEntity translateRules(@PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId, - @PathVariable("dcaeCompLabel") String dcaeCompLabel, - @PathVariable("nid") String nid, - @PathVariable("configParam") String configParam, - @RequestParam("flowType") String flowType) { - - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting translateRules", vfcmtUuid); - return ruleEditorBusinessLogic.translateRules(vfcmtUuid, requestId, dcaeCompLabel, nid, configParam, flowType); - } + + @RequestMapping(value = "/rule/translate", method = {RequestMethod.POST}, produces = "application/json") + public ResponseEntity translateRules(@RequestBody String body, @ModelAttribute("requestId") String requestId) + { + TranslateRequest request = gson.fromJson(body, TranslateRequest.class); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting translateRules"); + return ruleEditorBusinessLogic.translateRules(request, requestId); + } @RequestMapping(value = "/getExistingRuleTargets/{vfcmtUuid}/{dcaeCompLabel}/{nid:.*}", method = {RequestMethod.GET}, produces = "application/json") diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java index 4fbce49..725bd85 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/VfcmtController.java @@ -178,4 +178,9 @@ public class VfcmtController extends BaseController{ } } + @RequestMapping(value = { "/{contextType}/{serviceUuid}/{vfiName}/{vfcmtUuid}/getLatestMcUuid" }, method = { RequestMethod.GET }, produces = {"application/json" }) + public ResponseEntity getLatestMcUuid(@RequestHeader("USER_ID") String userId, @PathVariable String contextType, @PathVariable String serviceUuid, @PathVariable String vfiName, @PathVariable String vfcmtUuid, @ModelAttribute String requestId) { + return referenceBusinessLogic.checkoutAndBindToServiceIfCertified(userId, contextType, serviceUuid, vfiName, vfcmtUuid, requestId); + } + } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java index 6779257..6b0ec93 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BaseBusinessLogic.java @@ -25,7 +25,13 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.Base64Utils; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; @Component public class BaseBusinessLogic { @@ -130,7 +136,7 @@ public class BaseBusinessLogic { } - public void checkUserIfResourceCheckedOut(String userId, Asset asset) { + void checkUserIfResourceCheckedOut(String userId, Asset asset) { if (DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT == DcaeBeConstants.LifecycleStateEnum.findState(asset.getLifecycleState())) { String lastUpdaterUserId = asset.getLastUpdaterUserId(); if (lastUpdaterUserId != null && !lastUpdaterUserId.equals(userId)) { @@ -141,11 +147,11 @@ public class BaseBusinessLogic { } } - public boolean isNeedToCheckOut(String lifecycleState) { + boolean isNeedToCheckOut(String lifecycleState) { return DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT != DcaeBeConstants.LifecycleStateEnum.findState(lifecycleState); } - public void checkVfcmtType(ResourceDetailed vfcmt) { + void checkVfcmtType(ResourceDetailed vfcmt) { if (AssetType.VFCMT != getValidAssetTypeOrNull(vfcmt.getResourceType()) || !"Template".equals(vfcmt.getCategory())) { ResponseFormat responseFormat = ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.RESOURCE_NOT_VFCMT_ERROR, null, vfcmt.getUuid()); throw new DcaeException(HttpStatus.BAD_REQUEST, responseFormat.getRequestError()); @@ -161,4 +167,15 @@ public class BaseBusinessLogic { } } + + byte[] extractFile(ZipInputStream zis) throws IOException { + byte[] buffer = new byte[1024]; + try (ByteArrayOutputStream os = new ByteArrayOutputStream()){ + int len; + while ((len = zis.read(buffer)) > 0) { + os.write(buffer, 0, len); + } + return os.toByteArray(); + } + } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java index 7a6f9a7..fba8245 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java @@ -1,42 +1,42 @@ package org.onap.sdc.dcae.composition.impl; +import com.google.gson.Gson; import org.apache.commons.lang.StringUtils; import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.dcae.catalog.asdc.ASDC; -import org.onap.sdc.dcae.catalog.asdc.ASDCUtils; -import org.onap.sdc.dcae.catalog.asdc.Blueprinter; +import org.onap.sdc.dcae.catalog.commons.Recycler; import org.onap.sdc.dcae.composition.restmodels.MessageResponse; import org.onap.sdc.dcae.composition.restmodels.VfcmtData; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; -import org.onap.sdc.dcae.composition.util.DcaeBeConstants; import org.onap.sdc.dcae.errormng.ActionStatus; import org.onap.sdc.dcae.errormng.ErrConfMgr; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; +import org.springframework.web.client.RestTemplate; +import org.yaml.snakeyaml.Yaml; -import javax.annotation.PostConstruct; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.StringReader; -import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; @Component +@ConfigurationProperties(prefix="blueprinter") public class BlueprintBusinessLogic extends CompositionBusinessLogic { - @Autowired - private Blueprinter blueprinter; - @Autowired - private ASDC asdc; - - - @PostConstruct - public void init() { - URI sdcUri = URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.URI)); - asdc.setUri(sdcUri); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "SDC uri: {}", sdcUri); - } + private String uri; + public void setUri(String uri) { + this.uri = uri; + } public ResponseEntity generateAndSaveBlueprint(String userId, String context, String vfcmtUuid, String serviceUuid, String vfiName, String flowType, String requestId) { try { @@ -50,7 +50,13 @@ public class BlueprintBusinessLogic extends CompositionBusinessLogic { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found the cdump (composition.yml) on top of VFCMT {}", vfcmtUuid); String cdump = cdumpArtifactData.getPayloadData(); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to use python procedure to create a blueprint...."); - String resultBlueprintCreation = generateBlueprintViaToscaLab(cdump); + + String input = prepareInput(cdump, requestId); + if (null == input) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SUBMIT_BLUEPRINT_ERROR); + } + String resultBlueprintCreation = new RestTemplate().postForObject(uri, new HttpEntity<>(input), String.class); + if (StringUtils.isEmpty(resultBlueprintCreation)) { errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred during blueprint generation"); return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERATE_BLUEPRINT_ERROR, "", vfcmt.getName()); @@ -80,17 +86,65 @@ public class BlueprintBusinessLogic extends CompositionBusinessLogic { } } - private String generateBlueprintViaToscaLab(String cdump) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------CDUMP: -----------------------------------------------------------------------------"); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), cdump); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------------------------------------------------------------------------------------------"); - ASDCUtils utils = new ASDCUtils(asdc, blueprinter); - String resultBlueprintCreation = null; - try{ - resultBlueprintCreation = utils.buildBlueprintViaToscaLab(new StringReader(cdump)).waitForResult().waitForResult(); - }catch (Exception e){ - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Generate blueprint via tosca lab error: {}", e); - } - return resultBlueprintCreation; - } + private String prepareInput(String cdump, String requestId) throws IOException { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "fetched cdump payload: {}", cdump); + Map cdumpToTosca = new Recycler().recycle(new StringReader(cdump)); + Set<String> dcaeComponentsUuids = extractComponentUuids(cdumpToTosca); + List<Map> extractedModels = Collections.synchronizedSet(dcaeComponentsUuids).parallelStream().map(id -> fetchAndExtractModel(id, requestId)).filter(Objects::nonNull).collect(Collectors.toList()); + // aggregation of parallel stream fetch results - exceptions are swallowed and we check the final size to verify no errors occurred + if(dcaeComponentsUuids.size() != extractedModels.size()) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "error: {} distinct DCAE components were mapped to {} tosca lab input models.", dcaeComponentsUuids.size(), extractedModels.size()); + return null; + } + return new Gson().toJson(new ToscaLabInput(Base64Utils.encodeToString(new Yaml().dump(cdumpToTosca).getBytes()), extractedModels)); + } + + private Set<String> extractComponentUuids(Map cdump) { + //the node description contains the UUID of the resource declaring it + //if the description is the URI the resource uuid is the 5th path element (backward compatibility) + // TODO there has to be a better way + Map<String, Map<String, Object>> nodes = (Map<String, Map<String, Object>>)((Map<String, Object>)cdump.get("topology_template")).get("node_templates"); + return nodes.values().stream() + .map(n -> (String)n.get("description")) + .filter(StringUtils::isNotBlank) + .map(d -> StringUtils.substringBetween(d, "resources/", "/")) + .collect(Collectors.toSet()); + } + + + private class ToscaLabInput { + private String template; + private List<Map> models; + + ToscaLabInput(String template, List<Map> models){ + this.template = template; + this.models = models; + } + } + + private Map<String, String> fetchAndExtractModel(String uuid, String requestId) { + try { + return extractModelFromCsar(sdcRestClient.getResourceToscaModel(uuid, requestId)); + } catch (Exception e) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "model extraction error: {}", e); + return null; + } + } + + private Map<String, String> extractModelFromCsar(byte[] csar) throws IOException { + //we are only interested in unzipping the 3 files under Artifacts/Deployment/DCAE_TOSCA/ + String dcaeToscaDir = "Artifacts/Deployment/DCAE_TOSCA/"; + Map<String, String> extracted = new HashMap<>(); + try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(csar))) { + ZipEntry ze = zis.getNextEntry(); + while (ze != null && 3 != extracted.size()) { + if(ze.getName().startsWith(dcaeToscaDir)) { + extracted.put(ze.getName().replace(dcaeToscaDir,"").split("\\.")[0], Base64Utils.encodeToString(extractFile(zis))); + } + ze = zis.getNextEntry(); + } + return extracted; + } + } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogic.java index ff596b5..d970778 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogic.java @@ -1,205 +1,119 @@ package org.onap.sdc.dcae.composition.impl; -import org.json.JSONArray; -import org.json.JSONException; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.common.onaplog.OnapLoggerError; import org.onap.sdc.dcae.catalog.Catalog; -import org.onap.sdc.dcae.catalog.engine.*; +import org.onap.sdc.dcae.catalog.commons.Future; +import org.onap.sdc.dcae.catalog.engine.CatalogController; +import org.onap.sdc.dcae.catalog.engine.CatalogResponse; +import org.onap.sdc.dcae.catalog.engine.ElementRequest; +import org.onap.sdc.dcae.composition.restmodels.canvas.DcaeComponentCatalog; +import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; +import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; +import org.onap.sdc.dcae.composition.util.DcaeBeConstants; +import org.onap.sdc.dcae.enums.AssetType; +import org.onap.sdc.dcae.errormng.ActionStatus; +import org.onap.sdc.dcae.errormng.ErrConfMgr; +import org.onap.sdc.dcae.utils.SdcRestClientUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.web.context.request.async.DeferredResult; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; @Component -public class CompositionCatalogBusinessLogic { +public class CompositionCatalogBusinessLogic extends BaseBusinessLogic { @Autowired private CatalogController catalogController; protected OnapLoggerError errLogger = OnapLoggerError.getInstance(); - public DeferredResult<CatalogResponse> getItems(ItemsRequest theRequest) { - - final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest; - - Catalog catalog = catalogController.getCatalog(request.getCatalog()); - DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout()); + public ResponseEntity getModelById(String requestId, String theItemId) { - catalog.rootsByLabel(request.getStartingLabel()).setHandler(catalogController.new CatalogHandler<Catalog.Folders>(request, result) { - public CatalogResponse handleData(Catalog.Folders theFolders) { - JSONArray ja = new JSONArray(); - if (theFolders != null) { - for (Catalog.Folder folder : theFolders) { - ja.put(catalogController.patchData(catalog, folder.data())); - } - } - CatalogResponse response = new CatalogResponse(this.request); - try { - response.data().put("elements", ja); - } catch (JSONException e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting json elements to response {}", e); - } - return response; + try { + ResourceDetailed resourceDetailed = fetchAndExtractTemplateAndSchema(theItemId, requestId); + Future<Catalog.Template> modelFuture = catalogController.getCatalog().template(resourceDetailed).withInputs().withOutputs().withNodes().withNodeProperties().withNodePropertiesAssignments().withNodeRequirements().withNodeCapabilities().withNodeCapabilityProperties() + .withNodeCapabilityPropertyAssignments().withPolicies().withPolicyProperties().withPolicyPropertiesAssignments().execute(); + if(modelFuture.succeeded()) { + CatalogResponse response = new CatalogResponse(ElementRequest.EMPTY_REQUEST); + response.data().put("model", modelFuture.result().data()); + return ResponseEntity.ok().body(response); } - }); - return result; - } + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR, modelFuture.cause().getMessage()); - public DeferredResult<CatalogResponse> getItemById(ItemsRequest theRequest, String theItemId) { - - final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest; - - Catalog catalog = catalogController.getCatalog(request.getCatalog()); - DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout()); - - catalog.folder(theItemId).withParts().withPartAnnotations().withItems().withItemAnnotations().withItemModels().execute().setHandler(new FolderHandler(catalog, request, result)); - return result; + } catch (Exception e) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error fetching catalog model with id {}. Message: {}", theItemId, e); + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.GET_MODEL, theItemId); + } } - public DeferredResult getModelById(ElementRequest theRequest, String theItemId) { - final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest; - - Catalog catalog = catalogController.getCatalog(request.getCatalog()); - DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout()); -// try { - catalog.item(theItemId).withModels().execute().setHandler(new ItemHandler(catalog, request, result)); -// } catch (IllegalArgumentException e) { -// errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error fetching catalog model with id {}. Message: {}", theItemId, e); -// result.setErrorResult(new CatalogError(request, "Catalog API failed", e)); -// } - return result; - } + public ResponseEntity getTypeInfo(String theItemId, String theTypeName) { - public DeferredResult<CatalogResponse> getTypeInfo(ElementRequest theRequest, String theItemId, String theTypeName) { - final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest; - - Catalog catalog = catalogController.getCatalog(request.getCatalog()); - DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout()); - - catalog.type(theItemId, theTypeName).withHierarchy().withCapabilities().withRequirements().execute().setHandler(catalogController.new CatalogHandler<Catalog.Type>(request, result) { - public CatalogResponse handleData(Catalog.Type theType) { - CatalogResponse response = new CatalogResponse(this.request); - if (theType != null) { - try { - response.data().put("type", catalogController.patchData(catalog, theType.data())); - } catch (JSONException e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", e); - } - } - return response; + try { + Future<Catalog.Type> theTypeInfoFuture = catalogController.getCatalog().type(theItemId, theTypeName).withHierarchy().withCapabilities().withRequirements().execute(); + if(theTypeInfoFuture.succeeded()) { + CatalogResponse response = new CatalogResponse(ElementRequest.EMPTY_REQUEST); + response.data().put("type", theTypeInfoFuture.result().data()); + return ResponseEntity.ok().body(response); } - }); - return result; - } - - /// Nested Catalog Data Handlers /// - - private class FolderHandler extends CatalogController.CatalogHandler<Catalog.Folder> { - - private Catalog catalog; + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR, theTypeInfoFuture.cause().getMessage()); - private FolderHandler(Catalog catalog, ItemsRequest request, DeferredResult result) { - catalogController.super(request, result); - this.catalog = catalog; - } - - private void patchCatalogData(Catalog.Elements folders, Catalog catalog) { - if (folders != null) { - folders.forEach(folder -> { - catalogController.patchData(catalog, ((Catalog.Element) folder).data()); - // lots of ephemere proxies created here .. - Catalog.Elements annotations = ((Catalog.Element) folder).elements("annotations", Catalog.Annotations.class); - if (annotations != null) { - annotations.forEach(a -> catalogController.patchData(catalog, ((Catalog.Annotation) a).data())); - } - }); - } - } - - public CatalogResponse handleData(Catalog.Folder theFolder) { - CatalogResponse response = new CatalogResponse(this.request); - if (theFolder == null) { - return response; - } - try { - Catalog.Elements folders = theFolder.elements("parts", Catalog.Folders.class); - patchCatalogData(folders, catalog); - Catalog.Elements items = theFolder.elements("items", Catalog.Items.class); - patchCatalogData(items, catalog); - } catch (Exception x) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", x); - return new CatalogError(this.request, "", x); - } - try { - response.data().put("element", theFolder.data()); - } catch (JSONException e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting element to response {}", e); - } - return response; + } catch (Exception e) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", e); + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.GET_MODEL, theItemId); } } - private class ItemHandler extends CatalogController.CatalogHandler<Catalog.Item> { - - private Catalog catalog; - - private ItemHandler(Catalog catalog, ElementRequest request, DeferredResult result) { - catalogController.super(request, result); - this.catalog = catalog; - } - - public CatalogResponse handleData(Catalog.Item theItem) { - if (theItem == null) { - return new CatalogError(this.request, "No such item"); - } - Catalog.Templates models; - try { - models = (Catalog.Templates) theItem.elements("models", Catalog.Templates.class); - } catch (Exception x) { - return new CatalogError(this.request, "Failed to decode templates from result", x); - } - if (models == null || models.isEmpty()) { - return new CatalogError(this.request, "Item has no models"); - } - if (models.size() > 1) { - return new CatalogError(this.request, "Item has more than one model !?"); - } - try { - catalog.template(models.get(0).id()).withInputs().withOutputs().withNodes().withNodeProperties().withNodePropertiesAssignments().withNodeRequirements().withNodeCapabilities().withNodeCapabilityProperties() - .withNodeCapabilityPropertyAssignments().withPolicies().withPolicyProperties().withPolicyPropertiesAssignments().execute().setHandler(new TemplateHandler(this.catalog, this.request, this.result)); - } catch (Exception e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception caught during Catalog Item Handler: {}", e); - } - return null; - } + public DcaeComponentCatalog getCatalog(String requestId) { + List<DcaeComponentCatalog.SubCategoryFolder> folders = sdcRestClient.getResources(AssetType.VF.name(), "DCAE Component", null, requestId).stream() + .filter(r -> DcaeBeConstants.LifecycleStateEnum.CERTIFIED == DcaeBeConstants.LifecycleStateEnum.findState(r.getLifecycleState())) + .collect(Collectors.groupingBy(Resource::getSubCategory)).entrySet().stream() + .map(e -> new DcaeComponentCatalog.SubCategoryFolder(e.getKey(), e.getValue())).collect(Collectors.toList()); + DcaeComponentCatalog catalog = new DcaeComponentCatalog(); + catalog.setElements(folders); + return catalog; } - private class TemplateHandler extends CatalogController.CatalogHandler<Catalog.Template> { - - private Catalog catalog; - private TemplateHandler(Catalog catalog, CatalogRequest request, DeferredResult result) { - catalogController.super(request, result); - this.catalog = catalog; + private ResourceDetailed fetchAndExtractTemplateAndSchema(String uuid, String requestId) throws IOException { + String toscaModelPath = "/sdc/v1/catalog/resources/".concat(uuid).concat("/toscaModel/"); + if(!catalogController.getCatalog().hasCachedItem(uuid)){ + ResourceDetailed resourceDetailed = new ResourceDetailed(); + resourceDetailed.setUuid(uuid); + resourceDetailed.setToscaModelURL(toscaModelPath); + resourceDetailed.setArtifacts(extractToscaArtifactsFromCsar(sdcRestClient.getResourceToscaModel(uuid, requestId), toscaModelPath)); + return resourceDetailed; } + ResourceDetailed cachedVf = sdcRestClient.getResource(uuid, requestId); + cachedVf.getArtifacts().forEach(a -> a.setArtifactURL(toscaModelPath.concat(a.getArtifactName()))); + return cachedVf; + } - public CatalogResponse handleData(Catalog.Template theTemplate) { - CatalogResponse response = new CatalogResponse(this.request); - if (theTemplate != null) { - try { - response.data().put("model", catalogController.patchData(catalog, theTemplate.data())); - } catch (JSONException e) { - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting model to response {}", e); + private List<Artifact> extractToscaArtifactsFromCsar(byte[] csar, String toscaModelPath) throws IOException { + //we are only interested in unzipping files under Artifacts/Deployment/DCAE_TOSCA/ + String dcaeToscaDir = "Artifacts/Deployment/DCAE_TOSCA/"; + List<Artifact> extracted = new ArrayList<>(); + try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(csar))) { + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + if(ze.getName().startsWith(dcaeToscaDir)) { + String artifactName = ze.getName().replace(dcaeToscaDir,""); + extracted.add(SdcRestClientUtils.generateCatalogDcaeToscaArtifact(artifactName, toscaModelPath.concat(artifactName), extractFile(zis))); } + ze = zis.getNextEntry(); } - return response; + return extracted; } } -} - - - - +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java index 9c950b6..224fc24 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/ReferenceBusinessLogic.java @@ -2,9 +2,13 @@ package org.onap.sdc.dcae.composition.impl; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.restmodels.MonitoringComponent; +import org.onap.sdc.dcae.composition.restmodels.ReferenceUUID; +import org.onap.sdc.dcae.composition.restmodels.VfcmtData; import org.onap.sdc.dcae.composition.restmodels.sdc.ExternalReferencesMap; +import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceInstance; import org.onap.sdc.dcae.composition.restmodels.sdc.ServiceDetailed; +import org.onap.sdc.dcae.composition.util.DcaeBeConstants; import org.onap.sdc.dcae.errormng.ActionStatus; import org.onap.sdc.dcae.errormng.ErrConfMgr; import org.onap.sdc.dcae.utils.Normalizers; @@ -74,4 +78,26 @@ public class ReferenceBusinessLogic extends BaseBusinessLogic { return result; } + + // defect fix/workaround - rule editor may perform lazy checkout on a certified MC without binding it to the service. This is a preemptive measure + public ResponseEntity checkoutAndBindToServiceIfCertified(String userId, String contextType, String serviceUuid, String vfiName, String vfcmtUuid, String requestId) { + try { + ResourceDetailed vfcmt = sdcRestClient.getResource(vfcmtUuid, requestId); + DcaeBeConstants.LifecycleStateEnum initialState = DcaeBeConstants.LifecycleStateEnum.findState(vfcmt.getLifecycleState()); + if(DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT != initialState) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "about to checkout vfcmt {} {} version {}", vfcmtUuid, vfcmt.getLifecycleState(), vfcmt.getVersion()); + vfcmt = checkoutVfcmt(userId, vfcmtUuid, requestId); + } + //this is the only case in which the uuid will change. This UI call is followed by a save/import/delete rule request. + if(DcaeBeConstants.LifecycleStateEnum.CERTIFIED == initialState) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "about to create reference for new vfcmt {} version {}", vfcmt.getUuid(), vfcmt.getVersion()); + sdcRestClient.addExternalMonitoringReference(userId, contextType, serviceUuid, vfiName, new ReferenceUUID(vfcmt.getUuid()), requestId); + } + return new ResponseEntity<>(new VfcmtData(vfcmt), HttpStatus.OK); + } catch (Exception e) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(),"Failed to during getLatestMcUuid request for vfcmt {}. message: {}", vfcmtUuid, e); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED, e.getMessage()); + } + } + } 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 298ffac..94133e4 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 @@ -3,10 +3,8 @@ package org.onap.sdc.dcae.composition.impl; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.gson.JsonParseException; import org.apache.commons.collections.ListUtils; -import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.dcae.composition.CompositionConfig; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; @@ -17,6 +15,7 @@ import org.onap.sdc.dcae.errormng.ErrConfMgr; 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.utils.Normalizers; import org.onap.sdc.dcae.utils.SdcRestClientUtils; import org.onap.sdc.dcae.ves.VesDataItemsDefinition; @@ -24,7 +23,9 @@ import org.onap.sdc.dcae.ves.VesDataTypeDefinition; import org.onap.sdc.dcae.ves.VesSimpleTypesEnum; import org.onap.sdc.dcae.ves.VesStructureLoader; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.Base64Utils; @@ -39,8 +40,6 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { @Autowired private RulesBusinessLogic rulesBusinessLogic; - @Autowired - private CompositionConfig compositionConfig; private static final String EXCEPTION = "Exception {}"; @@ -49,7 +48,7 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { try { Rule rule = RulesPayloadUtils.parsePayloadToRule(json); if (null == rule) { - return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", ""); } List<ServiceException> errors = rulesBusinessLogic.validateRule(rule); @@ -71,19 +70,18 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { .filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))) .findAny().orElse(null); - // exception thrown if vfcmt is checked out and current user is not its owner - // performs checkoutVfcmt if required - String vfcmtId = assertOwnershipOfVfcmtId(userId, vfcmt, requestId); // new mappingRules artifact, validate nid exists in composition before creating new artifact if (null == artifactFound) { if (cdumpContainsNid(vfcmt, nid, requestId)) { - return saveNewRulesArtifact(rule, vfcmtId, generateMappingRulesFileName(dcaeCompLabel, nid, configParam), artifactLabel, userId, requestId); + MappingRules body = new MappingRules(rule); + saveNewRulesArtifact(body, vfcmtUuid, generateMappingRulesFileName(dcaeCompLabel, nid, configParam), artifactLabel, userId, requestId); + return checkInAndReturnSaveArtifactResult(rule.toJson(), vfcmtUuid, userId, requestId); } return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.NODE_NOT_FOUND, "", dcaeCompLabel); } //update artifact flow - append new rule or edit existing rule - return addOrEditRuleInArtifact(rule, vfcmtId, userId, artifactFound, requestId); + return addOrEditRuleInArtifact(rule, vfcmtUuid, userId, artifactFound, requestId); } catch (JsonParseException je) { errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error: Rule format is invalid: {}", je); @@ -91,35 +89,59 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } catch (Exception e) { return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); } - } - public ResponseEntity getRules(String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String requestId) { + public ResponseEntity getRulesAndSchema(String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String requestId) { try { - ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); - if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { - return new ResponseEntity<>("{}", HttpStatus.OK); - } - String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam); - - // check for MappingRules artifact in existing artifacts - Artifact artifactListed = vfcmt.getArtifacts().stream().filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))).findAny().orElse(null); - if (null == artifactListed) { - return new ResponseEntity<>("{}", HttpStatus.OK); - } - String ruleFile = getSdcRestClient().getResourceArtifact(vfcmtUuid, artifactListed.getArtifactUUID(), requestId); - + ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); + Artifact rulesArtifact = fetchRulesArtifact(vfcmt, dcaeCompLabel, nid, configParam, requestId); + if(null == rulesArtifact) { + return new ResponseEntity<>("{}", HttpStatus.OK); + } // To avoid opening the file for reading we search for the eventType and SchemaVer from the artifact metadata's description - SchemaInfo schemainfo = RulesPayloadUtils.extractInfoFromDescription(artifactListed); + SchemaInfo schemainfo = RulesPayloadUtils.extractInfoFromDescription(rulesArtifact); List<EventTypeDefinitionUI> schema = null == schemainfo ? new ArrayList<>() : getEventTypeDefinitionUIs(schemainfo.getVersion(), schemainfo.getEventType()); - return new ResponseEntity<>(RulesPayloadUtils.buildSchemaAndRulesResponse(ruleFile, schema), HttpStatus.OK); + return new ResponseEntity<>(RulesPayloadUtils.buildSchemaAndRulesResponse(rulesArtifact.getPayloadData(), schema), HttpStatus.OK); } catch (Exception e) { return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.GET_RULE_ARTIFACT); } - } + //1810 US423581 export rules + public ResponseEntity downloadRules(String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String requestId) { + + try { + ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); + Artifact rulesArtifact = fetchRulesArtifact(vfcmt, dcaeCompLabel, nid, configParam, requestId); + if(null == rulesArtifact) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"requested rules artifact not found"); + return new ResponseEntity(HttpStatus.NOT_FOUND); + } + return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM) + .header(HttpHeaders.CONTENT_DISPOSITION, generateMappingRulesFileNameHeader(vfcmt.getName(), dcaeCompLabel, configParam)) + .body(rulesArtifact.getPayloadData()); + } catch (Exception e) { + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.GET_RULE_ARTIFACT); + } + } + + private Artifact fetchRulesArtifact(ResourceDetailed vfcmt, String dcaeCompLabel, String nid, String configParam, String requestId) { + + if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { + return null; + } + String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam); + + // check for MappingRules artifact in existing artifacts + Artifact artifactListed = vfcmt.getArtifacts().stream().filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))).findAny().orElse(null); + if (null == artifactListed) { + return null; + } + artifactListed.setPayloadData(getSdcRestClient().getResourceArtifact(vfcmt.getUuid(), artifactListed.getArtifactUUID(), requestId)); + return artifactListed; + } + public ResponseEntity deleteRule(String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String ruleUid, String requestId) { try { @@ -140,8 +162,7 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED); } - String vfcmtId = assertOwnershipOfVfcmtId(userId, vfcmt, requestId); - String payload = getSdcRestClient().getResourceArtifact(vfcmtId, mappingRuleFile.getArtifactUUID(), requestId); + String payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, mappingRuleFile.getArtifactUUID(), requestId); MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); Rule removedRule = rulesBusinessLogic.deleteRule(rules, ruleUid); if (null == removedRule) { @@ -149,55 +170,89 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED); } if (rules.isEmpty()) { // if file doesn't contain any rules after last deletion -> let's delete the file - getSdcRestClient().deleteResourceArtifact(userId, vfcmtId, mappingRuleFile.getArtifactUUID(), requestId); + getSdcRestClient().deleteResourceArtifact(userId, vfcmtUuid, mappingRuleFile.getArtifactUUID(), requestId); } else { - updateRulesArtifact(vfcmtId, userId, mappingRuleFile, rules, requestId); + updateRulesArtifact(vfcmtUuid, userId, mappingRuleFile, rules, requestId); } - return checkInAndReturnSaveArtifactResult(removedRule, vfcmtId, userId, requestId); + return checkInAndReturnSaveArtifactResult(removedRule.toJson(), vfcmtUuid, userId, requestId); } catch (Exception e) { return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); } - } - public ResponseEntity translateRules(String vfcmtUuid, String requestId, String dcaeCompLabel, String nid, String configParam, String flowType) { + public ResponseEntity deleteGroupOfRules(String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam, String groupId, String requestId) { + + try { + ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); + if (null == vfcmt.getArtifacts()) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "VFCMT {} doesn't have artifacts", vfcmtUuid); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED); + } + String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam); + + // 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, vfcmtUuid); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED); + } + + String payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, mappingRuleFile.getArtifactUUID(), requestId); + MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); + List<Rule> removedRules = rulesBusinessLogic.deleteGroupOfRules(rules, groupId); + if (removedRules.isEmpty()) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Group {} not found.", groupId); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.DELETE_RULE_FAILED); + } + if (rules.isEmpty()) { // if file doesn't contain any rules after last deletion -> let's delete the file + getSdcRestClient().deleteResourceArtifact(userId, vfcmtUuid, mappingRuleFile.getArtifactUUID(), requestId); + } else { + updateRulesArtifact(vfcmtUuid, userId, mappingRuleFile, rules, requestId); + } + return checkInAndReturnSaveArtifactResult(removedRules, vfcmtUuid, userId, requestId); + } catch (Exception e) { + return ErrConfMgr.INSTANCE.handleException(e, ErrConfMgr.ApiType.SAVE_RULE_ARTIFACT); + } + + } + + public ResponseEntity translateRules(TranslateRequest request, String requestId) { try { - - if (StringUtils.isBlank(flowType) || MapUtils.isEmpty(compositionConfig.getFlowTypesMap()) || null == compositionConfig.getFlowTypesMap().get(flowType)) { - return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "Flow type " + flowType + " not found"); + if(!rulesBusinessLogic.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"); } - - // extract entry phase name and last phase name from configuration: - String entryPointPhaseName = compositionConfig.getFlowTypesMap().get(flowType).getEntryPointPhaseName(); - String lastPhaseName = compositionConfig.getFlowTypesMap().get(flowType).getLastPhaseName(); - - ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); + ResourceDetailed vfcmt = getSdcRestClient().getResource(request.getVfcmtUuid(), requestId); checkVfcmtType(vfcmt); if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { - return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "No rules found on VFCMT " + vfcmtUuid); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", "No rules found on VFCMT " + request.getVfcmtUuid()); } - String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam); + String artifactLabel = Normalizers.normalizeArtifactLabel(request.getDcaeCompLabel() + request.getNid() + request.getConfigParam()); // check for MappingRules artifact in existing artifacts Artifact rulesArtifact = vfcmt.getArtifacts().stream().filter(a -> artifactLabel.equals(Normalizers.normalizeArtifactLabel(a.getArtifactLabel()))).findAny().orElse(null); if (rulesArtifact == null) { - return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", artifactLabel + " doesn't exist on VFCMT " + vfcmtUuid); + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.TRANSLATE_FAILED, "", artifactLabel + " doesn't exist on VFCMT " + request.getVfcmtUuid()); } - String payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, rulesArtifact.getArtifactUUID(), requestId); + String payload = getSdcRestClient().getResourceArtifact(request.getVfcmtUuid(), rulesArtifact.getArtifactUUID(), requestId); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Retrieved mapping rules artifact {}, start parsing rules...", artifactLabel); MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); + rulesBusinessLogic.updateGlobalTranslationFields(rules, request, vfcmt.getName()); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Finished parsing rules, calling validator..."); - List<ServiceException> errors = rulesBusinessLogic.validateRules(rules); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(rules); if (!errors.isEmpty()) { return ErrConfMgr.INSTANCE.buildErrorArrayResponse(errors); } debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Validation completed successfully, calling translator..."); - String translateJson = rulesBusinessLogic.translateRules(rules, entryPointPhaseName, lastPhaseName, vfcmt.getName()); + String translateJson = rulesBusinessLogic.translateRules(rules); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Translation completed successfully"); return new ResponseEntity<>(translateJson, HttpStatus.OK); } catch (Exception e) { @@ -205,6 +260,50 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { } } + public ResponseEntity importRules(String json, String requestId, String userId, String vfcmtUuid, String dcaeCompLabel, String nid, String configParam) { + try { + MappingRulesResponse mappingRules = RulesPayloadUtils.parsePayloadToMappingRules(json); + List<ServiceException> 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 + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, errors.stream().map(ServiceException::getFormattedErrorMessage).collect(Collectors.joining(", ")), errors.get(0).getFormattedErrorMessage()); + } + + ResourceDetailed vfcmt = getSdcRestClient().getResource(vfcmtUuid, requestId); + checkVfcmtType(vfcmt); + + if (CollectionUtils.isEmpty(vfcmt.getArtifacts())) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED); + } + + String artifactLabel = Normalizers.normalizeArtifactLabel(dcaeCompLabel + nid + configParam); + + // 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, nid, requestId)) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.NODE_NOT_FOUND, "", dcaeCompLabel); + } + saveNewRulesArtifact(mappingRules, vfcmtUuid, generateMappingRulesFileName(dcaeCompLabel, nid, configParam), artifactLabel, userId, requestId); + } else { + updateRulesArtifact(vfcmtUuid, userId, artifactFound, mappingRules, requestId); + } + mappingRules.setSchema(getEventTypeDefinitionUIs(mappingRules.getVersion(), mappingRules.getEventType())); + return checkInAndReturnSaveArtifactResult(mappingRules, vfcmtUuid, 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); + } + + } + public ResponseEntity getExistingRuleTargets(String vfcmtUuid, String requestId, String dcaeCompLabel, String nid) { try { @@ -260,19 +359,6 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { ///////////////////PRIVATE METHODS//////////////////////////////////////////////////////////////////////// - private String assertOwnershipOfVfcmtId(String userId, ResourceDetailed vfcmt, String requestId) { - checkUserIfResourceCheckedOut(userId, vfcmt); - String newVfcmtId = vfcmt.getUuid(); // may change after checking out a certified vfcmt - if (isNeedToCheckOut(vfcmt.getLifecycleState())) { - ResourceDetailed result = checkoutVfcmt(userId, newVfcmtId, requestId); - if (result != null) { - newVfcmtId = result.getUuid(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New resource after checkoutVfcmt is: {}", newVfcmtId); - } - } - return newVfcmtId; - } - // called after validating vfcmt.getArtifacts() is not null private boolean cdumpContainsNid(ResourceDetailed vfcmt, String nid, String requestId) { Artifact cdump = vfcmt.getArtifacts().stream() @@ -295,40 +381,44 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return true; } - private ResponseEntity<String> saveNewRulesArtifact(Rule rule, String vfcmtUuid, String artifactFileName, String artifactLabel, String userId, String requestId) throws JsonProcessingException { - MappingRules body = new MappingRules(rule); - Artifact artifact = SdcRestClientUtils.generateDeploymentArtifact(body.describe(), artifactFileName, ArtifactType.OTHER.name(), artifactLabel, body.convertToPayload()); - getSdcRestClient().createResourceArtifact(userId, vfcmtUuid, artifact, requestId); - return checkInAndReturnSaveArtifactResult(rule, vfcmtUuid, userId, requestId); - } + + private void saveNewRulesArtifact(MappingRules mappingRules, String vfcmtUuid, String artifactFileName, String artifactLabel, String userId, String requestId) throws JsonProcessingException { + Artifact artifact = SdcRestClientUtils.generateDeploymentArtifact(mappingRules.describe(), artifactFileName, ArtifactType.OTHER.name(), artifactLabel, mappingRules.convertToPayload()); + getSdcRestClient().createResourceArtifact(userId, vfcmtUuid, artifact, requestId); + } private ResponseEntity addOrEditRuleInArtifact(Rule rule, String vfcmtUuid, String userId, Artifact rulesArtifact, String requestId) throws JsonProcessingException { String payload = getSdcRestClient().getResourceArtifact(vfcmtUuid, rulesArtifact.getArtifactUUID(), requestId); MappingRules rules = RulesPayloadUtils.parseMappingRulesArtifactPayload(payload); - // in case the rule id is passed but the rule doesn't exist on the mapping rule file: - if (!rulesBusinessLogic.addOrEditRule(rules, rule)) { + // 1810 US427299 support user defined phase names + boolean supportGroups = ValidationUtils.validateNotEmpty(rule.getGroupId()); + if(!rulesBusinessLogic.validateGroupDefinitions(rules, supportGroups)) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.INVALID_RULE_FORMAT, "", "invalid group definitions"); + } + // in case the rule id is passed but the rule doesn't exist on the mapping rule file or if there's a mismatch in group definitions: + if (!rulesBusinessLogic.addOrEditRule(rules, rule, supportGroups)) { return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SAVE_RULE_FAILED); } updateRulesArtifact(vfcmtUuid, userId, rulesArtifact, rules, requestId); - return checkInAndReturnSaveArtifactResult(rule, vfcmtUuid, userId, requestId); + return checkInAndReturnSaveArtifactResult(rule.toJson(), vfcmtUuid, userId, requestId); } // regardless of check in result, return save artifact success - private ResponseEntity<String> checkInAndReturnSaveArtifactResult(Rule rule, String vfcmtUuid, String userId, String requestId) { + private ResponseEntity checkInAndReturnSaveArtifactResult(Object response, String vfcmtUuid, String userId, String requestId) { try { checkinVfcmt(userId, vfcmtUuid, requestId); } catch (Exception e) { // swallowing the exception intentionally since it is on the check in action errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred while performing check in on VFCMT {}:{}", vfcmtUuid, e); } - return new ResponseEntity<>(rule.toJson(), HttpStatus.OK); + return new ResponseEntity<>(response, HttpStatus.OK); } private void updateRulesArtifact(String vfcmtUuid, String userId, Artifact artifactInfo, MappingRules rules, String requestId) throws JsonProcessingException { artifactInfo.setPayloadData(Base64Utils.encodeToString(rules.convertToPayload())); // POST must contain 'description' while GET returns 'artifactDescription' - artifactInfo.setDescription(artifactInfo.getArtifactDescription()); + artifactInfo.setDescription(rules.describe()); getSdcRestClient().updateResourceArtifact(userId, vfcmtUuid, artifactInfo, requestId); } @@ -378,6 +468,17 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return dcaeCompLabel + "_" + nid + "_" + configParam + DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX; } + private String generateMappingRulesFileNameHeader(String vfcmtName, String dcaeCompLabel, String configParam) { + return "attachment; filename=\"" + .concat(vfcmtName) + .concat("_") + .concat(dcaeCompLabel) + .concat("_") + .concat(configParam) + .concat(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX) + .concat("\""); + } + private List<EventTypeDefinitionUI> getEventTypeDefinitionUIs(String version, String eventType) { List<String> eventNamesToReturn = ListUtils.union(EventTypesByVersionUI.DEFAULT_EVENTS, Arrays.asList(eventType)); Map<String, VesDataTypeDefinition> eventDefs = VesStructureLoader.getEventListenerDefinitionByVersion(version); @@ -385,4 +486,6 @@ public class RuleEditorBusinessLogic extends BaseBusinessLogic { return convertToEventTypeDefinition(filteredEvents, null, "event"); } + + } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java index de1d06b..2aa721f 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ErrConfMgr.java @@ -146,6 +146,7 @@ public enum ErrConfMgr { map.put("SVC4127", "SVC6021"); map.put("SVC4086", AS_IS); map.put("SVC4301", AS_IS); + map.put("SVC4083", AS_IS); sdcDcaeMsgIdMap.put(ApiType.SAVE_CDUMP, map); } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java index ada790f..58d76be 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/errormng/ResponseFormatManager.java @@ -97,7 +97,7 @@ public class ResponseFormatManager { } } - public ResponseFormatManager(){ + private ResponseFormatManager(){ } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java index 2cd03a7..9a9658f 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/OperatorTypeEnum.java @@ -3,26 +3,41 @@ package org.onap.sdc.dcae.rule.editor.enums; import java.util.Arrays; public enum OperatorTypeEnum { - EQUALS("Equals", "OneOf"), - NOT_EQUAL("NotEqual", "NotOneOf"), - CONTAINS("Contains", null), - ENDS_WITH("EndsWith", null), - STARTS_WITH("StartsWith", null); + + EQUALS("Equals"), NOT_EQUAL("NotEqual"), CONTAINS("Contains"), ENDS_WITH("EndsWith"), STARTS_WITH("StartsWith"), ONE_OF("OneOf"), NOT_ONE_OF("NotOneOf"), ASSIGNED("Assigned"), UNASSIGNED("Unassigned"); private String type; - private String modifiedType; - OperatorTypeEnum(String type, String modifiedType) { + OperatorTypeEnum(String type) { this.type = type; - this.modifiedType = modifiedType; } public String getType() { return type; } - public String getModifiedType() { - return modifiedType; + public OperatorTypeEnum getModifiedType() { + switch (this) { + case EQUALS: + case ONE_OF: + return ONE_OF; + case NOT_EQUAL: + case NOT_ONE_OF: + return NOT_ONE_OF; + default: + return null; + } + } + + public String getConditionType() { + switch (this) { + case CONTAINS: + case STARTS_WITH: + case ENDS_WITH: + return "Condition"; // comparing strings + default: + return "FieldCondition"; // comparing any type + } } public static OperatorTypeEnum getTypeByName(String name) { diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java index a5e4a39..231c208 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/enums/RuleEditorElementType.java @@ -1,11 +1,10 @@ package org.onap.sdc.dcae.rule.editor.enums; -import java.util.Arrays; - -import org.onap.sdc.dcae.composition.restmodels.ruleeditor.LogEventAction; import org.onap.sdc.dcae.rule.editor.translators.*; import org.onap.sdc.dcae.rule.editor.validators.*; +import java.util.Arrays; + public enum RuleEditorElementType { COPY("Copy", CopyActionValidator.getInstance(), CopyActionTranslator.getInstance()), CONCAT("Concat", ConcatActionValidator.getInstance(), CopyActionTranslator.getInstance()), @@ -17,13 +16,18 @@ public enum RuleEditorElementType { REPLACE_TEXT("ReplaceText", ReplaceActionValidator.getInstance(), ReplaceActionTranslator.getInstance()), LOG_EVENT("LogEvent", LogEventValidator.getInstance(), LogEventTranslator.getInstance()), LOG_TEXT("LogText", LogTextValidator.getInstance(), LogTextTranslator.getInstance()), + //1810 US420763 additional hp processors support + CLEAR_NSF("ClearNSF", ClearActionValidator.getInstance(), ClearActionTranslator.getInstance()), + HP_METRIC("HpMetric", HpMetricValidator.getInstance(), HpMetricTranslator.getInstance()), + STRING_TRANSFORM("StringTransform", StringTransformValidator.getInstance(), StringTransformTranslator.getInstance()), + TOPO_SEARCH("TopologySearch", TopoSearchValidator.getInstance(), TopoSearchTranslator.getInstance()), CONDITION("Condition", ConditionValidator.getInstance(), ConditionTranslator.getInstance()), FIELD_CONDITION("FieldCondition", ConditionValidator.getInstance(), FieldConditionTranslator.getInstance()), CONDITION_GROUP("ConditionGroup", ConditionGroupValidator.getInstance(), ConditionGroupTranslator.getInstance()), RULE("Rule", RuleValidator.getInstance(), RuleTranslator.getInstance()), - MAPPING_RULES("MappingRules", null, MappingRulesTranslator.getInstance()); + MAPPING_RULES("MappingRules", MappingRulesValidator.getInstance(), MappingRulesTranslator.getInstance()); private String elementType; private IRuleElementValidator validator; 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 5270a18..468a6d5 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 @@ -12,6 +12,8 @@ import org.onap.sdc.dcae.errormng.ResponseFormat; import org.onap.sdc.dcae.errormng.ServiceException; 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; +import org.onap.sdc.dcae.rule.editor.validators.MappingRulesValidator; import org.onap.sdc.dcae.rule.editor.validators.RuleValidator; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -20,12 +22,14 @@ 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 { protected OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); private RuleValidator ruleValidator = RuleValidator.getInstance(); + private MappingRulesValidator mappingRulesValidator = MappingRulesValidator.getInstance(); private MappingRulesTranslator mappingRulesTranslator = MappingRulesTranslator.getInstance(); private static Gson gsonTranslator = new GsonBuilder().registerTypeAdapter(String.class, new EmptyStringTranslationSerializer()).enableComplexMapKeySerialization().create(); @@ -37,30 +41,58 @@ public class RulesBusinessLogic { return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList()); } - public List<ServiceException> validateRules(MappingRules rules) { + public List<ServiceException> validateImportedRules(MappingRules rules) { List<ResponseFormat> errors = new ArrayList<>(); - detectAndResolveRuleDependencies(rules, errors); + if(mappingRulesValidator.validate(rules, errors)){ + rules.getRules().forEach((k,v) -> { + v.setUid(k); + detectAndResolveActionDependencies(v, errors); + }); + } + return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList()); + } + + + public List<ServiceException> validateRulesBeforeTranslate(MappingRules rules) { + List<ResponseFormat> errors = new ArrayList<>(); + if(mappingRulesValidator.validateTranslationPhaseNames(rules, errors)) { + detectAndResolveRuleDependencies(rules, errors); + } return errors.stream().map(r -> r.getRequestError().getServiceException()).collect(Collectors.toList()); } - public String translateRules(MappingRules rules, String entryPointPhase, String lastPhase, String runPhase) { + public String translateRules(MappingRules rules) { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Start translating mapping rules"); - return gsonTranslator.toJson(mappingRulesTranslator.translateToHpJson(rules, entryPointPhase, lastPhase, runPhase)); + return gsonTranslator.toJson(mappingRulesTranslator.translateToHpJson(rules)); } - public boolean addOrEditRule(MappingRules rules, Rule rule) { + public boolean addOrEditRule(MappingRules rules, Rule rule, boolean supportGroups) { // in case the rule id is passed but the rule doesn't exist on the mapping rule file: if(StringUtils.isNotBlank(rule.getUid()) && !rules.ruleExists(rule)) { return false; } + // 1810 US427299 support user defined phase names - propagate update to all group members + if(supportGroups) { + rules.getRules().values().stream().filter(p -> rule.getGroupId().equals(p.getGroupId())).forEach(r -> r.setPhase(rule.getPhase())); + } rules.addOrReplaceRule(rule); return true; } + + public boolean validateGroupDefinitions(MappingRules rules, boolean supportGroups) { + return supportGroups == rules.getRules().values().stream().anyMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId())); + } + public Rule deleteRule(MappingRules rules, String ruleUid) { return rules.removeRule(ruleUid); } + public List<Rule> deleteGroupOfRules(MappingRules rules, String groupId) { + List<Rule> rulesByGroupId = rules.getRules().values().stream().filter(p -> groupId.equals(p.getGroupId())).collect(Collectors.toList()); + return rulesByGroupId.stream().map(rule -> rules.removeRule(rule.getUid())).collect(Collectors.toList()); + } + private <T> List<T> detectDependentItemsByDependencyDefinition(Collection<T> allItems, BiFunction<T, Collection<T>, Boolean> dependencyDefinition) { return allItems.stream().filter(i -> dependencyDefinition.apply(i, allItems)).collect(Collectors.toList()); } @@ -127,6 +159,7 @@ public class RulesBusinessLogic { } } + private String extractDependentActionTargetsFromRules(List<Rule> dependentRules) { List<BaseAction> allActions = dependentRules.stream().map(Rule::getActions).flatMap(List::stream).collect(Collectors.toList()); // option 1: circular dependency between actions @@ -150,4 +183,19 @@ public class RulesBusinessLogic { }, LinkedHashMap::new)); 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()); + mappingRules.setNotifyId(request.getNotifyId()); + if(validateGroupDefinitions(mappingRules, false)) { + // 1806 US349308 assign Vfcmt name as rule phaseName + mappingRules.getRules().forEach((k,v) -> v.setPhase(vfcmtName)); + } + } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ActionTranslator.java index 0ad33ce..c3f5c89 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ActionTranslator.java @@ -3,7 +3,9 @@ package org.onap.sdc.dcae.rule.editor.translators; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; abstract class ActionTranslator<A extends BaseAction> implements IRuleElementTranslator<A> { @@ -12,4 +14,13 @@ abstract class ActionTranslator<A extends BaseAction> implements IRuleElementTra processors.add(translateToHpJson(action)); return true; } + + class CopyActionSetTranslation extends ProcessorTranslation { + protected Map<String, String> updates = new LinkedHashMap<>(); + + CopyActionSetTranslation(String target, String from) { + clazz = "Set"; + updates.put(target, from); + } + } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ClearActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ClearActionTranslator.java index 31a3fdc..8b4368a 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ClearActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ClearActionTranslator.java @@ -1,5 +1,6 @@ package org.onap.sdc.dcae.rule.editor.translators; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.ActionTypeEnum; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.UnaryFieldAction; import java.util.List; @@ -15,7 +16,7 @@ public class ClearActionTranslator extends ActionTranslator<UnaryFieldAction> { private ClearActionTranslator(){} public Object translateToHpJson(UnaryFieldAction action) { - return new ClearActionTranslation(action); + return ActionTypeEnum.CLEAR == ActionTypeEnum.getTypeByName(action.getActionType()) ? new ClearActionTranslation(action) : new ClearNSFActionTranslation(action); } @@ -24,7 +25,17 @@ public class ClearActionTranslator extends ActionTranslator<UnaryFieldAction> { ClearActionTranslation(UnaryFieldAction action) { clazz = "Clear"; - fields = action.getFromValues(); + fields = action.fromValues(); + } + } + + + private class ClearNSFActionTranslation extends ProcessorTranslation { + private List<String> reservedFields; + + ClearNSFActionTranslation(UnaryFieldAction action) { + clazz = "ClearNoneStandardFields"; + reservedFields = action.fromValues(); } } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java index 86f55c9..c735723 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionGroupTranslator.java @@ -1,9 +1,11 @@ package org.onap.sdc.dcae.rule.editor.translators; -import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseCondition; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.ConditionGroup; import org.onap.sdc.dcae.rule.editor.enums.ConditionTypeEnum; import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum; -import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; +import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType; import java.util.List; import java.util.Map; @@ -30,8 +32,12 @@ public class ConditionGroupTranslator implements IRuleElementTranslator<Conditio private IRuleElementTranslator getConditionTranslator(BaseCondition condition){ - return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() : - ValidationUtils.validateNotEmpty(OperatorTypeEnum.getTypeByName(((Condition)condition).getOperator()).getModifiedType()) ? FieldConditionTranslator.getInstance() : ConditionTranslator.getInstance(); + return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() : getSimpleConditionTranslator((Condition) condition); + } + + private IRuleElementTranslator getSimpleConditionTranslator(Condition condition) { + String conditionType = OperatorTypeEnum.getTypeByName(condition.getOperator()).getConditionType(); + return RuleEditorElementType.getElementTypeByName(conditionType).getTranslator(); } private Object getTranslation(BaseCondition condition) { diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java index aa30fc3..81dc010 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ConditionTranslator.java @@ -20,15 +20,20 @@ public class ConditionTranslator implements IRuleElementTranslator<Condition> { private String string; private String value; - private StringFilterTranslation(Condition condition, String value){ - this.clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getType(); - this.string = condition.getLeft(); + private StringFilterTranslation(String clazz, String string, String value){ + this.clazz = clazz; + this.string = string; this.value = value; } + private StringFilterTranslation(Condition condition, String value) { + this(OperatorTypeEnum.getTypeByName(condition.getOperator()).getType(), condition.getLeft(), value); + } + private StringFilterTranslation(Condition condition){ this(condition, condition.getRight().get(0)); } + } public Object translateToHpJson(Condition condition) { @@ -36,5 +41,7 @@ public class ConditionTranslator implements IRuleElementTranslator<Condition> { .map(r -> new StringFilterTranslation(condition, r)).collect(Collectors.toList())); } - + Object notifyOidTranslation(String notifyOid) { + return new StringFilterTranslation(OperatorTypeEnum.STARTS_WITH.getType(),"${notify OID}", notifyOid); + } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java index 4226eba..3e42b60 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/CopyActionTranslator.java @@ -3,9 +3,7 @@ package org.onap.sdc.dcae.rule.editor.translators; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseCopyAction; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; public class CopyActionTranslator extends ActionTranslator<BaseCopyAction> { @@ -15,10 +13,10 @@ public class CopyActionTranslator extends ActionTranslator<BaseCopyAction> { return copyActionTranslator; } - CopyActionTranslator(){} + private CopyActionTranslator(){} public Object translateToHpJson(BaseCopyAction action) { - return new CopyActionSetTranslation(action.getTarget(), action.getFromValue()); + return new CopyActionSetTranslation(action.getTarget(), action.fromValue()); } @Override @@ -28,17 +26,9 @@ public class CopyActionTranslator extends ActionTranslator<BaseCopyAction> { processors.add(translateToHpJson(action)); } else { - ((CopyActionSetTranslation) processors.get(processors.size() - 1)).updates.put(action.getTarget(), action.getFromValue()); + ((CopyActionSetTranslation) processors.get(processors.size() - 1)).updates.put(action.getTarget(), action.fromValue()); } return false; } - class CopyActionSetTranslation extends ProcessorTranslation { - Map<String, String> updates = new LinkedHashMap<>(); - CopyActionSetTranslation(String target, String from) { - clazz = "Set"; - updates.put(target, from); - } - } - } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java index 449dbf0..dbbf6a1 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/DateFormatterTranslator.java @@ -22,12 +22,12 @@ public class DateFormatterTranslator extends ActionTranslator<DateFormatterActio private DateFormatterTranslation(DateFormatterAction action){ clazz = "DateFormatter"; - fromFormat = action.getFromFormat(); - fromTz = action.getFromTz(); + fromFormat = action.fromFormat(); + fromTz = action.fromTz(); toField = action.getTarget(); - toFormat = action.getToFormat(); - toTz = action.getToTz(); - value = action.getFromValue(); + toFormat = action.toFormat(); + toTz = action.toTz(); + value = action.fromValue(); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java index dddbc89..a8afd51 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/FieldConditionTranslator.java @@ -19,25 +19,45 @@ public class FieldConditionTranslator implements IRuleElementTranslator<Conditio private String field; private String value; - private FieldFilterTranslation(Condition condition) { - clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getType(); + private FieldFilterTranslation(Condition condition, OperatorTypeEnum operatorType) { + clazz = operatorType.getType(); field = condition.getLeft(); value = condition.getRight().get(0); } } + private class UnaryFilterTranslation extends ProcessorTranslation { + private String field; + private boolean emptyIsAssigned; + + private UnaryFilterTranslation(Condition condition, OperatorTypeEnum operatorType) { + clazz = operatorType.getType(); + field = condition.getLeft(); + emptyIsAssigned = condition.isEmptyIsAssigned(); + } + } + private class MultiFieldFilterTranslation extends ProcessorTranslation { private String field; private List<String> values; - private MultiFieldFilterTranslation(Condition condition) { + private MultiFieldFilterTranslation(Condition condition, OperatorTypeEnum operatorType) { field = condition.getLeft(); values = condition.getRight(); - clazz = OperatorTypeEnum.getTypeByName(condition.getOperator()).getModifiedType(); + clazz = operatorType.getModifiedType().getType(); } } public Object translateToHpJson(Condition condition) { - return 1 == condition.getRight().size() ? new FieldFilterTranslation(condition) : new MultiFieldFilterTranslation(condition); + OperatorTypeEnum operatorType = OperatorTypeEnum.getTypeByName(condition.getOperator()); + if(OperatorTypeEnum.UNASSIGNED == operatorType || OperatorTypeEnum.ASSIGNED == operatorType) { + return new UnaryFilterTranslation(condition, operatorType); + } + return 1 == condition.getRight().size() && !alwaysUseMultipleRightValues(operatorType)? new FieldFilterTranslation(condition, operatorType) : new MultiFieldFilterTranslation(condition, operatorType); } + + private boolean alwaysUseMultipleRightValues(OperatorTypeEnum operatorType) { + return operatorType.equals(operatorType.getModifiedType()); + } + } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/HpMetricTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/HpMetricTranslator.java new file mode 100644 index 0000000..31df164 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/HpMetricTranslator.java @@ -0,0 +1,18 @@ +package org.onap.sdc.dcae.rule.editor.translators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.HpMetricAction; + +public class HpMetricTranslator extends ActionTranslator<HpMetricAction> { + + private static HpMetricTranslator hpMetricTranslator = new HpMetricTranslator(); + + public static HpMetricTranslator getInstance() { + return hpMetricTranslator; + } + + private HpMetricTranslator(){} + + public Object translateToHpJson(HpMetricAction action) { + return new CopyActionSetTranslation("parserType", action.getSelectedHpMetric()); + } +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java index 97269ef..eeffda2 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/IRuleElementTranslator.java @@ -33,7 +33,7 @@ public interface IRuleElementTranslator<T> { class RuleTranslation { protected String phase; protected Object filter; - protected List<Object> processors = new ArrayList<>(); + protected List<ProcessorTranslation> processors = new ArrayList<>(); } class RunPhaseProcessorsTranslation extends ProcessorTranslation { diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogEventTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogEventTranslator.java index 8c29070..959a98e 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogEventTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogEventTranslator.java @@ -22,7 +22,7 @@ public class LogEventTranslator extends ActionTranslator<LogEventAction> { LogEventTranslation(LogEventAction action) { clazz = "LogEvent"; - title = action.getTitle(); + title = action.logTitle(); } } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogTextTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogTextTranslator.java index a9ed5bb..dada486 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogTextTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/LogTextTranslator.java @@ -24,9 +24,9 @@ public class LogTextTranslator extends ActionTranslator<LogTextAction> { private LogTextTranslation(LogTextAction action) { clazz = "LogText"; - logLevel = action.getLevel(); - logName = action.getName(); - logText = action.getText(); + logLevel = action.logLevel(); + logName = action.logName(); + logText = action.logText(); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java index d493abb..b83f646 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/MapActionTranslator.java @@ -27,7 +27,7 @@ public class MapActionTranslator extends ActionTranslator<MapAction> { private MapActionTranslation(MapAction action) { clazz = "MapAlarmValues"; Default = action.getMapDefaultValue(); - field = action.getFromValue(); + field = action.fromValue(); toField = action.getTarget(); map = action.transformToMap(); } 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 91a1ab0..cefb429 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 @@ -1,9 +1,11 @@ package org.onap.sdc.dcae.rule.editor.translators; -import java.util.List; -import java.util.stream.Collectors; - import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRules; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Rule; +import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; + +import java.util.*; +import java.util.stream.Collectors; public class MappingRulesTranslator implements IRuleElementTranslator<MappingRules> { @@ -17,15 +19,14 @@ public class MappingRulesTranslator implements IRuleElementTranslator<MappingRul } private RuleTranslator ruleTranslator = RuleTranslator.getInstance(); + private ConditionTranslator conditionTranslator = ConditionTranslator.getInstance(); public Object translateToHpJson(MappingRules mappingRules) { return new MappingRulesTranslation(mappingRules); } - public Object translateToHpJson(MappingRules mappingRules, String entryPointPhaseName, String lastPhaseName, String runPhase) { - // 1806 US349308 assign Vfcmt name as rule phaseName - mappingRules.getRules().forEach((k,v) -> v.setPhase(runPhase)); - return new MappingRulesTranslation(mappingRules, entryPointPhaseName, lastPhaseName, runPhase); + private List<Object> getPhaseTranslation(Collection<Rule> currentPhase) { + return currentPhase.stream().map(ruleTranslator::translateToHpJson).collect(Collectors.toList()); } private class MappingRulesTranslation { @@ -33,26 +34,50 @@ public class MappingRulesTranslator implements IRuleElementTranslator<MappingRul private List<Object> processing; private MappingRulesTranslation(MappingRules mappingRules) { - processing = mappingRules.getRules().values().stream().map(ruleTranslator::translateToHpJson).collect(Collectors.toList()); - } - - private MappingRulesTranslation(MappingRules mappingRules, String entryPointPhaseName, String lastPhaseName, String runPhase) { - this(mappingRules); - //hardcoded entry point processor - processing.add(0, new RunPhaseRuleTranslation(entryPointPhaseName, runPhase)); - //hardcoded map_publish processor - processing.add(new RunPhaseRuleTranslation(runPhase, lastPhaseName)); + String firstRunPhase; + // single phase + if(mappingRules.getRules().values().stream().noneMatch(r -> ValidationUtils.validateNotEmpty(r.getGroupId()))) { + processing = getPhaseTranslation(mappingRules.getRules().values()); + firstRunPhase = mappingRules.getRules().values().iterator().next().getPhase(); + } else { + // 1810 US427299 phase grouping - support user defined phase names + Map<String, List<Rule>> reorderByGroupId = mappingRules.getRules().values().stream().collect(Collectors.groupingBy(Rule::getGroupId, LinkedHashMap::new, Collectors.toList())); + List<String> phaseNames = new ArrayList<>(); + processing = new ArrayList<>(); + reorderByGroupId.forEach((k,v) -> { + String currentPhaseName = v.get(0).getPhase(); + // if phase name already triggered no need to call RunPhase processor again. + if(!processing.isEmpty() && !phaseNames.contains(currentPhaseName)) { + ((RuleTranslation)processing.get(processing.size()-1)).processors.add(new RunPhaseProcessorsTranslation(currentPhaseName)); + } + processing.addAll(getPhaseTranslation(v)); + phaseNames.add(currentPhaseName); + }); + firstRunPhase = phaseNames.get(0); + } + //hardcoded entry point processor - added as a phase unit + processing.add(0, new RunPhaseRuleTranslation(mappingRules.getEntryPhase(), firstRunPhase, mappingRules.getNotifyId())); + //hardcoded map_publish processor - added as processor unit to last phase unit + ((RuleTranslation)processing.get(processing.size()-1)).processors.add(new RunPhaseProcessorsTranslation(mappingRules.getPublishPhase())); } } + private class RunPhaseRuleTranslation extends RuleTranslation { private RunPhaseRuleTranslation(String phaseName, String runPhase) { phase = phaseName; + processors.add(new RunPhaseProcessorsTranslation(runPhase)); + } + + private RunPhaseRuleTranslation(String phaseName, String runPhase, String notifyOid) { + this(phaseName, runPhase); if("snmp_map".equals(phaseName)) { - processors.add(new SnmpConvertor()); + processors.add(0, new SnmpConvertor()); + } + if(ValidationUtils.validateTargetField(notifyOid)) { + filter = conditionTranslator.notifyOidTranslation(notifyOid); } - processors.add(new RunPhaseProcessorsTranslation(runPhase)); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java index 85fdf1d..f8da7cb 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RegexActionTranslator.java @@ -22,9 +22,9 @@ public class RegexActionTranslator extends ActionTranslator<BaseCopyAction> { private RegexCopyActionTranslation(BaseCopyAction action) { clazz = "ExtractText"; - regex = action.getRegexValue(); + regex = action.regexValue(); field = action.getTarget(); - value = action.getFromValue(); + value = action.fromValue(); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ReplaceActionTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ReplaceActionTranslator.java index 3069df3..8087760 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ReplaceActionTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/ReplaceActionTranslator.java @@ -24,9 +24,9 @@ public class ReplaceActionTranslator extends ActionTranslator<ReplaceTextAction> ReplaceActionTranslation(ReplaceTextAction action) { clazz = "ReplaceText"; - field = action.getFromValue(); - find = action.getFind(); - replace = action.getReplace(); + field = action.fromValue(); + find = action.find(); + replace = action.replace(); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java index b98050d..bce3980 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/RuleTranslator.java @@ -39,12 +39,18 @@ public class RuleTranslator implements IRuleElementTranslator<Rule> { private IRuleElementTranslator getConditionTranslator(BaseCondition condition){ return condition instanceof ConditionGroup ? ConditionGroupTranslator.getInstance() : - ValidationUtils.validateNotEmpty(OperatorTypeEnum.getTypeByName(((Condition)condition).getOperator()).getModifiedType()) ? FieldConditionTranslator.getInstance() : ConditionTranslator.getInstance(); + getSimpleConditionTranslator((Condition) condition); } + private IRuleElementTranslator getSimpleConditionTranslator(Condition condition) { + String conditionType = OperatorTypeEnum.getTypeByName(condition.getOperator()).getConditionType(); + return RuleEditorElementType.getElementTypeByName(conditionType).getTranslator(); + } + + private ActionTranslator getActionTranslator(BaseAction action) { ActionTypeEnum type = ActionTypeEnum.getTypeByName(action.getActionType()); - if(ActionTypeEnum.COPY == type && ValidationUtils.validateNotEmpty(((BaseCopyAction)action).getRegexValue())) { + if(ActionTypeEnum.COPY == type && ValidationUtils.validateNotEmpty(((BaseCopyAction)action).regexValue())) { return RegexActionTranslator.getInstance(); } return (ActionTranslator) RuleEditorElementType.getElementTypeByName(type.getType()).getTranslator(); diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/StringTransformTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/StringTransformTranslator.java new file mode 100644 index 0000000..de326d1 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/StringTransformTranslator.java @@ -0,0 +1,34 @@ +package org.onap.sdc.dcae.rule.editor.translators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.StringTransformAction; + +public class StringTransformTranslator extends ActionTranslator<StringTransformAction> { + + private static StringTransformTranslator stringTransformTranslator = new StringTransformTranslator(); + + public static StringTransformTranslator getInstance() { + return stringTransformTranslator; + } + + private StringTransformTranslator() { + } + + private class StringTransformTranslation extends ProcessorTranslation { + private String targetCase; + private String trim; + private String toField; + private String value; + + private StringTransformTranslation(StringTransformAction action) { + clazz = "StringTransform"; + targetCase = action.targetCase(); + trim = String.valueOf(action.trim()); + toField = action.getTarget(); + value = action.fromValue(); + } + } + + public Object translateToHpJson(StringTransformAction action) { + return new StringTransformTranslation(action); + } +}
\ No newline at end of file diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/TopoSearchTranslator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/TopoSearchTranslator.java new file mode 100644 index 0000000..005b005 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/translators/TopoSearchTranslator.java @@ -0,0 +1,60 @@ +package org.onap.sdc.dcae.rule.editor.translators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.Condition; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.TopoSearchAction; +import org.onap.sdc.dcae.rule.editor.enums.OperatorTypeEnum; +import org.onap.sdc.dcae.rule.editor.enums.RuleEditorElementType; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class TopoSearchTranslator extends ActionTranslator<TopoSearchAction> { + + private static TopoSearchTranslator topoSearchTranslator = new TopoSearchTranslator(); + + public static TopoSearchTranslator getInstance() { + return topoSearchTranslator; + } + + private TopoSearchTranslator() { + } + + private class TopoSearchTranslation extends ProcessorTranslation { + private String searchField; + private String searchValue; + private Object searchFilter; + private Map <String, Object> updates; + private List<String> enrichFields; + private String enrichPrefix; + + private TopoSearchTranslation(TopoSearchAction action) { + clazz = "TopoSearch"; + searchField = action.searchField(); + searchValue = action.searchValue(); + if(action.conditionalSearch()) { + searchFilter = getSimpleConditionTranslation(action.searchFilter()); + } + if(action.doEnrich()){ + enrichFields = action.enrichFields(); + enrichPrefix = action.enrichPrefix(); + } else { + updates = new LinkedHashMap<>(); + updates.putAll(action.updatesMap()); + updates.put("isEnriched", true); + } + } + } + + private Object getSimpleConditionTranslation(Condition condition) { + String conditionType = OperatorTypeEnum.getTypeByName(condition.getOperator()).getConditionType(); + IRuleElementTranslator<Condition> translator = RuleEditorElementType.getElementTypeByName(conditionType).getTranslator(); + return translator.translateToHpJson(condition); + } + + + public Object translateToHpJson(TopoSearchAction action) { + return new TopoSearchTranslation(action); + } + +} 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 33f9e92..8391d76 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 @@ -2,6 +2,8 @@ package org.onap.sdc.dcae.rule.editor.utils; import java.util.List; +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.common.onaplog.OnapLoggerError; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*; @@ -10,29 +12,39 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; public class RulesPayloadUtils { - private static Gson gson = new GsonBuilder().serializeNulls() - .registerTypeAdapter(BaseAction.class, new ActionDeserializer()) - .registerTypeAdapter(BaseCondition.class, new ConditionDeserializer()).create(); - public static Rule parsePayloadToRule(String payload) throws JsonParseException { - return gson.fromJson(payload, Rule.class); - } + private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - public static MappingRules parseMappingRulesArtifactPayload(String payload) throws JsonParseException { - return gson.fromJson(payload, MappingRules.class); - } + private static Gson gson = new GsonBuilder().serializeNulls() + .registerTypeAdapter(BaseAction.class, new ActionDeserializer()) + .registerTypeAdapter(BaseCondition.class, new ConditionDeserializer()).create(); - public static SchemaInfo extractInfoFromDescription(Artifact rulesArtifact) { - try { - return gson.fromJson(rulesArtifact.getArtifactDescription(), SchemaInfo.class); - }catch (JsonParseException e) { - return null; - } - } + private RulesPayloadUtils(){} - public static String buildSchemaAndRulesResponse(String payload, List<EventTypeDefinitionUI> schema) { - return "{\"schema\":"+gson.toJson(schema)+","+payload.replaceFirst("\\{", ""); + public static Rule parsePayloadToRule(String payload) { + return gson.fromJson(payload, Rule.class); + } + + public static MappingRules parseMappingRulesArtifactPayload(String payload) { + return gson.fromJson(payload, MappingRules.class); + } + + public static MappingRulesResponse parsePayloadToMappingRules(String payload) { + return gson.fromJson(payload, MappingRulesResponse.class); } + public static SchemaInfo extractInfoFromDescription(Artifact rulesArtifact) { + try { + return gson.fromJson(rulesArtifact.getArtifactDescription(), SchemaInfo.class); + }catch (JsonParseException e) { + errLogger.log(LogLevel.ERROR, RulesPayloadUtils.class.getName(), "Exception thrown while parsing rule artifact description: {}", e); + return null; + } + } + + public static String buildSchemaAndRulesResponse(String payload, List<EventTypeDefinitionUI> schema) { + return "{\"schema\":"+gson.toJson(schema)+","+payload.replaceFirst("\\{", ""); + } + } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java index 7a3b206..fd5e954 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/utils/ValidationUtils.java @@ -14,7 +14,4 @@ public class ValidationUtils { public static boolean validateTargetField(String value) { return validateNotEmpty(value) && !EXPLICIT_EMPTY.equals(value); } - - - } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseActionValidator.java new file mode 100644 index 0000000..18a1291 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseActionValidator.java @@ -0,0 +1,20 @@ +package org.onap.sdc.dcae.rule.editor.validators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseAction; +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.utils.ValidationUtils; + +import java.util.List; + +public abstract class BaseActionValidator<A extends BaseAction> implements IRuleElementValidator<A> { + + public boolean validate(A action, List<ResponseFormat> errors) { + if(!ValidationUtils.validateNotEmpty(action.getId())) { + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, "", "missing action id")); + return false; + } + return true; + } +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseConditionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseConditionValidator.java new file mode 100644 index 0000000..896648a --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/BaseConditionValidator.java @@ -0,0 +1,20 @@ +package org.onap.sdc.dcae.rule.editor.validators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.BaseCondition; +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.utils.ValidationUtils; + +import java.util.List; + +public abstract class BaseConditionValidator<C extends BaseCondition> implements IRuleElementValidator<C> { + + public boolean validate(C condition, List<ResponseFormat> errors) { + if(!ValidationUtils.validateNotEmpty(condition.getLevel()) || !ValidationUtils.validateNotEmpty(condition.getId()) || !ValidationUtils.validateNotEmpty(condition.getName())) { + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, "", "missing condition information")); + return false; + } + return true; + } +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ClearActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ClearActionValidator.java index 8be49b5..3991bb2 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ClearActionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ClearActionValidator.java @@ -4,10 +4,11 @@ import org.onap.sdc.dcae.composition.restmodels.ruleeditor.UnaryFieldAction; 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.utils.ValidationUtils; import java.util.List; -public class ClearActionValidator implements IRuleElementValidator<UnaryFieldAction> { +public class ClearActionValidator extends BaseActionValidator<UnaryFieldAction> { private static ClearActionValidator clearActionValidator = new ClearActionValidator(); @@ -17,11 +18,12 @@ public class ClearActionValidator implements IRuleElementValidator<UnaryFieldAct private ClearActionValidator(){} + @Override public boolean validate(UnaryFieldAction action, List<ResponseFormat> errors) { - if(action.getFromValues().isEmpty()) { + if(action.fromValues().isEmpty() || !action.fromValues().stream().allMatch(ValidationUtils::validateNotEmpty)) { errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from", action.getActionType(), action.strippedTarget())); return false; } - return true; + return super.validate(action, errors); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java index 956ac51..934dea5 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConcatActionValidator.java @@ -20,7 +20,7 @@ public class ConcatActionValidator extends CopyActionValidator<BaseCopyAction> { @Override protected boolean validateFromValue(BaseCopyAction action, List<ResponseFormat> errors) { - if(!ValidationUtils.validateNotEmpty(action.getFromValue()) || 2 > action.getFromValues().size()) { + if(!ValidationUtils.validateNotEmpty(action.fromValue()) || 2 > action.fromValues().size()) { errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_CONCAT_VALUE, null, action.getTarget())); return false; } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java index 995a817..0a420d9 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ConditionGroupValidator.java @@ -11,7 +11,7 @@ import org.springframework.util.CollectionUtils; import java.util.List; -public class ConditionGroupValidator implements IRuleElementValidator<ConditionGroup> { +public class ConditionGroupValidator extends BaseConditionValidator<ConditionGroup> { private static ConditionGroupValidator conditionGroupValidator = new ConditionGroupValidator(); @@ -21,8 +21,9 @@ public class ConditionGroupValidator implements IRuleElementValidator<ConditionG private ConditionGroupValidator(){} + @Override public boolean validate(ConditionGroup condition, List<ResponseFormat> errors) { - boolean valid = true; + boolean valid = super.validate(condition, errors); if(!ValidationUtils.validateNotEmpty(condition.getType()) || null == ConditionTypeEnum.getTypeByName(condition.getType())) { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_GROUP_CONDITION, null, condition.getType())); 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 1b4ae94..9ba4479 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 @@ -10,7 +10,7 @@ import org.springframework.util.CollectionUtils; import java.util.List; -public class ConditionValidator implements IRuleElementValidator<Condition> { +public class ConditionValidator extends BaseConditionValidator<Condition> { private static ConditionValidator conditionValidator = new ConditionValidator(); @@ -20,19 +20,26 @@ public class ConditionValidator implements IRuleElementValidator<Condition> { private ConditionValidator(){} + @Override public boolean validate(Condition condition, List<ResponseFormat> errors) { + return validateConditionalAction(condition, errors) && super.validate(condition, errors); + } + + + public boolean validateConditionalAction(Condition condition, List<ResponseFormat> errors) { boolean valid = true; if(!ValidationUtils.validateNotEmpty(condition.getLeft())) { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "left")); } - if(CollectionUtils.isEmpty(condition.getRight())) { + OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getTypeByName(condition.getOperator()); + if(null == operatorTypeEnum) { valid = false; - errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "right")); + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_OPERATOR, null, condition.getOperator())); } - if(!ValidationUtils.validateNotEmpty(condition.getOperator()) || null == OperatorTypeEnum.getTypeByName(condition.getOperator())) { + if(OperatorTypeEnum.ASSIGNED != operatorTypeEnum && OperatorTypeEnum.UNASSIGNED != operatorTypeEnum && (condition.getRight().isEmpty() || !condition.getRight().stream().allMatch(ValidationUtils::validateNotEmpty))) { valid = false; - errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_OPERATOR, null, condition.getOperator())); + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_OPERAND, null, "right")); } return valid; } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/CopyActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/CopyActionValidator.java index 74102a6..42d86ae 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/CopyActionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/CopyActionValidator.java @@ -8,7 +8,7 @@ import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; import java.util.List; -public class CopyActionValidator<A extends BaseCopyAction> implements IRuleElementValidator<A> { +public class CopyActionValidator<A extends BaseCopyAction> extends BaseActionValidator<A> { private static CopyActionValidator copyActionValidator = new CopyActionValidator(); @@ -18,6 +18,7 @@ public class CopyActionValidator<A extends BaseCopyAction> implements IRuleEleme CopyActionValidator(){} + @Override public boolean validate(A action, List<ResponseFormat> errors) { // validate from is populated @@ -27,14 +28,19 @@ public class CopyActionValidator<A extends BaseCopyAction> implements IRuleEleme valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "target", action.getActionType(), action.getTarget())); } - return valid; + return valid && super.validate(action, errors); } protected boolean validateFromValue(A action, List<ResponseFormat> errors) { - if(!ValidationUtils.validateNotEmpty(action.getFromValue())) { + if(!ValidationUtils.validateNotEmpty(action.fromValue())) { errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from", action.getActionType(), action.getTarget())); return false; } + //1810 US423851 validate imported input + if(!ValidationUtils.validateNotEmpty(action.regexState())) { + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, "", "missing regex state field")); + return false; + } return true; } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java index 19af40c..2776c8b 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/DateFormatterValidator.java @@ -20,19 +20,19 @@ public class DateFormatterValidator extends CopyActionValidator<DateFormatterAct @Override public boolean validate(DateFormatterAction action, List<ResponseFormat> errors) { boolean valid = super.validate(action, errors); - if(!ValidationUtils.validateNotEmpty(action.getFromFormat())){ + if(!ValidationUtils.validateNotEmpty(action.fromFormat())){ valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from format", action.getActionType(), action.getTarget())); } - if(!ValidationUtils.validateNotEmpty(action.getFromTz())){ + if(!ValidationUtils.validateNotEmpty(action.fromTz())){ valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from timezone", action.getActionType(), action.getTarget())); } - if(!ValidationUtils.validateNotEmpty(action.getToFormat())){ + if(!ValidationUtils.validateNotEmpty(action.toFormat())){ valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "to format", action.getActionType(), action.getTarget())); } - if(!ValidationUtils.validateNotEmpty(action.getToTz())){ + if(!ValidationUtils.validateNotEmpty(action.toTz())){ valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "to timezone", action.getActionType(), action.getTarget())); } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/HpMetricValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/HpMetricValidator.java new file mode 100644 index 0000000..7bd382c --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/HpMetricValidator.java @@ -0,0 +1,29 @@ +package org.onap.sdc.dcae.rule.editor.validators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.HpMetricAction; +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.utils.ValidationUtils; + +import java.util.List; + +public class HpMetricValidator extends BaseActionValidator<HpMetricAction> { + + private static HpMetricValidator hpMetricValidator = new HpMetricValidator(); + + public static HpMetricValidator getInstance() { + return hpMetricValidator; + } + + private HpMetricValidator(){} + + @Override + public boolean validate(HpMetricAction action, List<ResponseFormat> errors) { + if(!ValidationUtils.validateNotEmpty(action.getSelectedHpMetric())){ + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "HP Metric", action.getActionType(), action.strippedTarget())); + return false; + } + return super.validate(action, errors); + } +}
\ No newline at end of file diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogEventValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogEventValidator.java index 1bbf07a..96393dd 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogEventValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogEventValidator.java @@ -8,7 +8,7 @@ import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; import java.util.List; -public class LogEventValidator implements IRuleElementValidator<LogEventAction> { +public class LogEventValidator extends BaseActionValidator<LogEventAction> { private static LogEventValidator logEventValidator = new LogEventValidator(); @@ -16,13 +16,14 @@ public class LogEventValidator implements IRuleElementValidator<LogEventAction> return logEventValidator; } - LogEventValidator(){} + private LogEventValidator(){} + @Override public boolean validate(LogEventAction action, List<ResponseFormat> errors) { - if(!ValidationUtils.validateNotEmpty(action.getTitle())){ + if(!ValidationUtils.validateNotEmpty(action.logTitle())){ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "title", action.getActionType(), action.strippedTarget())); return false; } - return true; + return super.validate(action, errors); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogTextValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogTextValidator.java index 711692f..45c04db 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogTextValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/LogTextValidator.java @@ -8,7 +8,7 @@ import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; import java.util.List; -public class LogTextValidator implements IRuleElementValidator<LogTextAction> { +public class LogTextValidator extends BaseActionValidator<LogTextAction> { private static LogTextValidator logTextValidator = new LogTextValidator(); @@ -16,13 +16,14 @@ public class LogTextValidator implements IRuleElementValidator<LogTextAction> { return logTextValidator; } - LogTextValidator(){} + private LogTextValidator(){} + @Override public boolean validate(LogTextAction action, List<ResponseFormat> errors) { - if(!ValidationUtils.validateNotEmpty(action.getText())){ + if(!ValidationUtils.validateNotEmpty(action.logText())){ errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "text", action.getActionType(), action.strippedTarget())); return false; } - return true; + return super.validate(action, errors); } } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java index 130e428..64c2088 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MapActionValidator.java @@ -46,6 +46,6 @@ public class MapActionValidator extends CopyActionValidator<MapAction> { } private boolean validateMapValues(MapAction action) { - return action.transformToMap().entrySet().stream().noneMatch(p -> !ValidationUtils.validateNotEmpty(p.getKey()) || !ValidationUtils.validateNotEmpty(p.getValue())); + return action.transformToMap().entrySet().stream().allMatch(p -> ValidationUtils.validateNotEmpty(p.getKey()) && ValidationUtils.validateNotEmpty(p.getValue())); } } 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 new file mode 100644 index 0000000..90fda4d --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/MappingRulesValidator.java @@ -0,0 +1,73 @@ +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; +import org.onap.sdc.dcae.errormng.ErrConfMgr; +import org.onap.sdc.dcae.errormng.ResponseFormat; +import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; +import org.onap.sdc.dcae.ves.VesStructureLoader; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class MappingRulesValidator implements IRuleElementValidator<MappingRules> { + + private RuleValidator ruleValidator = RuleValidator.getInstance(); + + private static MappingRulesValidator mappingRulesValidator = new MappingRulesValidator(); + + public static MappingRulesValidator getInstance() { + return mappingRulesValidator; + } + + private MappingRulesValidator(){} + + public boolean validate(MappingRules rules, List<ResponseFormat> 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 + } + + private boolean validateVersionAndType(MappingRules rules, List<ResponseFormat> errors) { + Map<String, Set<String>> 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; + } + + private boolean validateImportedGroupDefinitions(MappingRules rules, List<ResponseFormat> 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) { + 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()); + } + + + public boolean validateTranslationPhaseNames(MappingRules rules, List<ResponseFormat> errors) { + boolean valid = true; + Set<String> phases = rules.getRules().values().stream().map(Rule::getPhase).collect(Collectors.toSet()); + if(phases.contains(rules.getEntryPhase())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.TRANSLATE_FAILED, null, "entry phase name already exists")); + } + if(phases.contains(rules.getPublishPhase())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.TRANSLATE_FAILED, null, "publish phase name already exists")); + } + return valid; + } +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ReplaceActionValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ReplaceActionValidator.java index d9aea82..1f879f6 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ReplaceActionValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/ReplaceActionValidator.java @@ -8,7 +8,7 @@ import org.onap.sdc.dcae.rule.editor.utils.ValidationUtils; import java.util.List; -public class ReplaceActionValidator implements IRuleElementValidator<ReplaceTextAction> { +public class ReplaceActionValidator extends BaseActionValidator<ReplaceTextAction> { private static ReplaceActionValidator replaceActionValidator = new ReplaceActionValidator(); @@ -19,16 +19,16 @@ public class ReplaceActionValidator implements IRuleElementValidator<ReplaceText private ReplaceActionValidator(){} public boolean validate(ReplaceTextAction action, List<ResponseFormat> errors) { - boolean valid = true; - if(!ValidationUtils.validateNotEmpty(action.getFromValue())) { + boolean valid = super.validate(action, errors); + if(!ValidationUtils.validateNotEmpty(action.fromValue())) { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "from", action.getActionType(), action.strippedTarget())); } - if(!ValidationUtils.validateNotEmpty(action.getFind())) { + if(!ValidationUtils.validateNotEmpty(action.find())) { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "find", action.getActionType(), action.strippedTarget())); } - if(!ValidationUtils.validateNotEmpty(action.getReplace())) { + if(!ValidationUtils.validateNotEmpty(action.replace())) { valid = false; errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "replace", action.getActionType(), action.strippedTarget())); } diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java index 33e1b33..5f577c8 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/RuleValidator.java @@ -21,9 +21,11 @@ public class RuleValidator implements IRuleElementValidator<Rule> { private RuleValidator(){} public boolean validate(Rule rule, List<ResponseFormat> errors) { - boolean valid = true; - if(rule.isConditionalRule()) { - valid = getConditionValidator(rule.getCondition()).validate(rule.getCondition(), errors); + boolean valid = !rule.isConditionalRule() || getConditionValidator(rule.getCondition()).validate(rule.getCondition(), errors); + // 1810 US427299 phase grouping - support user defined phase names + if(ValidationUtils.validateNotEmpty(rule.getGroupId()) && !ValidationUtils.validateNotEmpty(rule.getPhase())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.INVALID_RULE_FORMAT, "", "please define group name")); } if(!ValidationUtils.validateNotEmpty(rule.getDescription())) { valid = false; diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/StringTransformValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/StringTransformValidator.java new file mode 100644 index 0000000..a53b3f2 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/StringTransformValidator.java @@ -0,0 +1,38 @@ +package org.onap.sdc.dcae.rule.editor.validators; + +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.StringTransformAction; +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.utils.ValidationUtils; + +import java.util.List; + +public class StringTransformValidator extends BaseActionValidator<StringTransformAction> { + + private static StringTransformValidator stringTransformValidator = new StringTransformValidator(); + + public static StringTransformValidator getInstance() { + return stringTransformValidator; + } + + private StringTransformValidator(){} + + @Override + public boolean validate(StringTransformAction action, List<ResponseFormat> errors) { + boolean valid = super.validate(action, errors); + if(!ValidationUtils.validateNotEmpty(action.targetCase())){ + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "target case", action.getActionType(), action.getTarget())); + } + if (!ValidationUtils.validateTargetField(action.getTarget())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "target", action.getActionType(), action.getTarget())); + } + if (!ValidationUtils.validateTargetField(action.startValue())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "value", action.getActionType(), action.getTarget())); + } + return valid; + } +} diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/TopoSearchValidator.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/TopoSearchValidator.java new file mode 100644 index 0000000..1abc2d8 --- /dev/null +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/rule/editor/validators/TopoSearchValidator.java @@ -0,0 +1,69 @@ +package org.onap.sdc.dcae.rule.editor.validators; + +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.TopoSearchAction; +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.utils.ValidationUtils; + +import java.util.List; + +public class TopoSearchValidator extends BaseActionValidator<TopoSearchAction> { + + private static TopoSearchValidator topoSearchValidator = new TopoSearchValidator(); + + public static TopoSearchValidator getInstance() { + return topoSearchValidator; + } + + private TopoSearchValidator() { + } + + private ConditionValidator conditionValidator = ConditionValidator.getInstance(); + + @Override + public boolean validate(TopoSearchAction action, List<ResponseFormat> errors) { + + boolean valid = super.validate(action, errors); + if (action.conditionalSearch() && !conditionValidator.validateConditionalAction(action.searchFilter(), errors)) { + valid = false; + } + if (!ValidationUtils.validateNotEmpty(action.searchField())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "search field", action.getActionType(), action.strippedTarget())); + } + if (!ValidationUtils.validateNotEmpty(action.searchValue())) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "search value", action.getActionType(), action.strippedTarget())); + } + return validateEnrichOrUpdates(action, errors) && valid; + } + + + private boolean validateEnrichOrUpdates(TopoSearchAction action, List<ResponseFormat> errors) { + if (!action.doEnrich()) { + return validateUpdatesMap(action, errors); + } + if (action.enrichFields().isEmpty() || !action.enrichFields().stream().allMatch(ValidationUtils::validateNotEmpty)) { + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "enrich fields", action.getActionType(), action.strippedTarget())); + return false; + } + return true; + } + + private boolean validateUpdatesMap(TopoSearchAction action, List<ResponseFormat> errors) { + boolean valid = true; + try { + if (!action.updatesMap().entrySet().stream().allMatch(p -> ValidationUtils.validateNotEmpty(p.getKey()) && ValidationUtils.validateNotEmpty(p.getValue()))) { + valid = false; + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.MISSING_ACTION_FIELD, null, "key/value", action.getActionType(), action.strippedTarget())); + } + } catch (IllegalStateException err) { + valid = false; + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "updates validation error: {}", err); + errors.add(ErrConfMgr.INSTANCE.getResponseFormat(ActionStatus.DUPLICATE_KEY, null)); + } + return valid; + } +} diff --git a/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/application.properties b/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/application.properties index b833be9..2bb725d 100644 --- a/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/application.properties +++ b/dcaedt_be/src/main/webapp/WEB-INF/config/dcae-be/application.properties @@ -33,6 +33,12 @@ compositionConfig.flowTypes={"Syslog":{"entryPointPhaseName":"syslog_map","lastP "SNMP PM Poller":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publilsh"},\ "Discovery and MIB Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ "Nagios docker MSE":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "Discovery Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ + "MIB Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ + "VES Fault SE":{"entryPointPhaseName":"ves_fault_map","lastPhaseName":"ves_fault_publish"},\ + "Docker Supplement":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "Docker Enrich":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "VES Collector":{"entryPointPhaseName":"sam_collector_map","lastPhaseName":"sam_collector_publish"},\ "VES Fault":{"entryPointPhaseName":"ves_fault_map","lastPhaseName":"ves_fault_publish"},\ "VES Heartbeat":{"entryPointPhaseName":"ves_heartbeat_map","lastPhaseName":"ves_heartbeat_publish"},\ "VES Measurement":{"entryPointPhaseName":"ves_measurement_map","lastPhaseName":"ves_measurement_publish"},\ diff --git a/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogicTest.java b/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogicTest.java index ac12f8d..25bf1f1 100644 --- a/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogicTest.java +++ b/dcaedt_be/src/test/java/org/onap/sdc/dcae/composition/impl/CompositionCatalogBusinessLogicTest.java @@ -7,68 +7,84 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.sdc.dcae.catalog.asdc.ASDCCatalog; +import org.onap.sdc.dcae.catalog.asdc.ASDCException; import org.onap.sdc.dcae.catalog.engine.CatalogController; import org.onap.sdc.dcae.catalog.engine.CatalogError; import org.onap.sdc.dcae.catalog.engine.CatalogResponse; +import org.onap.sdc.dcae.client.ISdcClient; +import org.onap.sdc.dcae.composition.restmodels.canvas.DcaeComponentCatalog; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; +import org.onap.sdc.dcae.composition.util.DcaeBeConstants; +import org.onap.sdc.dcae.errormng.ErrorConfigurationLoader; +import org.onap.sdc.dcae.errormng.RequestError; +import org.onap.sdc.dcae.errormng.ResponseFormat; +import org.onap.sdc.dcae.errormng.ServiceException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.async.DeferredResult; -import java.net.URI; +import java.util.Arrays; +import java.util.List; import java.util.UUID; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; public class CompositionCatalogBusinessLogicTest { + private final String REQUEST_ID = "123456"; + private ASDCCatalog asdcCatalog = new ASDCCatalog(); + @Mock private CatalogController catalogController; - private ASDCCatalog asdcCatalog = new ASDCCatalog(URI.create("https://mockUri:8888#mock")); + @Mock + private ISdcClient sdcRestClient; @InjectMocks - private CompositionCatalogBusinessLogic compositionCatalogBusinessLogic = new CompositionCatalogBusinessLogic(); + private CompositionCatalogBusinessLogic compositionCatalogBusinessLogic; @Before public void init() throws JSONException { MockitoAnnotations.initMocks(this); - when(catalogController.getCatalog(any())).thenReturn(asdcCatalog); + when(catalogController.getCatalog()).thenReturn(asdcCatalog); + new ErrorConfigurationLoader(System.getProperty("user.dir")+"/src/main/webapp/WEB-INF"); + mockCatalog(); } @Test - public void getItemsTest() { - compositionCatalogBusinessLogic.getItems(null).getResult(); - verify(catalogController, times(7)).patchData(any(), any()); + public void getCatalogTest() { + DcaeComponentCatalog catalog = compositionCatalogBusinessLogic.getCatalog(REQUEST_ID); + assertEquals(1, catalog.getElements().size()); + assertEquals(1, catalog.getElements().get(0).getItems().size()); } - @Test - public void getItemByIdNoSuchFolderFailureTest() { - DeferredResult<CatalogResponse> result = compositionCatalogBusinessLogic.getItemById(null, "No Such Category"); - verify(catalogController).getCatalog(any()); - verify(catalogController, times(0)).patchData(any(), any()); - CatalogError error = (CatalogError)result.getResult(); - assertEquals("{\"exception\":\"java.lang.RuntimeException: No such folder No Such Category\",\"message\":\"Catalog API failed\"}", error.getError()); - } @Test public void getModelByIdInvalidUuidFailureTest() { - try { - compositionCatalogBusinessLogic.getModelById(null, "Invalid-UUID"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid UUID string: Invalid-UUID", e.getMessage()); - verify(catalogController).getCatalog(any()); - verify(catalogController, times(0)).patchData(any(), any()); - } + ResponseEntity result = compositionCatalogBusinessLogic.getModelById(REQUEST_ID, "invalidId"); + assertEquals("Invalid UUID string: invalidId", ((ResponseFormat)result.getBody()).getNotes()); } @Test public void getTypeInfoModelNotLoadedFailureTest() { - // this is pretty awful. you cannot call 'getTypeInfo' unless it is preceded by a 'getModel' call of the containing model, so that the 'catalogs' item is populated by the container model id. String uuid = UUID.randomUUID().toString(); - DeferredResult<CatalogResponse> result = compositionCatalogBusinessLogic.getTypeInfo(null, uuid, "tosca.nodes.Root"); - verify(catalogController).getCatalog(any()); - verify(catalogController, times(0)).patchData(any(), any()); - CatalogError error = (CatalogError)result.getResult(); - assertEquals("{\"exception\":\"java.lang.Exception: No catalog available for resource " + uuid + ". You might want to fetch the model first.\",\"message\":\"Catalog API failed\"}", error.getError()); + // this is pretty awful. you cannot call 'getTypeInfo' unless it is preceded by a 'getModel' call of the containing model, so that the 'catalogs' item is populated by the container model id. + ResponseEntity result = compositionCatalogBusinessLogic.getTypeInfo(uuid, "tosca.nodes.Root"); + assertEquals("No catalog available for resource " + uuid + ". You might want to fetch the model first.", ((ResponseFormat)result.getBody()).getNotes()); + } + + private void mockCatalog() { + String subcategory1 = "subcategory1"; + String subcategory2 = "subcategory2"; + List<Resource> resources = Arrays.asList(buildVf(subcategory1, DcaeBeConstants.LifecycleStateEnum.CERTIFIED.name()), buildVf(subcategory1, DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()), buildVf(subcategory2, DcaeBeConstants.LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())); + when(sdcRestClient.getResources(anyString(), anyString(), eq(null), anyString())).thenReturn(resources); + } + + private Resource buildVf(String subcategory, String lifecycleState) { + Resource vf = new Resource(); + vf.setLifecycleState(lifecycleState); + vf.setSubCategory(subcategory); + return vf; } }
\ 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 d421113..3c6d1dd 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 @@ -1,31 +1,37 @@ package org.onap.sdc.dcae.composition.impl; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +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.CompositionConfig; -import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*; -import org.onap.sdc.dcae.composition.restmodels.sdc.*; +import org.onap.sdc.dcae.composition.restmodels.ruleeditor.MappingRules; +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; +import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import org.onap.sdc.dcae.composition.util.DcaeBeConstants; import org.onap.sdc.dcae.errormng.ErrorConfigurationLoader; +import org.onap.sdc.dcae.errormng.RequestError; import org.onap.sdc.dcae.errormng.ResponseFormat; +import org.onap.sdc.dcae.errormng.ServiceException; import org.onap.sdc.dcae.rule.editor.impl.RulesBusinessLogic; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.testng.Assert; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; public class RuleEditorBusinessLogicTest { // DEFAULT PROPERTIES - private String justAString = "aStringForAllSeasons"; + private String justAString = "aStringForAllSeasons"; private String userId = "gc786h"; private String vfcmtUuid = "26e8d4b5-f087-4821-a75a-0b9514b5a7ab"; private String dcaeCompLabel = "dMp.DockerMap"; @@ -34,12 +40,10 @@ public class RuleEditorBusinessLogicTest { private String artifactUuid = "9b00ba74-da02-4706-8db0-ac3c11d1d47b"; private String configParam = "aaf_username"; private String requestId = "9a89b5c7-33b2-4f7e-a404-66bf4115f510"; - private String flowTypeName = "SNMP MSE"; private String ruleUuid = "sadsads"; private String categoryName = "Template"; private String resourceType = "VFCMT"; private String saveRulesJsonRequest = "{\n\"version\":\"4.1\",\n\"eventType\":\"syslogFields\",\n\"uid\":\"\",\n\"description\":\"sfasfsaf\",\n\"actions\":[\n{\n\"id\":\"6e0175a0-581f-11e8-82eb-53bb060b790a\",\n\"actionType\":\"copy\",\n\"from\":{\n\"value\":\"asfsf\",\n\"regex\":\"\",\n\"state\":\"closed\",\n\"values\":[\n{\n" + "\"value\":\"\"\n" + "},\n" + "{\n\"value\":\"\"\n}\n]\n},\n\"target\":\"event.commonEventHeader.eventType\",\n\"map\":{\n\"values\":[\n{\n\"key\":\"\",\n\"value\":\"\"\n}\n],\n\"haveDefault\":false,\n\"default\":\"\"\n},\n\"dateFormatter\":{\n\"fromFormat\":\"\",\n\"toFormat\":\"\",\n\"fromTimezone\":\"\",\n\"toTimezone\":\"\"\n},\n\"replaceText\":{\n\"find\":\"\",\n\"replace\":\"\"\n},\n\"logText\":{\n\"name\":\"\",\n\"level\":\"\",\n\"text\":\"\"\n},\n\"logEvent\":{\n\"title\":\"\"\n}\n}\n],\n\"condition\":null\n}"; - private String artifactJson = "{\n \"artifactName\":\"composition.yml\",\n \"artifactType\":\"DCAE_TOSCA\",\n \"artifactURL\":\"/sdc/v1/catalog/resources/c2877686-616a-48ca-a37b-7e311bf83adc/artifacts/9b00ba74-da02-4706-8db0-ac3c11d1d47b\",\n \"artifactDescription\":\"createReferenceArtifact\",\n \"artifactTimeout\":null,\n \"artifactChecksum\":\"MjhhYTAwOTIxZGZkMGMyMmFjYmEzYjI1NTIwYjA3YzM=\",\n \"artifactUUID\":\"9b00ba74-da02-4706-8db0-ac3c11d1d47b\",\n \"artifactVersion\":\"1\",\n \"generatedFromUUID\":null,\n \"artifactLabel\":\"servicereference\",\n \"artifactGroupType\":\"DEPLOYMENT\",\n \"payloadData\":null,\n \"description\":null\n" + "}"; private String defaultPayload = "{eventType:syslogFields,version:4.1,rules:{'test':{'version':'4.1'}}}"; @@ -47,9 +51,7 @@ public class RuleEditorBusinessLogicTest { private ISdcClient sdcClientMock = Mockito.mock(ISdcClient.class); private ResourceDetailed vfcmt = Mockito.mock(ResourceDetailed.class); private SchemaInfo schemaInfo = Mockito.mock(SchemaInfo.class); - private CompositionConfig compositionConfig = Mockito.mock(CompositionConfig.class); private RulesBusinessLogic rulesBusinessLogic = Mockito.mock(RulesBusinessLogic.class); - private CompositionConfig.FlowType flowType = Mockito.mock(CompositionConfig.FlowType.class); @InjectMocks private RuleEditorBusinessLogic ruleEditorBusinessLogic = new RuleEditorBusinessLogic(); @@ -67,11 +69,9 @@ public class RuleEditorBusinessLogicTest { when(vfcmt.getResourceType()).thenReturn(resourceType); when(vfcmt.getCategory()).thenReturn(categoryName); - when(ruleEditorBusinessLogic.getSdcRestClient().getResource(anyString(), anyString())).thenReturn(vfcmt); + when(sdcClientMock.getResource(anyString(), anyString())).thenReturn(vfcmt); when(schemaInfo.getVersion()).thenReturn("0.2"); - /* PowerMockito.doReturn(vs).when(VesStructureLoader.class); - when(vs.getEventListenerDefinitionByVersion(anyString())).thenReturn(null);*/ } @Test @@ -79,29 +79,55 @@ public class RuleEditorBusinessLogicTest { emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, true); - when(ruleEditorBusinessLogic.getSdcRestClient().getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); - when(rulesBusinessLogic.addOrEditRule(any(MappingRules.class), any(Rule.class))).thenReturn(true); + when(sdcClientMock.getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); + when(rulesBusinessLogic.addOrEditRule(any(MappingRules.class), any(Rule.class), anyBoolean())).thenReturn(true); + when(rulesBusinessLogic.validateGroupDefinitions(any(MappingRules.class), anyBoolean())).thenReturn(true); ResponseEntity result = ruleEditorBusinessLogic.saveRule(saveRulesJsonRequest, requestId, userId, vfcmtUuid, dcaeCompLabel, nId, configParam); assertEquals(200,result.getStatusCodeValue()); - Assert.assertTrue(result.getBody().toString().contains("6e0175a0-581f-11e8-82eb-53bb060b790a")); - verify(rulesBusinessLogic,times(1)).addOrEditRule(any(MappingRules.class), any(Rule.class)); + assertTrue(result.getBody().toString().contains("6e0175a0-581f-11e8-82eb-53bb060b790a")); + verify(rulesBusinessLogic,times(1)).addOrEditRule(any(MappingRules.class), any(Rule.class), anyBoolean()); } + @Test + public void test_exportRules_resourceNotFound() throws Exception { + RequestError requestError = new RequestError(); + requestError.setServiceException(new ServiceException("SVC4063", "", null)); + when(sdcClientMock.getResource(resourceUuid, requestId)).thenThrow(new ASDCException(HttpStatus.NOT_FOUND, requestError)); + + ResponseEntity result = ruleEditorBusinessLogic.downloadRules(vfcmtUuid, dcaeCompLabel, nId, configParam, requestId); + assertEquals(404,result.getStatusCodeValue()); + } + + + @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<ResponseFormat> 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()); + } + @Test public void test_saveRules_artifactNotFound() throws Exception { emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, false); - when(rulesBusinessLogic.addOrEditRule(any(MappingRules.class), any(Rule.class))).thenReturn(true); + when(rulesBusinessLogic.addOrEditRule(any(MappingRules.class), any(Rule.class), anyBoolean())).thenReturn(true); String payload = "{eventType:syslogFields,version:4.1,rules:{'test':{'version':'4.1'}},\"nid\":\"n.1525864440166.30}"; when(ruleEditorBusinessLogic.getSdcRestClient().getResourceArtifact(anyString(),anyString(), anyString())).thenReturn(payload); ResponseEntity result = ruleEditorBusinessLogic.saveRule(saveRulesJsonRequest, requestId, userId, vfcmtUuid, dcaeCompLabel, nId, configParam); assertEquals(200,result.getStatusCodeValue()); - Assert.assertTrue(result.getBody().toString().contains("6e0175a0-581f-11e8-82eb-53bb060b790a")); - verify(rulesBusinessLogic,times(0)).addOrEditRule(any(MappingRules.class), any(Rule.class)); + assertTrue(result.getBody().toString().contains("6e0175a0-581f-11e8-82eb-53bb060b790a")); + verify(rulesBusinessLogic,times(0)).addOrEditRule(any(MappingRules.class), any(Rule.class), anyBoolean()); } @@ -116,7 +142,7 @@ public class RuleEditorBusinessLogicTest { assertEquals(400,result.getStatusCodeValue()); assertEquals("SVC6114",result.getBody().getRequestError().getServiceException().getMessageId()); assertEquals("DCAE component %1 not found in composition",result.getBody().getRequestError().getServiceException().getText()); - verify(rulesBusinessLogic,times(0)).addOrEditRule(any(MappingRules.class), any(Rule.class)); + verify(rulesBusinessLogic,times(0)).addOrEditRule(any(MappingRules.class), any(Rule.class), anyBoolean()); } @@ -125,12 +151,9 @@ public class RuleEditorBusinessLogicTest { emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, true); - when(ruleEditorBusinessLogic.getSdcRestClient().getResourceArtifact(resourceUuid, artifactUuid, requestId)) - .thenReturn(defaultPayload); - - ResponseEntity result = ruleEditorBusinessLogic.getRules(vfcmtUuid, dcaeCompLabel, nId, configParam, requestId); + ResponseEntity result = ruleEditorBusinessLogic.getRulesAndSchema(vfcmtUuid, dcaeCompLabel, nId, configParam, requestId); assertEquals(200,result.getStatusCodeValue()); - Assert.assertTrue(result.getBody().toString().contains("eventType:syslogFields,version:4.1,rules:{'test':{'version':'4.1'")); + assertTrue(result.getBody().toString().contains("eventType:syslogFields,version:4.1,rules:{'test':{'version':'4.1'")); } @@ -147,33 +170,13 @@ public class RuleEditorBusinessLogicTest { } - @Test - public void test_translate() throws Exception { - - emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, true); - - when(ruleEditorBusinessLogic.getSdcRestClient().getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); - Map<String, CompositionConfig.FlowType> flowTypeMap = new HashMap<>(); - flowTypeMap.put("SNMP MSE", flowType); - when(compositionConfig.getFlowTypesMap()).thenReturn(flowTypeMap); - when(compositionConfig.getFlowTypesMap().get("SNMP MSE").getEntryPointPhaseName()).thenReturn("testName"); - when(compositionConfig.getFlowTypesMap().get("SNMP MSE").getLastPhaseName()).thenReturn("testLastName"); - - when(rulesBusinessLogic.translateRules(any(MappingRules.class), anyString(), anyString(), anyString())).thenReturn("testLastName"); - ResponseEntity result = ruleEditorBusinessLogic.translateRules(vfcmtUuid, requestId, dcaeCompLabel, nId, configParam, flowTypeName); - verify(compositionConfig,times(6)).getFlowTypesMap(); - verify(rulesBusinessLogic,times(1)).translateRules(any(MappingRules.class), anyString(), anyString(), anyString()); - - assertEquals(200,result.getStatusCodeValue()); - - } @Test public void test_deleteRule() throws Exception { emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, true); - when(ruleEditorBusinessLogic.getSdcRestClient().getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); + when(sdcClientMock.getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); when(rulesBusinessLogic.deleteRule(any(MappingRules.class), anyString())).thenReturn(new Rule()); ResponseEntity result = ruleEditorBusinessLogic.deleteRule(userId, vfcmtUuid, dcaeCompLabel, nId, configParam, ruleUuid, requestId); @@ -181,18 +184,16 @@ public class RuleEditorBusinessLogicTest { } - @Test - public void test_getDefinition(){ - + @Test + public void test_deleteGroupOfRules() throws Exception { -/* - PowerMockito.mockStatic(VesStructureLoader.class); - when(VesStructureLoader.getEventListenerDefinitionByVersion(anyString())).thenReturn(null); -*/ + emulateMockListOfArtifacts(dcaeCompLabel, nId, configParam, true); + when(sdcClientMock.getResourceArtifact(resourceUuid, artifactUuid, requestId)).thenReturn(defaultPayload); + when(rulesBusinessLogic.deleteGroupOfRules(any(MappingRules.class), anyString())).thenReturn(Collections.singletonList(new Rule())); + ResponseEntity result = ruleEditorBusinessLogic.deleteGroupOfRules(userId, vfcmtUuid, dcaeCompLabel, nId, configParam, ruleUuid, requestId); + assertEquals(200,result.getStatusCodeValue()); + } - ResponseEntity res = ruleEditorBusinessLogic.getDefinition("4.1","syslogFields"); - - } private void emulateMockListOfArtifacts(String dcaeCompLabel, String nid, String configParam, boolean isApprovedArtifact) { List<Artifact> listOfArtifactCompositionYml = new ArrayList<>(); @@ -208,10 +209,10 @@ public class RuleEditorBusinessLogicTest { when(artifact.getArtifactType()).thenReturn("DCAE_TOSCA"); when(artifact.getArtifactUUID()).thenReturn(artifactUuid); when(artifact.getArtifactDescription()).thenReturn("createmapArtifact"); + when(artifact.getPayloadData()).thenReturn(defaultPayload); listOfArtifactCompositionYml.add(artifact); when(vfcmt.getArtifacts()).thenReturn(listOfArtifactCompositionYml); } - } 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 bc03632..3b7181d 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 @@ -5,23 +5,30 @@ import com.google.gson.GsonBuilder; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.sdc.dcae.composition.restmodels.ruleeditor.*; import org.onap.sdc.dcae.errormng.ErrorConfigurationLoader; import org.onap.sdc.dcae.errormng.ResponseFormatManager; import org.onap.sdc.dcae.errormng.ServiceException; +import org.onap.sdc.dcae.rule.editor.validators.MappingRulesValidator; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; public class RulesBusinessLogicTest { private static Gson gson = new GsonBuilder() .registerTypeAdapter(BaseAction.class, new ActionDeserializer()) .registerTypeAdapter(BaseCondition.class, new ConditionDeserializer()).create(); + private String mockUiInput = "mockUiInput"; + private MappingRulesValidator mappingRulesValidator = Mockito.mock(MappingRulesValidator.class); + @InjectMocks private RulesBusinessLogic rulesBusinessLogic = new RulesBusinessLogic(); private ResponseFormatManager responseFormatManager = null; @@ -36,33 +43,57 @@ public class RulesBusinessLogicTest { @Test public void translateSingleRuleSingleCopyActionAddSnmpHeader() throws Exception { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," - + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\"},\"class\":\"Set\"}]}," - + "{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\"},\"class\":\"Set\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; Rule rule = new Rule(); rule.setActions(new ArrayList<>()); rule.getActions().add(buildCopyAction("2.0","event.commonEventHeader.version")); rule.setDescription("description"); + rule.setPhase("phase_1"); MappingRules mr = new MappingRules(rule); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + mr.setEntryPhase("snmp_map"); + mr.setPublishPhase("map_publish"); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); + } + + @Test + public void translateSingleRuleSingleCopyActionWithNotifyOidFilter() throws Exception { + String expectedTranslation = "{\"processing\":[{\"phase\":\"foi_map\",\"filter\":{\"string\":\"${notify OID}\",\"value\":\"someValue\",\"class\":\"StartsWith\"},\"processors\":[{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]}," + + "{\"phase\":\"phase_1\",\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\"},\"class\":\"Set\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + Rule rule = new Rule(); + rule.setActions(new ArrayList<>()); + 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); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); + assertTrue(errors.isEmpty()); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test public void translateSingleRuleSingleDateFormatterActionSnmpFlow() throws Exception { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," - + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"fromFormat\":\"fromFormat\",\"fromTz\":\"fromTZ\",\"toField\":\"targetField\",\"toFormat\":\"toFormat\",\"toTz\":\"toTz\",\"value\":\"fromField\",\"class\":\"DateFormatter\"}]}," - + "{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"fromFormat\":\"fromFormat\",\"fromTz\":\"fromTZ\",\"toField\":\"targetField\",\"toFormat\":\"toFormat\",\"toTz\":\"toTz\",\"value\":\"fromField\",\"class\":\"DateFormatter\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; Rule rule = new Rule(); rule.setActions(new ArrayList<>()); rule.getActions().add(buildDateFormatterAction()); rule.setDescription("description"); + rule.setPhase("phase_1"); + rule.setNotifyId(""); + rule.setEntryPhase("snmp_map"); + rule.setPublishPhase("map_publish"); MappingRules mr = new MappingRules(rule); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -70,12 +101,12 @@ public class RulesBusinessLogicTest { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\"," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; MappingRules mr = new MappingRules(buildRuleWithMultipleCopyActions()); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -85,36 +116,36 @@ public class RulesBusinessLogicTest { + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\"," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; MappingRules mr = new MappingRules(buildRuleWithMultipleCopyActions()); mr.addOrReplaceRule(buildRuleWithMultipleCopyActions()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test public void emptyStringTest() throws Exception { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," - + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"map\":{\"\":\"\"},\"field\":\"\",\"toField\":\"mapTargetField\",\"default\":\"\",\"class\":\"MapAlarmValues\"}]}," - + "{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; - String ruleRequestBody = "{version:4.1,eventType:syslogFields,description:description,actions:[{actionType:map,from:{value:'\"\"'},target:mapTargetField,map:{values:[{key:'\"\"',value:'\"\"'}],haveDefault:true,default:'\"\"'}}]}"; + + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"map\":{\"\":\"\"},\"field\":\"\",\"toField\":\"mapTargetField\",\"default\":\"\",\"class\":\"MapAlarmValues\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + String ruleRequestBody = "{entryPhase:snmp_map,publishPhase:map_publish,phase:phase_1,version:4.1,eventType:syslogFields,description:description,actions:[{actionType:map,from:{value:'\"\"'},target:mapTargetField,map:{values:[{key:'\"\"',value:'\"\"'}],haveDefault:true,default:'\"\"'}}]}"; Rule myRule = gson.fromJson(ruleRequestBody, Rule.class); MappingRules mr = new MappingRules(myRule); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test public void singleStringConditionTranslationTest() throws Exception { String expectedTranslation = "{\"processing\":[{\"phase\":\"syslog_map\",\"processors\":[{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"filter\":{\"string\":\"left\",\"value\":\"right\",\"class\":\"Contains\"}," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; String input = "{operator:contains,left:left,right:[right]}"; Rule rule = buildRuleWithMultipleCopyActions(); rule.setCondition(gson.fromJson(input, BaseCondition.class)); MappingRules mr = new MappingRules(rule); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "syslog_map", "map_publish", "phase_1")); + mr.setEntryPhase("syslog_map"); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -122,12 +153,13 @@ public class RulesBusinessLogicTest { String expectedTranslation = "{\"processing\":[{\"phase\":\"foi_map\",\"processors\":[{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]}," + "{\"phase\":\"phase_1\",\"filter\":{\"filters\":[{\"string\":\"left\",\"value\":\"right1\",\"class\":\"Contains\"},{\"string\":\"left\",\"value\":\"right2\",\"class\":\"Contains\"}],\"class\":\"Or\"}," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; String input = "{operator:contains,left:left,right:[right1, right2]}"; Rule rule = buildRuleWithMultipleCopyActions(); rule.setCondition(gson.fromJson(input, BaseCondition.class)); MappingRules mr = new MappingRules(rule); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "foi_map", "map_publish", "phase_1")); + mr.setEntryPhase("foi_map"); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -135,12 +167,12 @@ public class RulesBusinessLogicTest { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"filter\":{\"field\":\"left\",\"value\":\"right\",\"class\":\"Equals\"}," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; String input = "{operator:equals,left:left,right:[right]}"; Rule rule = buildRuleWithMultipleCopyActions(); rule.setCondition(gson.fromJson(input, BaseCondition.class)); MappingRules mr = new MappingRules(rule); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -148,12 +180,12 @@ public class RulesBusinessLogicTest { String expectedTranslation = "{\"processing\":[{\"phase\":\"snmp_map\",\"processors\":[{\"array\":\"varbinds\",\"datacolumn\":\"varbind_value\",\"keycolumn\":\"varbind_oid\",\"class\":\"SnmpConvertor\"}," + "{\"phase\":\"phase_1\",\"class\":\"RunPhase\"}]},{\"phase\":\"phase_1\",\"filter\":{\"field\":\"left\",\"values\":[\"right1\",\"right2\"],\"class\":\"NotOneOf\"}," + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\",\"event.commonEventHeader.eventId\":\"${event.commonEventHeader.sourceName}_${eventGroup}\"},\"class\":\"Set\"}," - + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "{\"regex\":\"([^:]*):.*\",\"field\":\"targetField\",\"value\":\"extractFromHere\",\"class\":\"ExtractText\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; String input = "{operator:notequal,left:left,right:[right1,right2]}"; Rule rule = buildRuleWithMultipleCopyActions(); rule.setCondition(gson.fromJson(input, BaseCondition.class)); MappingRules mr = new MappingRules(rule); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr, "snmp_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(mr)); } @Test @@ -173,6 +205,66 @@ public class RulesBusinessLogicTest { } @Test + public void reorderRuleWithConditionalActionDuringValidationSuccessTest() { + Rule rule1 = buildValidRuleWithDependentSearchAndTransformActions(); + Rule rule2 = buildValidRuleWithDependentSearchAndTransformActions(); + assertEquals(rule1, rule2); + List<ServiceException> errors = rulesBusinessLogic.validateRule(rule1); + assertTrue(errors.isEmpty()); + assertNotEquals(rule1, rule2); + //after validation actions are reordered: 5, 2, 4, 1, 3 + rule2.getActions().add(0, rule2.getActions().get(4)); // 1, 2, 3, 4, 5 -> 5, 1, 2, 3, 4, 5 + rule2.getActions().remove(5); // 5, 1, 2, 3, 4, 5 -> 5, 1, 2, 3, 4 + rule2.getActions().add(1, rule2.getActions().get(2)); // 5, 1, 2, 3, 4 -> 5, 2, 1, 2, 3, 4 + rule2.getActions().remove(3); // 5, 2, 1, 2, 3, 4 -> 5, 2, 1, 3, 4 + rule2.getActions().add(2, rule2.getActions().get(4)); // 5, 2, 1, 3, 4 -> 5, 2, 4, 1, 3, 4 + rule2.getActions().remove(5); // 5, 2, 4, 1, 3, 4 -> 5, 2, 4, 1, 3 + assertEquals(rule1, rule2); + } + + @Test + public void importMappingRulesAndReorderActionsDuringImportValidationSuccessTest() { + // as this top level validator uses external ves configuration it is mocked. + // dependency validations are conducted in the class under test and verified with the control rule + when(mappingRulesValidator.validate(any(), any())).thenReturn(true); + Rule importedRule = buildValidRuleWithDependentActions(); + Rule controlRule = buildValidRuleWithDependentActions(); + MappingRules mappingRules = new MappingRules(importedRule); + // copying the generated uuid to the control rule to sustain equality + controlRule.setUid(importedRule.getUid()); + assertEquals(importedRule, controlRule); + + List<ServiceException> errors = rulesBusinessLogic.validateImportedRules(mappingRules); + assertTrue(errors.isEmpty()); + assertNotEquals(importedRule, controlRule); + //after validation actions are reordered: 1, 3, 4, 2, 5 + controlRule.getActions().add(1, controlRule.getActions().get(2)); // 1, 2, 3, 4, 5 -> 1, 3, 2, 3, 4, 5 + controlRule.getActions().remove(3); // 1, 3, 2, 3, 4, 5 -> 1, 3, 2, 4, 5 + controlRule.getActions().add(2, controlRule.getActions().get(3)); // 1, 3, 2, 4, 5 -> 1, 3, 4, 2, 4, 5 + controlRule.getActions().remove(4); // 1, 3, 4, 2, 4, 5 -> 1, 3, 4, 2, 5 + assertEquals(importedRule, controlRule); + } + + @Test + public void supportGroupDefinitionTest() { + + Rule rule = buildRuleWithMultipleCopyActions(); + List<ServiceException> errors = rulesBusinessLogic.validateRule(rule); + assertTrue(errors.isEmpty()); + MappingRules mappingRules = new MappingRules(rule); + // first rule dictates whether or not user defined phases should be supported (supportGroups = false) + assertTrue(rulesBusinessLogic.validateGroupDefinitions(mappingRules, false)); + assertFalse(rulesBusinessLogic.validateGroupDefinitions(mappingRules, true)); + // add group definitions (supportGroups = true) + rule.setGroupId("mapPhaseId"); + errors = rulesBusinessLogic.validateRule(rule); + assertTrue(errors.isEmpty()); + assertTrue(rulesBusinessLogic.validateGroupDefinitions(mappingRules, true)); + assertFalse(rulesBusinessLogic.validateGroupDefinitions(mappingRules, false)); + } + + + @Test public void reorderRuleActionsDuringValidationFailureTest() { String expectedError = "A circular dependency was detected between actions. The following fields should be resolved: event.commonEventHeader.eventId, event.commonEventHeader.sourceName, invalidSelfDependency, circularDependencyTarget_3"; Rule rule1 = buildRuleWithCircularActionDependencies(); @@ -182,22 +274,39 @@ public class RulesBusinessLogicTest { @Test - public void reorderMappingRulesByDependencySuccessTest() { - MappingRules mr = new MappingRules(buildRuleWithMultipleCopyActions()); - Rule rule = new Rule(); - rule.setDescription("description"); - rule.setActions(new ArrayList<>()); + public void reorderMappingRulesByDependencyOnlyInSamePhaseSuccessTest() { + when(mappingRulesValidator.validateTranslationPhaseNames(any(), any())).thenReturn(true); + when(mappingRulesValidator.validate(any(), any())).thenReturn(true); + Rule rule1 = buildRuleWithMultipleCopyActions(); + MappingRules mr = new MappingRules(rule1); + Rule rule2 = new Rule(); + rule2.setDescription("description"); + rule2.setActions(new ArrayList<>()); // create a dependency between rules - rule.getActions().add(buildCopyAction("${event.commonEventHeader.someField}","event.commonEventHeader.sourceName")); - mr.addOrReplaceRule(rule); + rule2.getActions().add(buildCopyAction("${event.commonEventHeader.someField}","event.commonEventHeader.sourceName")); + rule2.setPhase("phase_1"); + mr.addOrReplaceRule(rule2); + mr.setPublishPhase("map_publish"); + mr.setEntryPhase("snmp_map"); List<String> ruleUids = new ArrayList<>(mr.getRules().keySet()); - String translateBefore = rulesBusinessLogic.translateRules(mr,"snmp_map", "map_publish", "phase_1"); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + String translateBefore = rulesBusinessLogic.translateRules(mr); + //separate the rules into two phases, call import validator and translate + rule1.setGroupId("group_1"); + rule2.setGroupId("group_2"); + List<ServiceException> errors = rulesBusinessLogic.validateImportedRules(mr); + assertTrue(errors.isEmpty()); + errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); + assertTrue(errors.isEmpty()); + assertEquals(translateBefore, rulesBusinessLogic.translateRules(mr)); + //revert to single phase + rule1.setGroupId(""); + rule2.setGroupId(""); + errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); List<String> ruleUidsMod = new ArrayList<>(mr.getRules().keySet()); assertEquals(ruleUids.get(0), ruleUidsMod.get(1)); assertEquals(ruleUids.get(1), ruleUidsMod.get(0)); - assertNotEquals(translateBefore, rulesBusinessLogic.translateRules(mr,"snmp_map", "map_publish", "phase_1")); + assertNotEquals(translateBefore, rulesBusinessLogic.translateRules(mr)); } @Test @@ -213,9 +322,9 @@ public class RulesBusinessLogicTest { @Test public void reorderMappingRulesCircularDependencyFailureTest() { - + when(mappingRulesValidator.validateTranslationPhaseNames(any(), any())).thenReturn(true); MappingRules mr = new MappingRules(buildRuleWithMultipleCopyActions()); - List<ServiceException> errors = rulesBusinessLogic.validateRules(mr); + List<ServiceException> errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertTrue(errors.isEmpty()); Rule rule = new Rule(); rule.setDescription("description"); @@ -224,8 +333,9 @@ public class RulesBusinessLogicTest { rule.getActions().add(buildCopyAction("${event.commonEventHeader.version}","event.commonEventHeader.sourceName")); String input = "{operator:equals,left:\"${event.commonEventHeader.version}\",right:[\"${event.commonEventHeader.eventId}\"]}"; rule.setCondition(gson.fromJson(input, BaseCondition.class)); - assertTrue(rulesBusinessLogic.addOrEditRule(mr, rule)); - errors = rulesBusinessLogic.validateRules(mr); + rule.setPhase("phase_1"); + assertTrue(rulesBusinessLogic.addOrEditRule(mr, rule, false)); + errors = rulesBusinessLogic.validateRulesBeforeTranslate(mr); assertFalse(errors.isEmpty()); String expectedError = String.format("A circular dependency was detected between rules: %s, %s within fields: event.commonEventHeader.sourceName, event.commonEventHeader.version, event.commonEventHeader.eventId", mr.getRules().keySet().toArray()); assertEquals(expectedError, errors.get(0).getFormattedErrorMessage()); @@ -238,18 +348,21 @@ public class RulesBusinessLogicTest { + "{\"phase\":\"phase_1\",\"filter\":{\"filters\":[{\"field\":\"${event.commonEventHeader.version}\",\"value\":\"${event.commonEventHeader.eventId}\",\"class\":\"Equals\"}," + "{\"filters\":[{\"field\":\"left\",\"value\":\"right\",\"class\":\"NotEqual\"},{\"string\":\"${XXX}\",\"value\":\"right1\",\"class\":\"Contains\"}," + "{\"string\":\"${XXX}\",\"value\":\"right2\",\"class\":\"Contains\"}],\"class\":\"Or\"}],\"class\":\"And\"}," - + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\"},\"class\":\"Set\"}]},{\"phase\":\"phase_1\",\"processors\":[{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; + + "\"processors\":[{\"updates\":{\"event.commonEventHeader.version\":\"2.0\"},\"class\":\"Set\"},{\"phase\":\"map_publish\",\"class\":\"RunPhase\"}]}]}"; Rule rule = new Rule(); rule.setActions(new ArrayList<>()); rule.getActions().add(buildCopyAction("2.0","event.commonEventHeader.version")); rule.setDescription("description"); - String condition = "{type:All,children:[{operator:equals,left:\"${event.commonEventHeader.version}\",right:[\"${event.commonEventHeader.eventId}\"]}," - + "{type:Any,children:[{operator:contains,left:\"${XXX}\",right:[right1,right2]},{operator:notEqual,left:left,right:[right]}]}]}"; + String condition = "{id:123456,level:1,name:elvis,type:All,children:[{id:123456,level:1,name:elvis,operator:equals,left:\"${event.commonEventHeader.version}\",right:[\"${event.commonEventHeader.eventId}\"]}," + + "{id:123456,level:1,name:elvis,type:Any,children:[{id:123456,level:1,name:elvis,operator:contains,left:\"${XXX}\",right:[right1,right2]},{id:123456,level:1,name:elvis,operator:notEqual,left:left,right:[right]}]}]}"; rule.setCondition(gson.fromJson(condition, BaseCondition.class)); + rule.setPublishPhase("map_publish"); + rule.setEntryPhase("foi_map"); + rule.setPhase("phase_1"); List<ServiceException> errors = rulesBusinessLogic.validateRule(rule); assertTrue(errors.isEmpty()); - assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(new MappingRules(rule),"foi_map", "map_publish", "phase_1")); + assertEquals(expectedTranslation, rulesBusinessLogic.translateRules(new MappingRules(rule))); } private Rule buildRuleWithMultipleCopyActions() { @@ -260,6 +373,9 @@ public class RulesBusinessLogicTest { actions.add(buildConcatAction(Arrays.asList("${event.commonEventHeader.sourceName}","_","${eventGroup}"), "event.commonEventHeader.eventId")); actions.add(buildRegexAction("extractFromHere", "targetField", "([^:]*):.*")); rule.setActions(actions); + rule.setPhase("phase_1"); + rule.setEntryPhase("snmp_map"); + rule.setPublishPhase("map_publish"); return rule; } @@ -270,6 +386,23 @@ public class RulesBusinessLogicTest { return rule; } + private Rule buildValidRuleWithDependentSearchAndTransformActions() { + Rule rule = buildRuleWithMultipleCopyActions(); + rule.getActions().add(0, buildStringTransformAction()); + rule.getActions().add(0, buildConditionalTopoSearchAction()); + return rule; + } + + private StringTransformAction buildStringTransformAction() { + String stringTransform = "{actionType:\"string Transform\",id:76,target:searchString,stringTransform:{targetCase:same,startValue:\"${event.otherFields.otherSiteId}${targetField}${event.commonEventHeader.sourceName}\"}}"; + return gson.fromJson(stringTransform, StringTransformAction.class); + } + + private TopoSearchAction buildConditionalTopoSearchAction() { + String topoSearch = "{actionType:\"Topology Search\",id:76,search:{searchField:sourceToSearch,searchValue:\"${searchString}\",radio:'',searchFilter:{left:\"${event.commonEventHeader.eventId}\",right:[rightO],operator:OneOf},enrich:{fields:[{value:e_field1},{value:e_field2}],prefix:e_prefix}}}"; + return gson.fromJson(topoSearch, TopoSearchAction.class); + } + private Rule buildRuleWithCircularActionDependencies() { Rule rule = buildValidRuleWithDependentActions(); rule.getActions().add(buildCopyAction("${invalidSelfDependency}", "invalidSelfDependency")); @@ -282,6 +415,7 @@ public class RulesBusinessLogicTest { action.setActionType("copy"); action.setFrom(from); action.setTarget(to); + mockUiGeneratedFields(action); return action; } @@ -289,6 +423,7 @@ public class RulesBusinessLogicTest { LogTextAction logTextAction = new LogTextAction(); logTextAction.setActionType("Log Text"); logTextAction.setLogText("a name", "a level", ""); + logTextAction.setId(mockUiInput); return logTextAction; } @@ -297,6 +432,7 @@ public class RulesBusinessLogicTest { action.setActionType("concat"); action.setFrom(from); action.setTarget(to); + mockUiGeneratedFields(action); return action; } @@ -305,6 +441,7 @@ public class RulesBusinessLogicTest { action.setActionType("copy"); action.setFrom(from, regex); action.setTarget(to); + mockUiGeneratedFields(action); return action; } @@ -317,6 +454,12 @@ public class RulesBusinessLogicTest { action.setToFormat("toFormat"); action.setFromTz("fromTZ"); action.setToTz("toTz"); + mockUiGeneratedFields(action); return action; } + + private void mockUiGeneratedFields(UnaryFieldAction action) { + action.setId(mockUiInput); + action.regexState(mockUiInput); + } }
\ No newline at end of file diff --git a/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/Catalog.java b/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/Catalog.java index c9813e4..d7db9e6 100644 --- a/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/Catalog.java +++ b/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/Catalog.java @@ -1,24 +1,17 @@ package org.onap.sdc.dcae.catalog; -import java.net.URI; - -import java.util.Iterator; -import java.util.LinkedList; - +import org.json.JSONArray; import org.json.JSONObject; import org.onap.sdc.dcae.catalog.commons.Action; import org.onap.sdc.dcae.catalog.commons.Future; -import org.onap.sdc.dcae.catalog.commons.Futures; import org.onap.sdc.dcae.catalog.commons.Proxies; +import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; - -import org.json.JSONArray; +import java.util.Iterator; +import java.util.LinkedList; public interface Catalog { - - URI getUri(); - <T> T proxy(JSONObject theData, Class<T> theType); @@ -39,7 +32,7 @@ public interface Catalog { */ JSONObject data(); - /* Allows for typed deep exploration of the backing JSON data structure + /* Allows for typed deep exploration of the backing JSON data structure * @arg theName name of a JSON entry ; It must map another JSONObject. * @arg theType the expected wrapping catalog artifact type * @return the JSON entry wrapped in the specified type @@ -127,18 +120,6 @@ public interface Catalog { String itemId(); - default Future<Items> items() { - Items i = elements("items", Items.class); - if (i != null) { - return Futures.succeededFuture(i); - } - else { - return Futures.advance(catalog().folder(itemId()) - .withItems() - .execute(), - folder -> folder.elements("items", Items.class)); - } - } } class Folders extends Elements<Folder> {} @@ -234,38 +215,8 @@ public interface Catalog { Future<Type> execute(); } - interface FolderAction extends Action<Folder> { - - FolderAction withItems(); - - FolderAction withItemAnnotations(); - - FolderAction withItemModels(); - - FolderAction withParts(); - - FolderAction withPartAnnotations(); - - @Override - Future<Folder> execute(); - } - - interface ItemAction<T extends Item> extends Action<T> { - - ItemAction<T> withModels(); - - @Override - Future<T> execute(); - - } - - Future<Folders> rootsByLabel(String theLabel); - - FolderAction folder(String theFolderId); - - <T extends Item> ItemAction<T> item(String theItemId); - TemplateAction template(String theTemplateId); + TemplateAction template(ResourceDetailed resourceData); TypeAction type(String theNamespace, String theTypeName); } diff --git a/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCCatalog.java b/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCCatalog.java index dfbaeaa..8557242 100644 --- a/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCCatalog.java +++ b/dcaedt_catalog/api/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCCatalog.java @@ -5,13 +5,15 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.JXPathNotFoundException; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; import org.json.JSONObject; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.common.onaplog.OnapLoggerDebug; import org.onap.sdc.dcae.catalog.Catalog; import org.onap.sdc.dcae.catalog.commons.*; import org.onap.sdc.dcae.checker.*; +import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; +import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; +import org.springframework.stereotype.Component; import java.io.*; import java.net.URI; @@ -22,7 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; -@SuppressWarnings("ALL") +@Component public class ASDCCatalog implements Catalog { private @@ -36,40 +38,14 @@ public class ASDCCatalog implements Catalog { private static final String ITEM_ID = "itemId"; private - static final String LABELS = "labels"; - private - static final String ARTIFACT_URL = "artifactURL"; - private static final String CAPABILITY = "capability"; private - static final String DATABASE = "Database"; - private - static final String COLLECTOR = "Collector"; - private - static final String MICROSERVICE = "Microservice"; - private - static final String ANALYTICS = "Analytics"; - private - static final String POLICY = "Policy"; - private - static final String SOURCE = "Source"; - private - static final String UTILITY = "Utility"; - private static final String NAME = "name"; private static final String ID = "id"; private - static final String ARTIFACT_NAME = "artifactName"; - private static final String DESCRIPTION = "description"; private - static final String MODELS = "models"; - private - static final String ARTIFACTS = "artifacts"; - private - static final String ITEMS = "items"; - private static final String PROPERTIES = "']/properties"; private static final String TOPOLOGY_TEMPLATE_NODE_TEMPLATES1 = "/topology_template/node_templates/"; @@ -82,114 +58,26 @@ public class ASDCCatalog implements Catalog { private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - private ASDC asdc; - - private JSONObject folders = new JSONObject(); - private String[] folderFields = new String[] {ID, ITEM_ID, NAME}; - private ProxyBuilder proxies; private Map<Target, JXPathContext> contexts = new HashMap<>(); // resource and its catalog private Map<UUID, org.onap.sdc.dcae.checker.Catalog> catalogs = new HashMap<>(); - public ASDCCatalog(URI theURI) { - - this.asdc = new ASDC(); - this.asdc.setUri(theURI); - - initFolders(); - + public ASDCCatalog() { this.proxies = new ProxyBuilder().withConverter(v -> v == null ? null : UUID.fromString(v.toString()), UUID.class) .withExtensions( new ImmutableMap.Builder<String, BiFunction<Proxy, Object[], Object>>().put("data", (proxy, args) -> proxy.data()) .build()).withContext(new ImmutableMap.Builder<String, Object>().put("catalog", this).build()); } - private void initFolders() { - - JSONArray labels = new JSONArray(); - labels.put("Folder"); - labels.put("DCAE"); - labels.put("Superportfolio"); // for CCD compatibility - - folders.put(DATABASE, new JSONObject().put(NAME, DATABASE).put(ID, "dcae_database") - .put(ITEM_ID, DATABASE).put(LABELS, labels)); - folders.put(COLLECTOR, new JSONObject().put(NAME, COLLECTOR).put(ID, "dcae_collector") - .put(ITEM_ID, COLLECTOR).put(LABELS, labels)); - folders.put(MICROSERVICE, new JSONObject().put(NAME, MICROSERVICE).put(ID, "dcae_microservice") - .put(ITEM_ID, MICROSERVICE).put(LABELS, labels)); - folders.put(ANALYTICS, new JSONObject().put(NAME, ANALYTICS).put(ID, "dcae_analytics") - .put(ITEM_ID, ANALYTICS).put(LABELS, labels)); - folders.put(POLICY, new JSONObject().put(NAME, POLICY).put(ID, "dcae_policy").put(ITEM_ID, POLICY) - .put(LABELS, labels)); - folders.put(SOURCE, new JSONObject().put(NAME, SOURCE).put(ID, "dcae_source").put(ITEM_ID, SOURCE) - .put(LABELS, labels)); - folders.put(UTILITY, new JSONObject().put(NAME, UTILITY).put(ID, "dcae_utility") - .put(ITEM_ID, UTILITY).put(LABELS, labels)); - } - - public URI getUri() { - return this.asdc.getUri(); - } - - public String namespace() { - return "asdc"; - } - - public boolean same(Catalog theCatalog) { - return true; - } - public <T> T proxy(JSONObject theData, Class<T> theType) { return proxies.build(theData, theType); } - /** */ - public Future<Folders> roots() { - - Folders roots = new Folders(); - for (Iterator fi = folders.keys(); fi.hasNext();) { - roots.add(proxies.build(folders.getJSONObject((String) fi.next()), Folder.class)); - } - return Futures.succeededFuture(roots); - } - - /** */ - public Future<Folders> rootsByLabel(String theLabel) { - - Folders roots = new Folders(); - for (Iterator fi = folders.keys(); fi.hasNext();) { - JSONObject folder = folders.getJSONObject((String) fi.next()); - JSONArray labels = folder.getJSONArray(LABELS); - - for (int i = 0; i < labels.length(); i++) { - if (labels.get(i).equals(theLabel)) { - roots.add(proxies.build(folder, Folder.class)); - } - } - } - return Futures.succeededFuture(roots); - } - - public Future<Mixels> lookup(JSONObject theSelector) { - return Futures.succeededFuture(new Mixels()); - } - - public Future<Mixels> lookup(String theAnnotation, JSONObject theSelector) { - return Futures.succeededFuture(new Mixels()); - } - - public ItemAction item(String theItemId) { - return new ResourceAction(UUID.fromString(theItemId)); - } - - public CatalogFolderAction folder(String theFolderId) { - return new CatalogFolderAction(theFolderId); - } - public CatalogTemplateAction template(String theId) { - return new CatalogTemplateAction(theId); + public CatalogTemplateAction template(ResourceDetailed resource) { + return new CatalogTemplateAction(resource); } public CatalogTypeAction type(String theItemId, String theName) { @@ -229,35 +117,6 @@ public class ASDCCatalog implements Catalog { Spliterator.NONNULL | Spliterator.DISTINCT | Spliterator.IMMUTABLE), false); } - private JSONArray selectModels(JSONArray theArtifacts) { - JSONArray models = new JSONArray(); - if (theArtifacts == null) { - return models; - } - - for (int i = 0; i < theArtifacts.length(); i++) { - JSONObject artifact = theArtifacts.getJSONObject(i); - String name = artifact.optString(ARTIFACT_NAME); - if (name != null && StringUtils.containsIgnoreCase(name, "template")) { - models.put(new JSONObject().putOpt(NAME, artifact.optString(ARTIFACT_NAME)) - .putOpt("version", artifact.optString("artifactVersion")) - .putOpt(DESCRIPTION, artifact.optString("artifactType")) - .putOpt(ID, artifact.optString(ARTIFACT_URL)) - .putOpt(ITEM_ID, artifact.optString(ARTIFACT_URL))); - } - } - return models; - } - - private JSONObject patchResource(JSONObject theResource) { - - theResource.remove("resources"); - theResource.putOpt(ID, theResource.opt("uuid")); - theResource.putOpt(ITEM_ID, theResource.opt("uuid")); - - return theResource; - } - private static void dumpTargets(String theDirName, Collection<Target> theTargets) { File targetDir = new File(theDirName); if (!targetDir.exists() && !targetDir.mkdirs()) { @@ -285,180 +144,17 @@ public class ASDCCatalog implements Catalog { return UUID.fromString(theValue); } - private org.onap.sdc.dcae.checker.Catalog getCatalog(UUID theResourceId) { + private org.onap.sdc.dcae.checker.Catalog getCachedCatalogItem(UUID theResourceId) { return this.catalogs.get(theResourceId); } - private String getArtifactVersion(JSONObject theData) { - return theData.getString("artifactVersion"); - } - - private String getArtifactName(JSONObject theData) { - return theData.getString(ARTIFACT_NAME); - } - - private String getArtifactURL(JSONObject theData) { - return theData.getString(ARTIFACT_URL); - } - - private URI getArtifactURI(JSONObject theData) { - return asURI(theData.getString(ARTIFACT_URL)); - } - - /** */ - public class ResourceAction implements Catalog.ItemAction<Resource> { - - private UUID iid; - private boolean doModels; - - ResourceAction(UUID theItemId) { - this.iid = theItemId; - } - - public ResourceAction withModels() { - this.doModels = true; - return this; - } - - public ResourceAction withAnnotations() { - return this; - } - - @Override - public Future<Resource> execute() { - - return Futures.advance(asdc.getResource(this.iid, JSONObject.class), resourceData -> { - if (doModels) { - resourceData.put(MODELS, selectModels(resourceData.optJSONArray(ARTIFACTS))); - } - return proxies.build(patchResource(resourceData), Resource.class); - }); - } - - protected Future<JSONObject> executeRaw() { - - return Futures.advance(asdc.getResource(this.iid, JSONObject.class), resourceData -> { - if (doModels) { - resourceData.put(MODELS, selectModels(resourceData.optJSONArray(ARTIFACTS))); - } - return resourceData; - }, resourceError -> new RuntimeException("Failed to retrieve item " + this.iid, resourceError)); - } - } - - public class CatalogFolderAction implements Catalog.FolderAction { - - private boolean doItemModels; - private String folderName; + public boolean hasCachedItem(String uuid) { + return this.catalogs.containsKey(asUUID(uuid)); + } - // use the id/UUID of the folder ?? - private CatalogFolderAction(String theFolderName) { - this.folderName = theFolderName; - } - - public CatalogFolderAction withAnnotations() { - return this; - } - - public CatalogFolderAction withAnnotations(String theSelector) { - return this; - } - - public CatalogFolderAction withItems() { - return this; - } - - public CatalogFolderAction withItemAnnotations() { - return this; - } - - public CatalogFolderAction withItemAnnotations(String theSelector) { - return this; - } - - public CatalogFolderAction withItemModels() { - doItemModels = true; - return this; - } - - public CatalogFolderAction withParts() { - return this; - } - - public CatalogFolderAction withPartAnnotations() { - return this; - } - - public CatalogFolderAction withPartAnnotations(String theSelector) { - return this; - } - - @Override - public Future<Folder> execute() { - - JSONObject folder = folders.optJSONObject(this.folderName); - if (folder == null) { - return Futures.failedFuture(new RuntimeException("No such folder " + this.folderName)); - } - - final JSONObject folderView = new JSONObject(folder, folderFields); - - return Futures.advance(asdc.getResources(JSONArray.class, "DCAE Component", this.folderName), - resourcesData -> { - - Actions.CompoundAction<Resource> itemsAction = new Actions.BasicCompoundAction<>(); - for (int i = 0; i < resourcesData.length(); i++) { - JSONObject resource = resourcesData.getJSONObject(i); - - if (doItemModels) { - itemsAction - .addAction(new ResourceAction(asUUID(resource.getString("uuid"))).withModels()); - } else { - folderView.append(ITEMS, patchResource(resource)); - } - } - - try { - List<Resource> items = itemsAction.execute().waitForResult(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Number of DCAE item for : {} is {}", this.folderName, items.size()); - - for (Resource res : filterLatestVersion(items)) { - folderView.append(ITEMS, patchResource(res.data())); - } - } catch (Exception x) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Exception {}", x); - throw new RuntimeException("Failed to retrieve folder items", x); - } - - return proxies.build(folderView, Folder.class); - }, resourcesError -> new RuntimeException("Failed to retrieve resources", resourcesError)); - } - - public Collection<Resource> filterLatestVersion(Collection<Resource> items) { - if (items == null) { - throw new IllegalArgumentException("null is not acceptable as a list of items"); - } - Map<UUID, Resource> itemsMap = new HashMap<UUID, Resource>(items.size()); - for (Resource r : items) { - if (itemsMap.containsKey(r.invariantUUID()) && isNewerVersion(itemsMap, r)) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Avoiding adding item {} since it has a advanced version already", r.toString()); - continue; - } - itemsMap.put(r.invariantUUID(), r); - } - return itemsMap.values(); - } - - private boolean isNewerVersion(Map<UUID, Resource> itemsMap, Resource r) { - return Float.valueOf(itemsMap.get(r.invariantUUID()).version()) > Float.valueOf(r.version()); - } - - } - - /** */ public class CatalogTemplateAction implements Catalog.TemplateAction { - private String artifactId; + private ResourceDetailed resourceMetadata; private Target target; private org.onap.sdc.dcae.checker.Catalog catalog; private JXPathContext ctx = JXPathContext.newContext(new HashMap()); @@ -466,13 +162,10 @@ public class ASDCCatalog implements Catalog { private boolean doNodes, doNodeProperties, doNodePropertiesAssignments, doNodeRequirements, doNodeCapabilities, doNodeCapabilityProperties, doNodeCapabilityPropertyAssignments; - /* - * expected to be the relative url provided by asdc for the template - * artifact - */ - CatalogTemplateAction(String theArtifactId) { - this.artifactId = theArtifactId; - } + + CatalogTemplateAction(ResourceDetailed resourceMetadata) { + this.resourceMetadata = resourceMetadata; + } public CatalogTemplateAction withInputs() { return this; @@ -500,7 +193,7 @@ public class ASDCCatalog implements Catalog { ctx.setValue("/nodes", nodes.entrySet().stream() .map(nodeEntry -> new MapBuilder().put(NAME, ((Map.Entry) nodeEntry).getKey()) - .put(DESCRIPTION, this.artifactId) + .put(DESCRIPTION, resourceMetadata.getToscaModelURL()) .putAll(selectEntries((Map) ((Map.Entry) nodeEntry).getValue(), "type")).build()) .collect(Collectors.toList())); @@ -852,29 +545,20 @@ public class ASDCCatalog implements Catalog { if (this.target == null) { - String[] parts = this.artifactId.split("/"); - if (parts.length != 8) { - return Futures - .failedFuture(new Exception("Unexpected artifact id for template " + this.artifactId)); - } - - UUID resourceId = asUUID(parts[5]); + UUID resourceId = asUUID(resourceMetadata.getUuid()); this.catalog = ASDCCatalog.this.catalogs.get(resourceId); // if we find a catalog for this resource we have to figure out // if it contains the required target .. try { - JSONObject resource = new ResourceAction(resourceId).executeRaw().waitForResult(); Checker checker = new Checker(); - TargetLocator locator = new ASDCLocator(resource.getJSONArray(ARTIFACTS), - ASDCCatalog.this.catalogs.get(resourceId)); + TargetLocator locator = new ASDCLocator(resourceMetadata.getArtifacts(), ASDCCatalog.this.catalogs.get(resourceId)); checker.setTargetLocator(locator); - Target template = locator.resolve("template"); if (template == null) { - return Futures.failedFuture(new Exception("Failed to locate template in " + resource)); + return Futures.failedFuture(new Exception("Failed to locate template in " + resourceMetadata)); } checker.check(template); @@ -902,8 +586,8 @@ public class ASDCCatalog implements Catalog { .doNodeCapabilityProperties().doNodeCapabilityPropertyAssignments(); JSONObject pack = new JSONObject((Map) ctx.getContextBean()).put(NAME, this.target.getName()) - .put(ID, this.target.getLocation().toString()) - .put(ITEM_ID, this.target.getLocation().toString()); + .put(ID, resourceMetadata.getUuid()) + .put(ITEM_ID, resourceMetadata.getToscaModelURL()); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), pack.toString(2)); return Futures.succeededFuture(proxies.build(pack, Template.class)); @@ -918,7 +602,7 @@ public class ASDCCatalog implements Catalog { private boolean doHierarchy = false, doRequirements = false, doCapabilities = false; - private CatalogTypeAction(UUID theResourceId, /* Construct theConstruct, */ String theName) { + private CatalogTypeAction(UUID theResourceId, String theName) { this.resourceId = theResourceId; this.name = theName; } @@ -967,7 +651,7 @@ public class ASDCCatalog implements Catalog { // the type reference, else it is a name // (within a node type) .put(ID, - getCatalog(resourceId).hasType(Construct.Capability, capability) + getCachedCatalogItem(resourceId).hasType(Construct.Capability, capability) ? (resourceId + "/" + capability) : capability) .build()) .put("node", new MapBuilder().putOpt(NAME, node).putOpt(ID, node == null ? null @@ -1010,9 +694,6 @@ public class ASDCCatalog implements Catalog { .putOpt("validSourceTypes", ((Map) capability.getValue()).get("validSourceTypes")) .build() - // renderEntry((Map.Entry)capability, - // "occurrences", - // "validSourceTypes") ).collect(Collectors.toList())); return this; } @@ -1042,60 +723,12 @@ public class ASDCCatalog implements Catalog { } } - public interface Resource extends Catalog.Item<Resource> { - - @Override - @Proxy.DataMap(map = "uuid") - public String id(); - - public UUID uuid(); - - public UUID invariantUUID(); - - public String category(); - - public String subCategory(); - - public String lastUpdaterFullName(); - - public String version(); - - @Proxy.DataMap(proxy = true, elementType = Artifact.class) - public Artifacts artifacts(); - - } - - public static class Resources extends Elements<Resource> { - } - - public interface Artifact extends Catalog.Element<Artifact> { - - @Proxy.DataMap(map = ARTIFACT_NAME) - String name(); - - @Proxy.DataMap(map = "artifactType") - String type(); - - @Proxy.DataMap(map = "artifactDescription") - String description(); - - @Proxy.DataMap(map = "artifactUUID") - UUID uuid(); - - @Proxy.DataMap(map = "artifactVersion") - int version(); - - } - - public static class Artifacts extends Elements<Artifact> { - } - public class ASDCLocator implements TargetLocator { - private JSONArray artifacts; + private List<Artifact> artifacts; private org.onap.sdc.dcae.checker.Catalog catalog; - private ASDCLocator(JSONArray theArtifacts, org.onap.sdc.dcae.checker.Catalog theCatalog) { + private ASDCLocator(List<Artifact> theArtifacts, org.onap.sdc.dcae.checker.Catalog theCatalog) { this.artifacts = theArtifacts; this.catalog = theCatalog; } @@ -1113,15 +746,8 @@ public class ASDCCatalog implements Catalog { } public Target resolve(String theName) { - JSONObject targetArtifact = null; - for (int i = 0; i < this.artifacts.length(); i++) { - JSONObject artifact = this.artifacts.getJSONObject(i); - String artifactName = artifact.getString(ARTIFACT_NAME); - if (StringUtils.containsIgnoreCase(artifactName, theName)) { - targetArtifact = artifact; - } - } + Artifact targetArtifact = this.artifacts.stream().filter(a -> StringUtils.containsIgnoreCase(a.getArtifactName(), theName)).findAny().orElse(null); if (targetArtifact == null) { return null; @@ -1130,8 +756,8 @@ public class ASDCCatalog implements Catalog { ASDCTarget target; if (this.catalog != null) { // this is the caching!! - target = (ASDCTarget) this.catalog.getTarget(ASDCCatalog.this.getArtifactURI(targetArtifact)); - if (target != null && target.getVersion().equals(ASDCCatalog.this.getArtifactVersion(targetArtifact))) { + target = (ASDCTarget) this.catalog.getTarget(asURI(targetArtifact.getArtifactURL())); + if (target != null) { return target; } } @@ -1142,11 +768,10 @@ public class ASDCCatalog implements Catalog { public class ASDCTarget extends Target { - private String content; - private JSONObject artifact; + private Artifact artifact; - private ASDCTarget(JSONObject theArtifact) { - super(ASDCCatalog.this.getArtifactName(theArtifact), ASDCCatalog.this.getArtifactURI(theArtifact)); + private ASDCTarget(Artifact theArtifact) { + super(theArtifact.getArtifactName(), asURI(theArtifact.getArtifactURL())); this.artifact = theArtifact; } @@ -1156,53 +781,8 @@ public class ASDCCatalog implements Catalog { @Override public Reader open() throws IOException { - if (this.content == null) { - try { - this.content = ASDCCatalog.this.asdc - .fetch(ASDCCatalog.this.getArtifactURL(this.artifact), String.class).waitForResult(); - } catch (Exception x) { - throw new IOException("Failed to load " + ASDCCatalog.this.getArtifactURL(this.artifact), x); - } - } - - // should return immediately a reader blocked until content - // available .. hard to handle errors - return new StringReader(this.content); - } - - public String getVersion() { - return ASDCCatalog.this.getArtifactVersion(this.artifact); + return new StringReader(this.artifact.getPayloadData()); } } - - public static void main(String[] theArgs) throws Exception { - - ASDCCatalog catalog = new ASDCCatalog(new URI(theArgs[0])); - - Folder f = catalog.folder(theArgs[1]).withItems().withItemModels().execute().waitForResult(); - - debugLogger.log(LogLevel.DEBUG, ASDCCatalog.class.getName(), "folder: {}", f.data()); - - Resources items = f.elements(ITEMS, Resources.class); - if (items != null) { - for (Resource item : items) { - executeItemsNodePropertiesAssignments(catalog, item); - } - } - } - - private static void executeItemsNodePropertiesAssignments(ASDCCatalog catalog, Resource item) throws Exception { - debugLogger.log(LogLevel.DEBUG, ASDCCatalog.class.getName(), "\titem: {} : {}",item.name(), item.data()); - Templates templates = item.elements(MODELS, Templates.class); - if (templates != null) { - for (Template t : templates) { - Template ft = catalog.template(t.id()).withNodes().withNodeProperties() - .withNodePropertiesAssignments().execute().waitForResult(); - - debugLogger.log(LogLevel.DEBUG, ASDCCatalog.class.getName(), "template data: {}", ft.data()); - } - } - } - } diff --git a/dcaedt_catalog/api/src/test/java/org/onap/sdc/dcae/catalog/ASDCCatalogTest.java b/dcaedt_catalog/api/src/test/java/org/onap/sdc/dcae/catalog/ASDCCatalogTest.java deleted file mode 100644 index 360b76d..0000000 --- a/dcaedt_catalog/api/src/test/java/org/onap/sdc/dcae/catalog/ASDCCatalogTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.onap.sdc.dcae.catalog; - -import static org.assertj.core.api.Assertions.*; - -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.UUID; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.onap.sdc.dcae.catalog.asdc.ASDCCatalog; -import org.onap.sdc.dcae.catalog.asdc.ASDCCatalog.CatalogFolderAction; -import org.onap.sdc.dcae.catalog.asdc.ASDCCatalog.Resource; - -import static org.mockito.Mockito.*; - - -public class ASDCCatalogTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private static CatalogFolderAction getTarget() { - ASDCCatalog catalog = mock(ASDCCatalog.class); - when(catalog.folder("test")).thenCallRealMethod(); - CatalogFolderAction target = catalog.folder("test"); - return target; - } - - @Test - public void filterLatestVersion_null_throwIllegalArgumentException() { - // arrange - CatalogFolderAction target = getTarget(); - // assert - thrown.expect(IllegalArgumentException.class); - // act - target.filterLatestVersion(null); - } - - @Test - public void filterLatestVersion_emptyItemsList_emptyItemsList() throws URISyntaxException { - // arrange - CatalogFolderAction target = getTarget(); - // act - Collection<Resource> result = target.filterLatestVersion(new ArrayList<>()); - // assert - assertThat(result).isEmpty(); - } - - @Test - public void filterLatestVersion_itemWithTwoVersions_itemWithLatestVersion() { - // arrange - CatalogFolderAction target = getTarget(); - - UUID invariantUUID = UUID.randomUUID(); - Resource r1v1 = mock(Resource.class); - Resource r1v2 = mock(Resource.class); - when(r1v1.invariantUUID()).thenReturn(invariantUUID); - when(r1v2.invariantUUID()).thenReturn(invariantUUID); - when(r1v1.version()).thenReturn("1.0"); - when(r1v2.version()).thenReturn("2.0"); - ArrayList<Resource> listItemWithTwoVersions = new ArrayList<Resource>(Arrays.asList(r1v1, r1v2)); - // act - Collection<Resource> result = target.filterLatestVersion(listItemWithTwoVersions); - // assert - assertThat(result).containsExactly(r1v2); - } - - @Test - public void filterLatestVersion_2distinctItems_2distinctItems() { - // arrange - CatalogFolderAction target = getTarget(); - - Resource r1 = mock(Resource.class); - Resource r2 = mock(Resource.class); - when(r1.invariantUUID()).thenReturn(UUID.randomUUID()); - when(r2.invariantUUID()).thenReturn(UUID.randomUUID()); - ArrayList<Resource> listOfTwoDistinctItems = new ArrayList<Resource>(Arrays.asList(r1, r2)); - // act - Collection<Resource> result = target.filterLatestVersion(listOfTwoDistinctItems); - // assert - assertThat(result).containsExactlyInAnyOrder(r1, r2); - } - -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDC.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDC.java deleted file mode 100644 index c704689..0000000 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDC.java +++ /dev/null @@ -1,288 +0,0 @@ -package org.onap.sdc.dcae.catalog.asdc; - -import org.apache.commons.codec.digest.DigestUtils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.common.onaplog.OnapLoggerError; -import org.onap.sdc.dcae.catalog.commons.Action; -import org.onap.sdc.dcae.catalog.commons.Future; -import org.onap.sdc.dcae.catalog.commons.Futures; -import org.onap.sdc.dcae.catalog.commons.JSONHttpMessageConverter; -import org.springframework.context.annotation.Scope; -import org.springframework.http.*; -import org.springframework.http.client.AsyncClientHttpRequestExecution; -import org.springframework.http.client.AsyncClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import org.springframework.util.Base64Utils; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; -import org.springframework.web.client.AsyncRestTemplate; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestClientException; - -import javax.annotation.PostConstruct; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -@Component("asdc") -@Scope("singleton") -public class ASDC { - - public enum AssetType { - resource, - service, - product - } - - protected static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - protected static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - private URI rootUri; - private String rootPath = "/sdc/v1/catalog/"; - private String user, passwd; - private String instanceId; - - public void setUri(URI theUri) { - String userInfo = theUri.getUserInfo(); - if (userInfo != null) { - String[] userInfoParts = userInfo.split(":"); - setUser(userInfoParts[0]); - if (userInfoParts.length > 1) { - setPassword(userInfoParts[1]); - } - } - String fragment = theUri.getFragment(); - if (fragment == null) { - throw new IllegalArgumentException("The URI must contain a fragment specification, to be used as ASDC instance id"); - } - setInstanceId(fragment); - - try { - this.rootUri = new URI(theUri.getScheme(), null, theUri.getHost(), theUri.getPort(), theUri.getPath(), theUri.getQuery(), null); - } - catch (URISyntaxException urix) { - throw new IllegalArgumentException("Invalid uri", urix); - } - } - - public URI getUri() { - return this.rootUri; - } - - public void setUser(String theUser) { - this.user = theUser; - } - - public String getUser() { - return this.user; - } - - public void setPassword(String thePassword) { - this.passwd = thePassword; - } - - public String getPassword() { - return this.passwd; - } - - public void setInstanceId(String theId) { - this.instanceId = theId; - } - - @Scheduled(fixedRateString = "${beans.context.scripts.updateCheckFrequency?:60000}") - public void checkForUpdates() { - // ffu - } - - @PostConstruct - public void initASDC() { - // ffu - } - - public <T> Future<T> getResources(Class<T> theType) { - return getAssets(AssetType.resource, theType); - } - - public Future<JSONArray> getResources() { - return getAssets(AssetType.resource, JSONArray.class); - } - - public <T> Future<T> getResources(Class<T> theType, String theCategory, String theSubCategory) { - return getAssets(AssetType.resource, theType, theCategory, theSubCategory); - } - - public Future<JSONArray> getResources(String category, String subCategory, String resourceType) { - return getAssets(AssetType.resource, JSONArray.class, category, subCategory, resourceType); - } - - public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType) { - return fetch(refAssets(theAssetType), theType); - } - - public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType, - String theCategory, String theSubCategory) { - return getAssets(theAssetType, theType, theCategory, theSubCategory, null); - } - - public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType, - String theCategory, String theSubCategory, String theResourceType) { - return fetch(refAssets(theAssetType) + filter(theCategory, theSubCategory, theResourceType), theType); - } - - protected String refAssets(AssetType theAssetType) { - return this.rootPath + theAssetType + "s/"; - } - - private String filter(String theCategory, String theSubCategory, String theResourceType) { - StringBuilder filter = null; - if (theCategory != null) { - filter = new StringBuilder(); - filter.append("?category=") - .append(theCategory); - if (theSubCategory != null) { - filter.append("&subCategory=") - .append(theSubCategory); - if (theResourceType != null) { - filter.append("&resourceType=") - .append(theResourceType); - } - } - } - return filter == null ? "" : filter.toString(); - } - - protected String refAsset(AssetType theAssetType, UUID theId) { - return this.rootPath + theAssetType + "s/" + theId; - } - - public <T> Future<T> getResource(UUID theId, Class<T> theType) { - return getAsset(AssetType.resource, theId, theType); - } - - public Future<JSONObject> getResource(UUID theId) { - return getAsset(AssetType.resource, theId, JSONObject.class); - } - - public <T> Future<T> getAsset(AssetType theAssetType, UUID theId, Class<T> theType) { - return fetch(refAsset(theAssetType, theId) + "/metadata", theType); - } - - public <T> Action<T> getAssetAction(AssetType theAssetType, UUID theId, Class<T> theType) { - return () -> fetch(refAsset(theAssetType, theId) + "/metadata", theType); - } - - public Future<byte[]> getAssetArchive(AssetType theAssetType, UUID theId) { - return fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class); - } - - public Action<byte[]> getAssetArchiveAction(AssetType theAssetType, UUID theId) { - return () -> fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class); - } - - protected String refAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId) { - return refAsset(theAssetType, theAssetId) + "/artifacts" + (theArtifactId == null ? "" : ("/" + theArtifactId)); - } - - public <T> Future<T> getResourceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) { - return getAssetArtifact(AssetType.resource, theAssetId, theArtifactId, theType); - } - - public <T> Future<T> getAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId, Class<T> theType) { - return fetch(refAssetArtifact(theAssetType, theAssetId, theArtifactId), theType); - } - - - public static JSONObject merge(JSONObject theOriginal, JSONObject thePatch) { - for (String key: (Set<String>)thePatch.keySet()) { - if (!theOriginal.has(key)) { - theOriginal.put(key, thePatch.get(key)); - } - } - return theOriginal; - } - - private HttpHeaders prepareHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((this.user + ":" + this.passwd).getBytes())); - headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); - headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE); - headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); - headers.add("X-ECOMP-InstanceID", this.instanceId); - - return headers; - } - - public <T> Future<T> fetch(String theRef, Class<T> theContentType) { - return exchange(theRef, HttpMethod.GET, new HttpEntity(prepareHeaders()), theContentType); - } - - public <T> Future<T> exchange(String theRef, HttpMethod theMethod, HttpEntity theRequest, Class<T> theResponseType) { - - AsyncRestTemplate restTemplate = new AsyncRestTemplate(); - - List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters(); - converters.add(0, new JSONHttpMessageConverter()); - restTemplate.setMessageConverters(converters); - - restTemplate.setInterceptors(Collections.singletonList(new ContentMD5Interceptor())); - ASDCFuture<T> result = new ASDCFuture<T>(); - String uri = this.rootUri + theRef; - try { - restTemplate - .exchange(uri, theMethod, theRequest, theResponseType) - .addCallback(result.callback); - } - catch (RestClientException rcx) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "Failed to fetch {} {}", uri, rcx); - return Futures.failedFuture(rcx); - } - catch (Exception x) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "Failed to fetch {} {}", uri, x); - return Futures.failedFuture(x); - } - - return result; - } - - public class ASDCFuture<T> extends Futures.BasicFuture<T> { - - ListenableFutureCallback<ResponseEntity<T>> callback = new ListenableFutureCallback<ResponseEntity<T>>() { - - public void onSuccess(ResponseEntity<T> theResult) { - ASDCFuture.this.result(theResult.getBody()); - } - - public void onFailure(Throwable theError) { - if (theError instanceof HttpClientErrorException) { - ASDCFuture.this.cause(new ASDCException((HttpClientErrorException)theError)); - } - else { - ASDCFuture.this.cause(theError); - } - } - }; - } - - public class ContentMD5Interceptor implements AsyncClientHttpRequestInterceptor { - @Override - public ListenableFuture<ClientHttpResponse> intercept( - HttpRequest theRequest, byte[] theBody, AsyncClientHttpRequestExecution theExecution) - throws IOException { - if (HttpMethod.POST == theRequest.getMethod()) { - HttpHeaders headers = theRequest.getHeaders(); - headers.add("Content-MD5", Base64Utils.encodeToString(DigestUtils.md5Hex(theBody).getBytes())); - } - return theExecution.executeAsync(theRequest, theBody); - } - } -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCEngine.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCEngine.java deleted file mode 100644 index 73c7601..0000000 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCEngine.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.onap.sdc.dcae.catalog.asdc; - -import org.onap.sdc.dcae.composition.util.SystemProperties; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -@SpringBootApplication -public class ASDCEngine { - - /** - * Creates and returns a new instance of a {@link SystemProperties} class. - * - * @return New instance of {@link SystemProperties}. - */ - @Bean - public SystemProperties systemProperties() { - return new SystemProperties(); - } - - public static void main(String[] args) { - SpringApplication.run(ASDCEngine.class, args); - } - -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtils.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtils.java deleted file mode 100644 index a3ea63d..0000000 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtils.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.onap.sdc.dcae.catalog.asdc; - -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.common.onaplog.OnapLoggerError; -import org.onap.sdc.dcae.catalog.commons.Actions; -import org.onap.sdc.dcae.catalog.commons.Future; -import org.onap.sdc.dcae.catalog.commons.Futures; -import org.onap.sdc.dcae.catalog.commons.Recycler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; -import org.springframework.util.Base64Utils; - -import java.io.*; -import java.net.URI; -import java.util.List; -import java.util.Spliterators; -import java.util.UUID; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - - -@Component("asdcutils") -@Scope("singleton") -@ConfigurationProperties(prefix="asdcutils") -public class ASDCUtils { - - private static final String ARTIFACT_URL = "artifactURL"; - private static final String ARTIFACT_NAME = "artifactName"; - private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - @Autowired - private ASDC asdc; - - @Autowired - private Blueprinter blueprint; - - public ASDCUtils() { - // Making sonar happy - } - - public ASDCUtils(URI theASDCURI) { - this(theASDCURI, null); - } - - public ASDCUtils(URI theASDCURI, URI theBlueprinterURI) { - this.asdc = new ASDC(); - this.asdc.setUri(theASDCURI); - if (theBlueprinterURI != null) { - this.blueprint = new Blueprinter(); - this.blueprint.setUri(theBlueprinterURI); - } - } - - public ASDCUtils(ASDC theASDC) { - this(theASDC, null); - } - - public ASDCUtils(ASDC theASDC, Blueprinter theBlueprinter) { - this.asdc = theASDC; - this.blueprint = theBlueprinter; - } - - - private static JSONObject lookupArtifactInfo(JSONArray theArtifacts, String theName) { - - for (int i = 0; theArtifacts != null && i < theArtifacts.length(); i++) { - JSONObject artifactInfo = theArtifacts.getJSONObject(i); - if (theName.equals(artifactInfo.getString(ARTIFACT_NAME))) { - debugLogger.log(LogLevel.DEBUG, ASDCUtils.class.getName(), "Found artifact info {}", artifactInfo); - return artifactInfo; - } - } - - return null; - } - - private static byte[] extractArtifactData(InputStream theEntryStream) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - byte[] buff = new byte[4096]; - int cnt = 0; - while ((cnt = theEntryStream.read(buff)) != -1) { - baos.write(buff, 0, cnt); - } - } finally { - baos.close(); - } - return baos.toByteArray(); - } - - - public Future<Future<String>> buildBlueprintViaToscaLab(Reader theCdump) { - return processCdump(theCdump, (theTemplate, theArchives) -> { - Blueprinter.BlueprintAction action = blueprint.generateBlueprint(); - processArtifacts(theArchives, (JSONObject theInfo, byte[] theData) -> new JSONObject().put(theInfo.getString(ARTIFACT_NAME).split("\\.")[0], Base64Utils.encodeToString(theData)), - (Stream<JSONObject> theAssetArtifacts) -> theAssetArtifacts.reduce(new JSONObject(), ASDC::merge)).forEach(artifactInfo -> action.withModelInfo(artifactInfo)); - - return action.withTemplateData(Recycler.toString(theTemplate).getBytes()).execute(); - - }); - } - - /* The common process of recycling, retrieving all related artifacts and then doing 'something' */ - private <T> Future<T> processCdump(Reader theCdump, BiFunction<Object, List, T> theProcessor) { - - final Recycler recycler = new Recycler(); - Object template = null; - try { - template = recycler.recycle(theCdump); - - } catch (Exception x) { - return Futures.failedFuture(x); - } - - JXPathContext jxroot = JXPathContext.newContext(template); - jxroot.setLenient(true); - - //based on the output of ASDCCatalog the node description will contain the UUID of the resource declaring it - //the desc contains the full URI and the resource uuid is the 5th path element - List uuids = (List) StreamSupport.stream(Spliterators.spliteratorUnknownSize(jxroot.iterate("topology_template/node_templates/*/description"), 16), false).distinct().filter(desc -> desc != null) - .map(desc -> desc.toString().split("/")[5]).collect(Collectors.toList()); - - //serialized fetch version - final Actions.Sequence sequencer = new Actions.Sequence(); - uuids.stream().forEach(uuid -> { - UUID rid = UUID.fromString((String) uuid); - sequencer.add(this.asdc.getAssetArchiveAction(ASDC.AssetType.resource, rid)); - sequencer.add(this.asdc.getAssetAction(ASDC.AssetType.resource, rid, JSONObject.class)); - }); - - final Object tmpl = template; - return Futures.advance(sequencer.execute(), (List theArchives) -> theProcessor.apply(tmpl, theArchives)); - } - - private static <T> Stream<T> processArtifacts(List theArtifactData, BiFunction<JSONObject, byte[], T> theProcessor, Function<Stream<T>, T> theAggregator) { - - Stream.Builder<T> assetBuilder = Stream.builder(); - - for (int i = 0; i < theArtifactData.size(); i = i + 2) { //cute old style loop - - JSONObject assetInfo = (JSONObject) theArtifactData.get(i + 1); - byte[] assetData = (byte[]) theArtifactData.get(i + 0); - - JSONArray artifacts = assetInfo.optJSONArray("artifacts"); - - Stream.Builder<T> artifactBuilder = Stream.builder(); - - try (ZipInputStream zipper = new ZipInputStream(new ByteArrayInputStream(assetData))){ - //we process the artifacts in the order they are stored in the archive .. fugly - processZipArtifacts(theProcessor, artifacts, artifactBuilder, zipper); - } catch (IOException iox) { - errLogger.log(LogLevel.ERROR, ASDC.class.getName(), "IOException: {}", iox); - return null; - } - - if (theAggregator != null) { - assetBuilder.add(theAggregator.apply(artifactBuilder.build())); - } else { - artifactBuilder.build().forEach(entry -> assetBuilder.add(entry)); - } - } - - return assetBuilder.build(); - } - - private static <T> void processZipArtifacts(BiFunction<JSONObject, byte[], T> theProcessor, JSONArray artifacts, Stream.Builder<T> artifactBuilder, ZipInputStream zipper) throws IOException { - for (ZipEntry zipped = zipper.getNextEntry(); zipped != null; zipped = zipper.getNextEntry()) { - JSONObject artifactInfo = lookupArtifactInfo(artifacts, StringUtils.substringAfterLast(zipped.getName(), "/")); - if (artifactInfo != null) { - artifactBuilder.add(theProcessor.apply(artifactInfo, extractArtifactData(zipper))); - } - zipper.closeEntry(); - } - } -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtilsController.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtilsController.java deleted file mode 100644 index 377e71b..0000000 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/ASDCUtilsController.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.onap.sdc.dcae.catalog.asdc; - -import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.springframework.beans.BeansException; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - - -@RestController -@ConfigurationProperties(prefix="asdcUtilsController") -public class ASDCUtilsController implements ApplicationContextAware { - - private OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - public void setApplicationContext(ApplicationContext theCtx) throws BeansException { - // no use for app context - } - - @PostConstruct - public void initController() { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"initASDCUtilsController"); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"ASDCUtilsController started"); - } - - @PreDestroy - public void cleanupController() { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(),"cleanupASDCUtilsController"); - } - -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/Blueprinter.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/Blueprinter.java deleted file mode 100644 index 4e5349f..0000000 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/catalog/asdc/Blueprinter.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.onap.sdc.dcae.catalog.asdc; - -import java.net.URI; - -import java.util.Collections; - -import org.json.JSONObject; -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.dcae.catalog.commons.Action; -import org.onap.sdc.dcae.catalog.commons.Future; -import org.onap.sdc.dcae.catalog.commons.Http; - -import org.springframework.util.Base64Utils; - -import org.springframework.http.MediaType; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpEntity; -import org.springframework.stereotype.Component; -import org.springframework.context.annotation.Scope; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@Component("blueprinter") -@Scope("singleton") -@ConfigurationProperties(prefix="blueprinter") -public class Blueprinter { - private URI serviceUri; - private OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - public void setUri(URI theUri) { - this.serviceUri = theUri; - } - - public BlueprintAction generateBlueprint() { - return new BlueprintAction(); - } - - public class BlueprintAction implements Action<String> { - - private JSONObject body = new JSONObject(); - - protected BlueprintAction() { - } - - public BlueprintAction withModelInfo(JSONObject theModelInfo) { - body.append("models", theModelInfo); - return this; - } - - public BlueprintAction withTemplateData(byte[] theData) { - body.put("template", Base64Utils.encodeToString(theData)); - return this; - } - - public Future<String> execute() { - - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Blueprinter::execute() | PAYLOAD to TOSCA_LAB={}", body.toString()); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - return Http.exchange(serviceUri.toString(), HttpMethod.POST, new HttpEntity<>(body.toString(), headers), String.class); - } - } -} diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/ISdcClient.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/ISdcClient.java index c389d75..9623d4c 100644 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/ISdcClient.java +++ b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/ISdcClient.java @@ -11,7 +11,9 @@ public interface ISdcClient { ResourceDetailed getResource(String uuid, String requestId); - ServiceDetailed getService(String uuid, String requestId); + byte[] getResourceToscaModel(String uuid, String requestId); + + ServiceDetailed getService(String uuid, String requestId); ServiceDetailed getAssetMetadata(String contextType, String uuid, String requestId); diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/SdcRestClient.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/SdcRestClient.java index b07126e..7b89465 100644 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/SdcRestClient.java +++ b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/client/SdcRestClient.java @@ -52,6 +52,7 @@ public class SdcRestClient implements ISdcClient { private static final String LIFECYCLE_STATE_PATH = "lifecycleState/{lifecycleOperation}"; private static final String METADATA_PATH = "metadata"; private static final String VERSION_PATH = "version"; + private static final String CSAR_PATH = "toscaModel"; private static final String MONITORING_REFERENCES_PATH = "externalReferences/monitoring"; private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); @@ -93,6 +94,12 @@ public class SdcRestClient implements ISdcClient { return getObject(url, requestId, ResourceDetailed.class); } + public byte[] getResourceToscaModel(String uuid, String requestId) { + String url = buildRequestPath(AssetType.RESOURCE.getSdcContextPath(), uuid, CSAR_PATH); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Get resource csar from SDC. URL={}", url); + return getObject(url, requestId, byte[].class); + } + public ServiceDetailed getService(String uuid, String requestId) { return getAssetMetadata(AssetType.SERVICE.name(), uuid, requestId); } diff --git a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/utils/SdcRestClientUtils.java b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/utils/SdcRestClientUtils.java index 33c2f49..1e5102e 100644 --- a/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/utils/SdcRestClientUtils.java +++ b/dcaedt_catalog/asdc/src/main/java/org/onap/sdc/dcae/utils/SdcRestClientUtils.java @@ -72,7 +72,7 @@ public class SdcRestClientUtils { return mapper.writeValueAsString(artifact); } - public static Artifact generateDeploymentArtifact(String description, String name, String type, String label, byte[] payload){ + public static Artifact generateDeploymentArtifact(String description, String name, String type, String label, byte[] payload) { Artifact artifact = new Artifact(); artifact.setDescription(description); artifact.setArtifactName(name); @@ -82,4 +82,12 @@ public class SdcRestClientUtils { artifact.setPayloadData(Base64Utils.encodeToString(payload)); return artifact; } + + public static Artifact generateCatalogDcaeToscaArtifact(String name, String path, byte[] payload) { + Artifact artifact = new Artifact(); + artifact.setArtifactName(name); + artifact.setArtifactURL(path); + artifact.setPayloadData(new String(payload)); + return artifact; + } } diff --git a/dcaedt_catalog/asdc/src/test/java/org/onap/sdc/dcae/utils/SDCResponseErrorHandlerTest.java b/dcaedt_catalog/asdc/src/test/java/org/onap/sdc/dcae/utils/SDCResponseErrorHandlerTest.java index 05eb4b1..15c4a8a 100644 --- a/dcaedt_catalog/asdc/src/test/java/org/onap/sdc/dcae/utils/SDCResponseErrorHandlerTest.java +++ b/dcaedt_catalog/asdc/src/test/java/org/onap/sdc/dcae/utils/SDCResponseErrorHandlerTest.java @@ -90,4 +90,4 @@ public class SDCResponseErrorHandlerTest { Assert.assertFalse(result); } -} +}
\ No newline at end of file diff --git a/dcaedt_catalog/commons/README b/dcaedt_catalog/commons/README new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dcaedt_catalog/commons/README diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java index 2c62412..6535fe5 100644 --- a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java +++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Action.java @@ -4,6 +4,5 @@ package org.onap.sdc.dcae.catalog.commons; */ public interface Action<T> { - public Future<T> execute(); - + Future<T> execute(); } diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java deleted file mode 100644 index 132b0c0..0000000 --- a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Actions.java +++ /dev/null @@ -1,201 +0,0 @@ -package org.onap.sdc.dcae.catalog.commons; - -import java.util.List; -import java.util.LinkedList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.concurrent.CountDownLatch; - -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.common.onaplog.OnapLoggerError; -import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.dcae.catalog.commons.Action; -import org.onap.sdc.dcae.catalog.commons.Future; -import org.onap.sdc.dcae.catalog.commons.FutureHandler; -import org.onap.sdc.dcae.catalog.commons.Futures; - -/** - */ -public interface Actions { - - /** */ - public static interface CompoundAction<T> extends Action<List<T>> { - - public CompoundAction<T> addAction(Action<T> theAction); - - public List<Action<T>> actions(); - - public Future<List<T>> execute(); - } - - - public static class BasicCompoundAction<T> implements CompoundAction<T> { - - private LinkedList<Action<T>> actions = new LinkedList<Action<T>>(); - - - - public CompoundAction<T> addAction(Action<T> theAction) { - this.actions.add(theAction); - return this; - } - - public List<Action<T>> actions() { - return this.actions; - } - - public Future<List<T>> execute() { - CompoundFuture<T> cf = new CompoundFuture<T>(this.actions.size()); - for (Action a: this.actions) - cf.addFuture(a.execute()); - return cf; - } - } - - - public static class CompoundFuture<T> extends Futures.BasicFuture<List<T>> { - - private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - private LinkedList<Future<T>> futures = new LinkedList<Future<T>>(); - private FutureHandler<T> hnd; - - CompoundFuture(int theActionCount) { - - hnd = new Futures.BasicHandler<T>(new CountDownLatch(theActionCount)) { - - private List<T> results = new ArrayList<T>(Collections.nCopies(theActionCount, null)); - - protected void process(Future<T> theResult) { - synchronized(CompoundFuture.this) { - if (theResult.failed()) { - CompoundFuture.this.cause(theResult.cause()); - //and stop processing of other results - this.results = null; - //?? - } - else { - if (this.results != null) - this.results.set(futures.indexOf(theResult), theResult.result()); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got result for action {}. Count at {}", futures.indexOf(theResult), this.latch.getCount()); - } - if (this.latch.getCount() == 1) {//this was the last result - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Got all results: {}", this.results); - CompoundFuture.this.result(this.results); - } - } - } - }; - } - - CompoundFuture<T> addFuture(Future<T> theFuture) { - synchronized(this) { - futures.add(theFuture); - theFuture.setHandler(this.hnd); - } - return this; - } - - } - -/* - public static class CompoundFutureHandler<T> implements FutureHandler<T> { - - protected List<T> result = null; - protected List<Throwable> error = null; - protected CountDownLatch latch = null; - - CompoundFutureHandler(int theResultCount) { - this(new CountDownLatch(theResultCount)); - } - - public void handle(Future<T> theResult) { - if (this.latch != null) { - this.latch.countDown(); - } - } - - public T result() - throws InterruptedException, RuntimeException { - return result(true); - } - - public BasicHandler<T> waitForCompletion() throws InterruptedException { - this.latch.await(); - return this; - } - - } -*/ - - public static class Sequence<T> implements Action<List<T>> { - - private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - private List<Action<T>> actions = new LinkedList<Action<T>>(); - private int current = 0; - private SequenceFuture<T> future = new SequenceFuture<T>(); - - public Sequence<T> add(Action<T> theAction) { - if (this.current > 0) - throw new IllegalStateException("In execution"); - this.actions.add(theAction); - return this; - } - - /* we allow 'early' access to the future so that a client can pass its reference while - * it still builds the sequence, for example. - */ - public Future<List<T>> future() { - return this.future; - } - - //need to add protection when for the 'no action' case - public Future<List<T>> execute() { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Starting serialized execution of {}", actions); - if (hasNext()) - next().execute().setHandler(future.hnd); - return this.future; - } - - protected boolean hasNext() { - return this.current < actions.size(); - } - - protected Action next() { - return actions.get(this.current++); - } - - private class SequenceFuture<T> extends Futures.BasicFuture<List<T>> { - - private List<T> results = new LinkedList<T>(); - private FutureHandler<T> hnd = new Futures.BasicHandler<T>() { - - protected void process(Future<T> theResult) { - - if (theResult.failed()) { - SequenceFuture.this.cause(theResult.cause()); - //and stop processing of other results - } - else { - SequenceFuture.this.results.add(theResult.result()); - if (Sequence.this.hasNext()) { - Sequence.this.next().execute().setHandler(this); - } - else { - SequenceFuture.this.result(SequenceFuture.this.results); - } - } - } - }; - - - } - - - - } - -} diff --git a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java index f6ea6ad..2711722 100644 --- a/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java +++ b/dcaedt_catalog/commons/src/main/java/org/onap/sdc/dcae/catalog/commons/Recycler.java @@ -73,11 +73,11 @@ public class Recycler { return this; } - public Object recycle(final Reader theSource) throws Exception { + public Map recycle(final Reader theSource) throws IOException { return this.recycle(new ObjectMapper().readValue(theSource, (Class)HashMap.class)); } - public Object recycle(final Object theDump) { + private Map recycle(final Object theDump) { final JXPathContext jxroot = JXPathContext.newContext(theDump); jxroot.setLenient(true); diff --git a/dcaedt_catalog/db/src/main/java/org/onap/sdc/dcae/db/neo4j/Modeled.java b/dcaedt_catalog/db/src/main/java/org/onap/sdc/dcae/db/neo4j/Modeled.java deleted file mode 100644 index 3a439b5..0000000 --- a/dcaedt_catalog/db/src/main/java/org/onap/sdc/dcae/db/neo4j/Modeled.java +++ /dev/null @@ -1 +0,0 @@ -//package org.onap.sdc.dcae.db.neo4j; diff --git a/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogController.java b/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogController.java index b42f8cf..b364087 100644 --- a/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogController.java +++ b/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogController.java @@ -18,27 +18,16 @@ under the License. */ package org.onap.sdc.dcae.catalog.engine; -import org.json.JSONObject; import org.onap.sdc.common.onaplog.Enums.LogLevel; import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.dcae.catalog.Catalog; import org.onap.sdc.dcae.catalog.asdc.ASDCCatalog; import org.onap.sdc.dcae.catalog.commons.Future; import org.onap.sdc.dcae.catalog.commons.FutureHandler; -import org.onap.sdc.dcae.composition.util.DcaeBeConstants; -import org.onap.sdc.dcae.composition.util.SystemProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; - /** * All requests body: * { @@ -94,73 +83,11 @@ public class CatalogController { private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - @Autowired - private SystemProperties systemProperties; - - private URI defaultCatalog; - private static Map<URI, Catalog> catalogs = new HashMap<>(); - - - public void setDefaultCatalog(URI theUri) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "set default catalog at {}", theUri); - this.defaultCatalog = theUri; - } - - @PostConstruct - public void initCatalog() { - // Dump some info and construct our configuration objects - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "initCatalog"); - - this.defaultCatalog = URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.ASDC_CATALOG_URL)); - // Initialize default catalog connection - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "default catalog at {}", this.defaultCatalog); - getCatalog(null); - - // Done - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "CatalogEngine started"); - } - - @PreDestroy - public void cleanupCatalog() { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "destroyCatalog"); - } - - public Catalog getCatalog(URI theCatalogUri) { - //TODO: Thread safety! Check catalog is alive! - if (theCatalogUri == null) { - theCatalogUri = this.defaultCatalog; - } - - Catalog cat = catalogs.get(theCatalogUri); - if (cat == null && theCatalogUri != null) { - String scheme = theCatalogUri.getScheme(); - URI catalogUri; - try { - catalogUri = new URI(theCatalogUri.getSchemeSpecificPart() + "#" + theCatalogUri.getFragment()); - } - catch (URISyntaxException urisx) { - throw new IllegalArgumentException("Invalid catalog reference '" + theCatalogUri.getSchemeSpecificPart() + "'"); - } - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Build catalog for {}", catalogUri); - - if ("asdc".equals(scheme)) { - cat = new ASDCCatalog(catalogUri); - } - else { - return null; - } - - catalogs.put(theCatalogUri, cat); - } - return cat; - } + private ASDCCatalog catalog; - public JSONObject patchData(Catalog theCat, JSONObject theData) { - theData.put("catalog", theCat.getUri()); - theData.put("catalogId", theData.optLong("id")); - theData.put("id", theData.optLong("itemId")); - return theData; + public ASDCCatalog getCatalog() { + return catalog; } public abstract class CatalogHandler<T> implements FutureHandler<T> { diff --git a/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogEngine.java b/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogEngine.java index 042798f..98db815 100644 --- a/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogEngine.java +++ b/dcaedt_catalog/service/src/main/java/org/onap/sdc/dcae/catalog/engine/CatalogEngine.java @@ -1,21 +1,11 @@ package org.onap.sdc.dcae.catalog.engine; -import org.onap.sdc.dcae.catalog.engine.CatalogEngine; import org.springframework.boot.SpringApplication; -import org.springframework.context.ApplicationContext; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; import org.springframework.boot.autoconfigure.SpringBootApplication; - - -import java.util.Arrays; - - +import org.springframework.context.annotation.ComponentScan; @SpringBootApplication - +@ComponentScan("org.onap.sdc.dcae") public class CatalogEngine { public static void main(String[] args) { diff --git a/dcaedt_tools/src/ReadMe.txt b/dcaedt_tools/src/ReadMe.txt index 4657a81..9813f98 100644 --- a/dcaedt_tools/src/ReadMe.txt +++ b/dcaedt_tools/src/ReadMe.txt @@ -61,4 +61,10 @@ config.json example: }] } ] - }
\ No newline at end of file + } + + + exit codes: + 0 - completed successfully + 1 - completed with errors + 2 - failed
\ No newline at end of file diff --git a/dcaedt_tools/src/main/java/json/response/ElementsResponse/Data.java b/dcaedt_tools/src/main/java/json/response/ElementsResponse/Data.java deleted file mode 100644 index 15876af..0000000 --- a/dcaedt_tools/src/main/java/json/response/ElementsResponse/Data.java +++ /dev/null @@ -1,23 +0,0 @@ - -package json.response.ElementsResponse; - -import java.util.List; -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Data { - - @SerializedName("elements") - private List<Element> mElements; - - public List<Element> getElements() { - return mElements; - } - - public void setElements(List<Element> elements) { - mElements = elements; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ElementsResponse/Element.java b/dcaedt_tools/src/main/java/json/response/ElementsResponse/Element.java deleted file mode 100644 index 6402061..0000000 --- a/dcaedt_tools/src/main/java/json/response/ElementsResponse/Element.java +++ /dev/null @@ -1,73 +0,0 @@ - -package json.response.ElementsResponse; - -import java.util.List; -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Element { - - @SerializedName("catalog") - private String mCatalog; - @SerializedName("catalogId") - private Long mCatalogId; - @SerializedName("id") - private Long mId; - @SerializedName("itemId") - private String mItemId; - @SerializedName("labels") - private List<String> mLabels; - @SerializedName("name") - private String mName; - - public String getCatalog() { - return mCatalog; - } - - public void setCatalog(String catalog) { - mCatalog = catalog; - } - - public Long getCatalogId() { - return mCatalogId; - } - - public void setCatalogId(Long catalogId) { - mCatalogId = catalogId; - } - - public Long getId() { - return mId; - } - - public void setId(Long id) { - mId = id; - } - - public String getItemId() { - return mItemId; - } - - public void setItemId(String itemId) { - mItemId = itemId; - } - - public List<String> getLabels() { - return mLabels; - } - - public void setLabels(List<String> labels) { - mLabels = labels; - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ElementsResponse/ElementsResponse.java b/dcaedt_tools/src/main/java/json/response/ElementsResponse/ElementsResponse.java deleted file mode 100644 index 02dcdf2..0000000 --- a/dcaedt_tools/src/main/java/json/response/ElementsResponse/ElementsResponse.java +++ /dev/null @@ -1,53 +0,0 @@ - -package json.response.ElementsResponse; - -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; -import json.response.Error; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class ElementsResponse { - - @SerializedName("data") - private Data mData; - @SerializedName("error") - private Error mError; - @SerializedName("id") - private Object mId; - @SerializedName("timestamp") - private Long mTimestamp; - - public Data getData() { - return mData; - } - - public void setData(Data data) { - mData = data; - } - - public Error getError() { - return mError; - } - - public void setError(Error error) { - mError = error; - } - - public Object getId() { - return mId; - } - - public void setId(Object id) { - mId = id; - } - - public Long getTimestamp() { - return mTimestamp; - } - - public void setTimestamp(Long timestamp) { - mTimestamp = timestamp; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Data.java b/dcaedt_tools/src/main/java/json/response/ItemsResponse/Data.java deleted file mode 100644 index 36fcb09..0000000 --- a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Data.java +++ /dev/null @@ -1,22 +0,0 @@ - -package json.response.ItemsResponse; - -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Data { - - @SerializedName("element") - private Element mElement; - - public Element getElement() { - return mElement; - } - - public void setElement(Element element) { - mElement = element; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Element.java b/dcaedt_tools/src/main/java/json/response/ItemsResponse/Element.java deleted file mode 100644 index 5d56a25..0000000 --- a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Element.java +++ /dev/null @@ -1,53 +0,0 @@ - -package json.response.ItemsResponse; - -import java.util.List; -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Element { - - @SerializedName("id") - private Long mId; - @SerializedName("itemId") - private String mItemId; - @SerializedName("items") - private List<Item> mItems; - @SerializedName("name") - private String mName; - - public Long getId() { - return mId; - } - - public void setId(Long id) { - mId = id; - } - - public String getItemId() { - return mItemId; - } - - public void setItemId(String itemId) { - mItemId = itemId; - } - - public List<Item> getItems() { - return mItems; - } - - public void setItems(List<Item> items) { - mItems = items; - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Item.java b/dcaedt_tools/src/main/java/json/response/ItemsResponse/Item.java deleted file mode 100644 index 6f0e518..0000000 --- a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Item.java +++ /dev/null @@ -1,203 +0,0 @@ - -package json.response.ItemsResponse; - -import java.util.List; -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Item { - - @SerializedName("artifacts") - private List<Artifact> mArtifacts; - @SerializedName("catalog") - private String mCatalog; - @SerializedName("catalogId") - private Long mCatalogId; - @SerializedName("category") - private String mCategory; - @SerializedName("description") - private String mDescription; - @SerializedName("id") - private Long mId; - @SerializedName("invariantUUID") - private String mInvariantUUID; - @SerializedName("itemId") - private String mItemId; - @SerializedName("lastUpdaterFullName") - private String mLastUpdaterFullName; - @SerializedName("lastUpdaterUserId") - private String mLastUpdaterUserId; - @SerializedName("lifecycleState") - private String mLifecycleState; - @SerializedName("models") - private List<Model> mModels; - @SerializedName("name") - private String mName; - @SerializedName("resourceType") - private String mResourceType; - @SerializedName("subCategory") - private String mSubCategory; - @SerializedName("toscaModelURL") - private String mToscaModelURL; - @SerializedName("toscaResourceName") - private String mToscaResourceName; - @SerializedName("uuid") - private String mUuid; - @SerializedName("version") - private String mVersion; - - public List<Artifact> getArtifacts() { - return mArtifacts; - } - - public void setArtifacts(List<Artifact> artifacts) { - mArtifacts = artifacts; - } - - public String getCatalog() { - return mCatalog; - } - - public void setCatalog(String catalog) { - mCatalog = catalog; - } - - public Long getCatalogId() { - return mCatalogId; - } - - public void setCatalogId(Long catalogId) { - mCatalogId = catalogId; - } - - public String getCategory() { - return mCategory; - } - - public void setCategory(String category) { - mCategory = category; - } - - public String getDescription() { - return mDescription; - } - - public void setDescription(String description) { - mDescription = description; - } - - public Long getId() { - return mId; - } - - public void setId(Long id) { - mId = id; - } - - public String getInvariantUUID() { - return mInvariantUUID; - } - - public void setInvariantUUID(String invariantUUID) { - mInvariantUUID = invariantUUID; - } - - public String getItemId() { - return mItemId; - } - - public void setItemId(String itemId) { - mItemId = itemId; - } - - public String getLastUpdaterFullName() { - return mLastUpdaterFullName; - } - - public void setLastUpdaterFullName(String lastUpdaterFullName) { - mLastUpdaterFullName = lastUpdaterFullName; - } - - public String getLastUpdaterUserId() { - return mLastUpdaterUserId; - } - - public void setLastUpdaterUserId(String lastUpdaterUserId) { - mLastUpdaterUserId = lastUpdaterUserId; - } - - public String getLifecycleState() { - return mLifecycleState; - } - - public void setLifecycleState(String lifecycleState) { - mLifecycleState = lifecycleState; - } - - public List<Model> getModels() { - return mModels; - } - - public void setModels(List<Model> models) { - mModels = models; - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - public String getResourceType() { - return mResourceType; - } - - public void setResourceType(String resourceType) { - mResourceType = resourceType; - } - - public String getSubCategory() { - return mSubCategory; - } - - public void setSubCategory(String subCategory) { - mSubCategory = subCategory; - } - - public String getToscaModelURL() { - return mToscaModelURL; - } - - public void setToscaModelURL(String toscaModelURL) { - mToscaModelURL = toscaModelURL; - } - - public String getToscaResourceName() { - return mToscaResourceName; - } - - public void setToscaResourceName(String toscaResourceName) { - mToscaResourceName = toscaResourceName; - } - - public String getUuid() { - return mUuid; - } - - public void setUuid(String uuid) { - mUuid = uuid; - } - - public String getVersion() { - return mVersion; - } - - public void setVersion(String version) { - mVersion = version; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ItemsResponse/ItemsResponse.java b/dcaedt_tools/src/main/java/json/response/ItemsResponse/ItemsResponse.java deleted file mode 100644 index 5b64b59..0000000 --- a/dcaedt_tools/src/main/java/json/response/ItemsResponse/ItemsResponse.java +++ /dev/null @@ -1,53 +0,0 @@ - -package json.response.ItemsResponse; - -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; -import json.response.Error; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class ItemsResponse { - - @SerializedName("data") - private Data mData; - @SerializedName("error") - private Error mError; - @SerializedName("id") - private Object mId; - @SerializedName("timestamp") - private Long mTimestamp; - - public Data getData() { - return mData; - } - - public void setData(Data data) { - mData = data; - } - - public Error getError() { - return mError; - } - - public void setError(Error error) { - mError = error; - } - - public Object getId() { - return mId; - } - - public void setId(Object id) { - mId = id; - } - - public Long getTimestamp() { - return mTimestamp; - } - - public void setTimestamp(Long timestamp) { - mTimestamp = timestamp; - } - -} diff --git a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Model.java b/dcaedt_tools/src/main/java/json/response/ItemsResponse/Model.java deleted file mode 100644 index 036b16b..0000000 --- a/dcaedt_tools/src/main/java/json/response/ItemsResponse/Model.java +++ /dev/null @@ -1,62 +0,0 @@ - -package json.response.ItemsResponse; - -import javax.annotation.Generated; -import com.google.gson.annotations.SerializedName; - -@Generated("net.hexar.json2pojo") -@SuppressWarnings("unused") -public class Model { - - @SerializedName("description") - private String mDescription; - @SerializedName("id") - private String mId; - @SerializedName("itemId") - private String mItemId; - @SerializedName("name") - private String mName; - @SerializedName("version") - private String mVersion; - - public String getDescription() { - return mDescription; - } - - public void setDescription(String description) { - mDescription = description; - } - - public String getId() { - return mId; - } - - public void setId(String id) { - mId = id; - } - - public String getItemId() { - return mItemId; - } - - public void setItemId(String itemId) { - mItemId = itemId; - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - public String getVersion() { - return mVersion; - } - - public void setVersion(String version) { - mVersion = version; - } - -} diff --git a/dcaedt_tools/src/main/java/tools/DeployTemplate.java b/dcaedt_tools/src/main/java/tools/DeployTemplate.java index d319542..556316b 100644 --- a/dcaedt_tools/src/main/java/tools/DeployTemplate.java +++ b/dcaedt_tools/src/main/java/tools/DeployTemplate.java @@ -29,7 +29,7 @@ public class DeployTemplate { } public void deploy(Map<TemplateInfo, JsonObject> templateInfoToJsonObjectMap) { - ArrayList<ResourceDetailed> vfcmtList = new ArrayList(); + ArrayList<ResourceDetailed> vfcmtList = new ArrayList<>(); List<ResourceDetailed> regularVfcmtList = dcaeRestClient.getAllVfcmts(); if (regularVfcmtList != null) { vfcmtList.addAll(regularVfcmtList); @@ -55,7 +55,7 @@ public class DeployTemplate { private void verify(Map<TemplateInfo, JsonObject> templateInfoToJsonObjectMap) { AtomicInteger foundCount = new AtomicInteger(); debugLogger.log("Starting verify deployment"); - ArrayList<ResourceDetailed> vfcmtList = new ArrayList(); + ArrayList<ResourceDetailed> vfcmtList = new ArrayList<>(); List<ResourceDetailed> regularVfcmtList = dcaeRestClient.getAllVfcmts(); if (regularVfcmtList != null) { vfcmtList.addAll(regularVfcmtList); @@ -91,10 +91,11 @@ public class DeployTemplate { saveAndCertify(jsonObject, vfcmt); - } catch (HttpServerErrorException e) { + } catch (Exception e) { String msg = FAILED_UPDATE_VFCMT + templateInfo.getName() + ", With general message: " + e.getMessage(); report.addErrorMessage(msg); errLogger.log(msg + " " + e); + report.setStatusCode(2); } } @@ -120,10 +121,11 @@ public class DeployTemplate { } else { report.addNotUpdatedMessage("vfcmt: " + vfcmt.getName() + " found, but didn't update."); } - } catch (HttpServerErrorException e) { + } catch (Exception e) { String msg = FAILED_UPDATE_VFCMT + vfcmt.getName() + ", With general message: " + e.getMessage(); report.addErrorMessage(msg); errLogger.log( msg + " " + e); + report.setStatusCode(2); } } diff --git a/dcaedt_tools/src/main/java/tools/EntitiesRetriever.java b/dcaedt_tools/src/main/java/tools/EntitiesRetriever.java deleted file mode 100644 index 0c31ddf..0000000 --- a/dcaedt_tools/src/main/java/tools/EntitiesRetriever.java +++ /dev/null @@ -1,33 +0,0 @@ -package tools; - -import json.response.ElementsResponse.Element; -import json.response.ItemsResponse.Item; -import utilities.IDcaeRestClient; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -public class EntitiesRetriever { - private final IDcaeRestClient dcaeRestClient; - - EntitiesRetriever(IDcaeRestClient dcaeRestClient) { - - this.dcaeRestClient = dcaeRestClient; - } - - public Map<String, List<Item>> getElementsByFolder() { - List<Element> elementList = dcaeRestClient.getElements(); - Map<String, List<Item>> elementsByFolderNames = new HashMap<>(); - - for (Element element : elementList) { - List<Item> items = dcaeRestClient.getItem(element.getName()); - if (items == null) { - continue; - } - elementsByFolderNames.put(element.getName(), items); - } - return elementsByFolderNames; - } -} diff --git a/dcaedt_tools/src/main/java/tools/ItemAndAlias.java b/dcaedt_tools/src/main/java/tools/ItemAndAlias.java index e282a58..dae65ef 100644 --- a/dcaedt_tools/src/main/java/tools/ItemAndAlias.java +++ b/dcaedt_tools/src/main/java/tools/ItemAndAlias.java @@ -1,16 +1,16 @@ package tools; -import json.response.ItemsResponse.Item; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; public class ItemAndAlias { - private final Item item; + private final Resource item; private final String alias; - public ItemAndAlias(Item item, String alias) { + public ItemAndAlias(Resource item, String alias) { this.item = item; this.alias = alias; } - public Item getItem() { + public Resource getItem() { return item; } diff --git a/dcaedt_tools/src/main/java/tools/Main.java b/dcaedt_tools/src/main/java/tools/Main.java index bf02c44..142b6bd 100644 --- a/dcaedt_tools/src/main/java/tools/Main.java +++ b/dcaedt_tools/src/main/java/tools/Main.java @@ -4,10 +4,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonObject; import json.Environment; -import json.response.ItemsResponse.Item; + import json.templateInfo.DeployTemplateConfig; import json.templateInfo.TemplateInfo; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import utilities.IDcaeRestClient; import utilities.IReport; import utilities.Report; @@ -35,7 +36,7 @@ public class Main { debugLogger.log("Starting VFCMT template deployment"); if (args.length != 2) { errLogger.log("Got " + args.length + ", but expecting exactly 2 arguments ONLY!"); - return; + System.exit(2); } debugLogger.log("Arguments:"); Arrays.stream(args).forEach(arg -> debugLogger.log(arg)); @@ -50,8 +51,7 @@ public class Main { IDcaeRestClient dcaeRestClient = new DcaeRestClient(environment.getCredential()); dcaeRestClient.init(environment); - EntitiesRetriever entitiesRetriever = new EntitiesRetriever(dcaeRestClient); - Map<String, List<Item>> elementsByFolderNames = entitiesRetriever.getElementsByFolder(); + Map<String, List<Resource>> elementsByFolderNames = dcaeRestClient.getDcaeCatalog(); TemplateContainer templateContainer = new TemplateContainer(report, dcaeRestClient, deployTemplateConfig.getTemplateInfo(), elementsByFolderNames); Map<TemplateInfo, JsonObject> templateInfoToJsonObjectMap = templateContainer.getCdumps(); @@ -59,15 +59,20 @@ public class Main { DeployTemplate deployTemplate = new DeployTemplate(report, dcaeRestClient); deployTemplate.deploy(templateInfoToJsonObjectMap); - debugLogger.log( "VFCMT template deployment completed successfully"); + debugLogger.log( "VFCMT template deployment completed"); + } catch (RuntimeException e) { errLogger.log("ERROR - Template deployment failed with error " + e, e); + report.setStatusCode(2); } catch (ConnectException e) { errLogger.log( "ERROR - Failed connection to server, are you on AT&T network? {}" + e, e); + report.setStatusCode(2); } catch (IOException e) { errLogger.log( "ERROR - Fatal Error! " + e, e); + report.setStatusCode(2); } finally { debugLogger.log(report.toString()); + report.reportAndExit(); } } diff --git a/dcaedt_tools/src/main/java/tools/NodeData.java b/dcaedt_tools/src/main/java/tools/NodeData.java index e9043de..a2df502 100644 --- a/dcaedt_tools/src/main/java/tools/NodeData.java +++ b/dcaedt_tools/src/main/java/tools/NodeData.java @@ -2,6 +2,7 @@ package tools; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import org.apache.commons.lang3.StringUtils; public class NodeData { private final JsonArray capabilities; @@ -41,7 +42,11 @@ public class NodeData { } public String getNameWithAlias() { - return aliasBelong + "." + nodeName; + if (StringUtils.isBlank(aliasBelong)) { + return nodeName; + } else { + return aliasBelong + "." + nodeName; + } } public String getAliasBelong() { diff --git a/dcaedt_tools/src/main/java/tools/TemplateContainer.java b/dcaedt_tools/src/main/java/tools/TemplateContainer.java index a5bca1f..b8b7b5a 100644 --- a/dcaedt_tools/src/main/java/tools/TemplateContainer.java +++ b/dcaedt_tools/src/main/java/tools/TemplateContainer.java @@ -4,12 +4,12 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import json.response.ItemsResponse.Item; import json.templateInfo.Composition; import json.templateInfo.NodeToDelete; import json.templateInfo.Relation; import json.templateInfo.TemplateInfo; import org.apache.commons.lang3.StringUtils; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import utilities.IDcaeRestClient; import utilities.IReport; @@ -20,16 +20,16 @@ import java.util.concurrent.atomic.AtomicReference; public class TemplateContainer { private static final String NODES = "nodes"; private static final String RELATIONSHIP = "relationship"; - public static final String ASSIGNMENT = "assignment"; + private static final String ASSIGNMENT = "assignment"; private static long nidCounter = 0; private final IReport report; private final IDcaeRestClient dcaeRestClient; private final List<TemplateInfo> templateInfos; - private final Map<String, List<Item>> elementsByFolderNames; + private final Map<String, List<Resource>> elementsByFolderNames; private LoggerDebug debugLogger = LoggerDebug.getInstance(); - public TemplateContainer(IReport report, IDcaeRestClient dcaeRestClient, List<TemplateInfo> templateInfos, Map<String, List<Item>> elementsByFolderNames) { + public TemplateContainer(IReport report, IDcaeRestClient dcaeRestClient, List<TemplateInfo> templateInfos, Map<String, List<Resource>> elementsByFolderNames) { this.report = report; this.dcaeRestClient = dcaeRestClient; this.templateInfos = templateInfos; @@ -69,6 +69,7 @@ public class TemplateContainer { List<ItemAndAlias> items = findTemplate(templateInfo); if (items == null || items.isEmpty()) { report.addErrorMessage("vfcmt: " + templateInfo.getName() + ". DCAE Component not found"); + report.setStatusCode(1); continue; } templateInfoToJsonObjectMap.put(templateInfo, getCdumpJsonObject(items, templateInfo)); @@ -81,20 +82,21 @@ public class TemplateContainer { Map<ItemAndAlias, Map<String, NodeData>> itemMapHashMap = new HashMap<>(); JsonArray relationsJsonArray = new JsonArray(); for (ItemAndAlias itemAndAlias : ItemsAndAlias) { - Item item = itemAndAlias.getItem(); + Resource item = itemAndAlias.getItem(); debugLogger.log("Creating cdump for item: " + item.getName()); JsonArray jsonArrayNode = cdumpJsonObject.getAsJsonArray(NODES); JsonParser jsonParser = new JsonParser(); - JsonArray allNodeTemplates = jsonParser.parse(dcaeRestClient.getItemModel(item.getItemId())).getAsJsonObject().get("data").getAsJsonObject().get("model").getAsJsonObject().get(NODES).getAsJsonArray(); + JsonObject modelResponse = jsonParser.parse(dcaeRestClient.getItemModel(item.getUuid())).getAsJsonObject().get("data").getAsJsonObject().get("model").getAsJsonObject(); + JsonArray allNodeTemplates = modelResponse.get(NODES).getAsJsonArray(); Map<String, NodeData> stringRelationsDataMap = new HashMap<>(); for (JsonElement nodeElement : allNodeTemplates) { if (checkIfNeedToSkip(templateInfo.getNodesToDelete(), nodeElement, item.getName())) { continue; } JsonObject responseModelJson = nodeElement.getAsJsonObject(); - JsonObject responseTypeInfoJson = jsonParser.parse(dcaeRestClient.getItemType(item.getItemId(), responseModelJson.get("type").getAsString())).getAsJsonObject().get("data").getAsJsonObject().get("type").getAsJsonObject(); - String nodeName = itemAndAlias.getAlias() + "." + responseModelJson.get("name").getAsString(); - JsonObject jsonObjectElement = newNodeTemplate(nodeName, item.getModels().get(0).getItemId()); + JsonObject responseTypeInfoJson = jsonParser.parse(dcaeRestClient.getItemType(item.getUuid(), responseModelJson.get("type").getAsString())).getAsJsonObject().get("data").getAsJsonObject().get("type").getAsJsonObject(); + String nodeName = itemAndAlias.getAlias() != "" ? itemAndAlias.getAlias() + "." + responseModelJson.get("name").getAsString() : responseModelJson.get("name").getAsString(); + JsonObject jsonObjectElement = newNodeTemplate(nodeName, modelResponse.get("itemId").getAsString()); jsonObjectElement.addProperty("id", responseTypeInfoJson.get("itemId").getAsString().split("/")[0]); String nid = "n." + new Date().getTime() + "." + nidCounter++; jsonObjectElement.addProperty("nid", nid); @@ -228,7 +230,7 @@ public class TemplateContainer { metaData.addProperty("n1", nidListByRequirement.get(requirement)); metaData.addProperty("p1", requirement.get("name").toString().replaceAll("\"", "")); relationElement.addProperty("n2", toNId); - relationElement.addProperty("name2", fromNode.getAliasBelong() + "." + toNodeName); + relationElement.addProperty("name2", StringUtils.isBlank(fromNode.getAliasBelong()) ? toNodeName : fromNode.getAliasBelong() + "." + toNodeName); metaData.addProperty("n2", toNId); String capabilityFullName = requirement.get("capability").getAsJsonObject().get("name").toString(); String capabilityShortName = StringUtils.substringAfterLast(capabilityFullName, "."); @@ -270,10 +272,18 @@ public class TemplateContainer { JsonObject relationElement = new JsonObject(); String fromComponent = relation.getFromComponent(); String toComponent = relation.getToComponent(); - String fromComponentAlias = StringUtils.substringBefore(fromComponent, "."); - String fromComponentNodeName = StringUtils.substringAfterLast(fromComponent, "."); - String toComponentAlias = StringUtils.substringBefore(toComponent, "."); - String toComponentNodeName = StringUtils.substringAfterLast(toComponent, "."); + String fromComponentAlias = ""; + String fromComponentNodeName = fromComponent; + if ((fromComponent.contains("."))) { + fromComponentAlias = StringUtils.substringBefore(fromComponent, "."); + fromComponentNodeName = StringUtils.substringAfterLast(fromComponent, "."); + } + String toComponentAlias = ""; + String toComponentNodeName = toComponent; + if (toComponent.contains(".")) { + toComponentAlias = StringUtils.substringBefore(toComponent, "."); + toComponentNodeName = StringUtils.substringAfterLast(toComponent, "."); + } boolean findTo = false; boolean findFrom = false; for (ItemAndAlias item : nodeDataByNidByItem.keySet()) { @@ -281,12 +291,14 @@ public class TemplateContainer { for (String nid : nodeDataByNid.keySet()) { NodeData currentNodeData = nodeDataByNid.get(nid); + String finalFromComponentAlias = fromComponentAlias; + String finalFromComponentNodeName = fromComponentNodeName; Optional<Composition> isFoundComposition = templateInfo.getComposition().stream() - .filter(element -> fromComponentAlias.equalsIgnoreCase(element.getAlias()) + .filter(element -> finalFromComponentAlias.equalsIgnoreCase(element.getAlias()) && element.getAlias().equalsIgnoreCase(currentNodeData.getAliasBelong()) && element.getAlias().equalsIgnoreCase(item.getAlias()) && element.getType().equalsIgnoreCase(item.getItem().getName()) - && fromComponentNodeName.equalsIgnoreCase(currentNodeData.getName())).findAny(); + && finalFromComponentNodeName.equalsIgnoreCase(currentNodeData.getName())).findAny(); if (isFoundComposition.isPresent()) { boolean isFound = findNode(relation.getFromRequirement(), currentNodeData.getRequirements()); if (isFound) { @@ -313,12 +325,14 @@ public class TemplateContainer { } + String finalToComponentNodeName = toComponentNodeName; + String finalToComponentAlias = toComponentAlias; isFoundComposition = templateInfo.getComposition().stream() - .filter(element -> toComponentAlias.equalsIgnoreCase(element.getAlias()) + .filter(element -> finalToComponentAlias.equalsIgnoreCase(element.getAlias()) && element.getAlias().equalsIgnoreCase(currentNodeData.getAliasBelong()) && element.getAlias().equalsIgnoreCase(item.getAlias()) && element.getType().equalsIgnoreCase(item.getItem().getName()) - && toComponentNodeName.equalsIgnoreCase(currentNodeData.getName())).findAny(); + && finalToComponentNodeName.equalsIgnoreCase(currentNodeData.getName())).findAny(); if (isFoundComposition.isPresent()) { boolean isFound = findNode(relation.getToCapability(), currentNodeData.getCapabilities()); if (isFound) { diff --git a/dcaedt_tools/src/main/java/utilities/DcaeRestClient.java b/dcaedt_tools/src/main/java/utilities/DcaeRestClient.java index 7e991d7..ee6cdc7 100644 --- a/dcaedt_tools/src/main/java/utilities/DcaeRestClient.java +++ b/dcaedt_tools/src/main/java/utilities/DcaeRestClient.java @@ -2,14 +2,12 @@ package utilities; import json.Credential; import json.Environment; -import json.response.ElementsResponse.Element; -import json.response.ElementsResponse.ElementsResponse; -import json.response.ItemsResponse.Item; -import json.response.ItemsResponse.ItemsResponse; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.onap.sdc.dcae.composition.restmodels.CreateVFCMTRequest; +import org.onap.sdc.dcae.composition.restmodels.canvas.DcaeComponentCatalog; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @@ -17,10 +15,10 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -30,6 +28,7 @@ public class DcaeRestClient implements IDcaeRestClient { private static final String GET_RESOURCES_BY_CATEGORY = "/getResourcesByCategory"; private static final String CREATE_VFCMT = "/createVFCMT"; private static final String ELEMENTS = "/elements"; + private static final String CATALOG = "/catalog"; private static final String ECOMP_INSTANCE_ID_HEADER = "X-ECOMP-InstanceID"; @@ -102,16 +101,13 @@ public class DcaeRestClient implements IDcaeRestClient { return resourceDetailedResponse.getBody(); } - @Override - public List<Element> getElements() { - String url = buildRequestPath(ELEMENTS); - return client.getForObject(url, ElementsResponse.class).getData().getElements(); - } - @Override - public List<Item> getItem(String element) { - String url = buildRequestPath("/"+ element + ELEMENTS); - return client.getForObject(url, ItemsResponse.class).getData().getElement() == null ? null : client.getForObject(url, ItemsResponse.class).getData().getElement().getItems(); - } + @Override + public Map<String, List<Resource>> getDcaeCatalog() { + String url = buildRequestPath(CATALOG); + DcaeComponentCatalog catalog = client.getForObject(url, DcaeComponentCatalog.class); + return catalog.getElements().stream().collect(Collectors.toMap(DcaeComponentCatalog.SubCategoryFolder::getName, DcaeComponentCatalog.SubCategoryFolder::getItems)); + } + @Override public String getItemModel(String elementId) { diff --git a/dcaedt_tools/src/main/java/utilities/IDcaeRestClient.java b/dcaedt_tools/src/main/java/utilities/IDcaeRestClient.java index bfe3595..a1ccdbe 100644 --- a/dcaedt_tools/src/main/java/utilities/IDcaeRestClient.java +++ b/dcaedt_tools/src/main/java/utilities/IDcaeRestClient.java @@ -1,12 +1,12 @@ package utilities; import json.Environment; -import json.response.ElementsResponse.Element; -import json.response.ItemsResponse.Item; import org.onap.sdc.dcae.composition.restmodels.CreateVFCMTRequest; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import java.util.List; +import java.util.Map; public interface IDcaeRestClient { void init(Environment environment); @@ -23,9 +23,7 @@ public interface IDcaeRestClient { ResourceDetailed checkinVfcmt(String vfcmtUuid); - List<Element> getElements(); - - List<Item> getItem(String element); + Map<String, List<Resource>> getDcaeCatalog(); String getItemModel(String elementId); diff --git a/dcaedt_tools/src/main/java/utilities/IReport.java b/dcaedt_tools/src/main/java/utilities/IReport.java index 4c5f8af..5f4099c 100644 --- a/dcaedt_tools/src/main/java/utilities/IReport.java +++ b/dcaedt_tools/src/main/java/utilities/IReport.java @@ -5,4 +5,6 @@ public interface IReport { void addUpdatedMessage(String message); void addNotUpdatedMessage(String message); void addErrorMessage(String message); + void setStatusCode(int statusCode); + void reportAndExit(); } diff --git a/dcaedt_tools/src/main/java/utilities/Report.java b/dcaedt_tools/src/main/java/utilities/Report.java index 8f79056..0b99603 100644 --- a/dcaedt_tools/src/main/java/utilities/Report.java +++ b/dcaedt_tools/src/main/java/utilities/Report.java @@ -9,6 +9,7 @@ public class Report implements IReport { private List<String> updated = new ArrayList<>(); private List<String> notUpdated = new ArrayList<>(); private List<String> error = new ArrayList<>(); + private int statusCode = 0; @Override public void addCreatedMessage(String message) { @@ -51,4 +52,14 @@ public class Report implements IReport { } return stringBuilder.toString(); } + + + public void reportAndExit() { + System.exit(statusCode); + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + } diff --git a/dcaedt_tools/src/main/resources/conf/config.json b/dcaedt_tools/src/main/resources/conf/config.json index 4ca81cc..f7c07d7 100644 --- a/dcaedt_tools/src/main/resources/conf/config.json +++ b/dcaedt_tools/src/main/resources/conf/config.json @@ -1,6 +1,7 @@ + { "templateInfo": [{ - "name": "Syslog Collector Template", + "name": "Syslog Collector", "flowType": "Syslog Collector", "description": "Syslog Collector", "category": "Template", @@ -8,24 +9,10 @@ "updateIfExist": "false", "composition": [{ "type": "SyslogCollector", - "alias": "Syslog" - }, { - "type": "Existing Topic", - "alias": "eTopic" - }], - "relations": [{ - "fromComponent": "Syslog.SyslogCollector", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "SyslogCollector", - "nodeName": "topic0" - }] + "alias": "" + }] },{ - "name": "Syslog MSEA Template", + "name": "Syslog MSEA", "flowType": "Syslog MSEA", "description": "Syslog MSEA", "category": "Template", @@ -33,60 +20,37 @@ "updateIfExist": "false", "composition": [{ "type": "Map", - "alias": "Map" + "alias": "" }, { "type": "Supplement", - "alias": "Sup" + "alias": "" }, { "type": "Enrich", - "alias": "Enr" + "alias": "" }, { "type": "Alert", - "alias": "Ale" + "alias": "" }], "relations": [{ - "fromComponent": "Sup.Supplement", + "fromComponent": "Supplement", "fromRequirement": "dependency", - "toComponent": "Map.Map", + "toComponent": "Map", "toCapability": "feature" },{ - "fromComponent": "Enr.Enrich", + "fromComponent": "Enrich", "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", + "toComponent": "Supplement", "toCapability": "feature" },{ - "fromComponent": "Ale.Alert", + "fromComponent": "Alert", "fromRequirement": "dependency", - "toComponent": "Enr.Enrich", + "toComponent": "Enrich", "toCapability": "feature" }] - },{ - "name": "Status Poller Collector Template", - "flowType": "Status Poller Collector", - "description": "Status Poller Collector", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "StatusPoller", - "alias": "sPoller" - }, { - "type": "Existing Topic", - "alias": "eTopic0" - }], - "relations": [{ - "fromComponent": "sPoller.StatusPoller", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic0.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "StatusPoller", - "nodeName": "topic0" - }] - }, { - "name": "Status Poller MSE Template", + }, + + { + "name": "Status Poller MSE", "flowType": "Status Poller MSE", "description": "Status Poller MSE", "category": "Template", @@ -94,27 +58,27 @@ "updateIfExist": "false", "composition": [{ "type": "Map", - "alias": "Map" + "alias": "" }, { "type": "Supplement", - "alias": "Sup" + "alias": "" }, { "type": "Enrich", - "alias": "Enr" + "alias": "" }], "relations": [{ - "fromComponent": "Sup.Supplement", + "fromComponent": "Supplement", "fromRequirement": "dependency", - "toComponent": "Map.Map", + "toComponent": "Map", "toCapability": "feature" },{ - "fromComponent": "Enr.Enrich", + "fromComponent": "Enrich", "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", + "toComponent": "Supplement", "toCapability": "feature" }] }, { - "name": "FOI Collector Template", + "name": "FOI Collector", "flowType": "FOI Collector", "description": "FOI Collector", "category": "Template", @@ -122,24 +86,11 @@ "updateIfExist": "false", "composition": [{ "type": "FOICollector", - "alias": "fCollector" - }, { - "type": "Existing Feed", - "alias": "eFeed" - }], - "relations": [{ - "fromComponent": "fCollector.FoiSftp", - "fromRequirement": "stream_publish_0", - "toComponent": "eFeed.feed", - "toCapability": "feed" - }], - "nodesToDelete": [ - { - "type": "FOICollector", - "nodeName": "feed0" - }] + "alias": "" + }] + }, { - "name": "SNMP MSE Template", + "name": "SNMP MSE", "flowType": "SNMP MSE", "description": "SNMP MSE", "category": "Template", @@ -147,27 +98,27 @@ "updateIfExist": "false", "composition": [{ "type": "Map", - "alias": "Map" + "alias": "" }, { "type": "Supplement", - "alias": "Sup" + "alias": "" }, { "type": "Enrich", - "alias": "Enr" + "alias": "" }], "relations": [{ - "fromComponent": "Sup.Supplement", + "fromComponent": "Supplement", "fromRequirement": "dependency", - "toComponent": "Map.Map", + "toComponent": "Map", "toCapability": "feature" },{ - "fromComponent": "Enr.Enrich", + "fromComponent": "Enrich", "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", + "toComponent": "Supplement", "toCapability": "feature" }] }, { - "name": "Docker Map Template", + "name": "Docker Map", "flowType": "Docker Map", "description": "Docker Map", "category": "Template", @@ -175,33 +126,125 @@ "updateIfExist": "false", "composition": [{ "type": "DockerMap", - "alias": "dMp" - }, { - "type": "Existing Feed", - "alias": "eFeed" + "alias": "" + }] + }, + { + "name": "SAM Collector", + "flowType": "SAM Collector", + "description": "SAM Collector", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "SAMCollector1806", + "alias": "" + }] + }, + { + "name": "SNMP PM Poller", + "flowType": "SNMP PM Poller", + "description": "SNMP PM Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "PM Poller", + "alias": "" + }] + }, + { + "name": "Status Poller Collector", + "flowType": "Status Poller Collector", + "description": "Status Poller Collector", + "category": "Template", + "subCategory": "Base Monitoring Template", + "updateIfExist": "false", + "composition": [ + { + "type": "StatusPoller", + "alias": "" + }] + }, + { + "name": "VES Collector", + "flowType": "VES Collector", + "description": "VES Collector", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "VES Collector", + "alias": "" + }] + }, + { + "name": "VES Fault SE", + "flowType": "VES Fault SE", + "description": "VES Fault SE", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Supplement", + "alias": "" }, { - "type": "Existing Topic", - "alias": "eTopic" + "type": "Enrich", + "alias": "" }], "relations": [{ - "fromComponent": "dMp.DockerMap", - "fromRequirement": "stream_subscribe_0", - "toComponent": "eFeed.feed", - "toCapability": "feed" - }, { - "fromComponent": "dMp.DockerMap", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "DockerMap", - "nodeName": "feed0" - }, - { - "type": "DockerMap", - "nodeName": "topic0" - }] + "fromComponent": "Enrich", + "fromRequirement": "dependency", + "toComponent": "Supplement", + "toCapability": "feature" + }] + }, + { + "name": "Docker Supplement", + "flowType": "Docker Supplement", + "description": "Docker Supplement", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Docker_Supplement", + "alias": "" + }] + }, + { + "name": "Docker Enrich", + "flowType": "Docker Enrich", + "description": "Docker Enrich", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "DockerEnrich", + "alias": "" + }] + }, + { + "name": "MIB Poller", + "flowType": "MIB Poller", + "description": "MIB Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "MIBPoller", + "alias": "" + }] + }, + { + "name": "Discovery Poller", + "flowType": "Discovery Poller", + "description": "Discovery Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Discovery", + "alias": "" + }] }] }
\ No newline at end of file diff --git a/dcaedt_tools/src/test/java/BaseTest.java b/dcaedt_tools/src/test/java/BaseTest.java index f618f2d..d3a6ed5 100644 --- a/dcaedt_tools/src/test/java/BaseTest.java +++ b/dcaedt_tools/src/test/java/BaseTest.java @@ -1,17 +1,16 @@ -import json.response.ElementsResponse.Element; -import json.response.ItemsResponse.Item; -import json.response.ItemsResponse.Model; import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; import utilities.IDcaeRestClient; import utilities.IReport; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; @@ -47,8 +46,7 @@ abstract class BaseTest { public void setup() { when(dcaeRestClient.getUserId()).thenReturn(USER_ID); mockGetAllVfcmt(); - mockGetElements(); - mockGetItems(); + mockGetCatalog(); mockGetItemModel(); mockGetItemType(); mockCheckoutVfcmtAndCreateResource(); @@ -70,46 +68,29 @@ abstract class BaseTest { } private void mockGetItemModel() { - when(dcaeRestClient.getItemModel(anyString())).thenReturn("{\"data\":{\"model\":{\"nodes\":[{\"capability\":{\"type\":\"someType\"}, \"type\":\"type\", \"name\":\"SomeNameFromRequirement\", \"requirements\":[{\"name\":\"SomeNameFromRequirement\"}], \"properties\":[{}], \"capabilities\":[{\"name\":\"SomeNameToCapability\"}],\"type\":\"type\"}]}}}", - "{\"data\":{\"model\":{\"nodes\":[{\"capability\":{\"type\":\"someType\"}, \"type\":\"type\", \"name\":\"SomeNameToCapability\", \"requirements\":[{\"name\":\"SomeNameFromRequirement\"}], \"properties\":[{}], \"capabilities\":[{\"name\":\"SomeNameToCapability\"}],\"type\":\"type\"}]}}}"); + when(dcaeRestClient.getItemModel(anyString())).thenReturn("{\"data\":{\"model\":{\"itemId\":\"\",\"nodes\":[{\"capability\":{\"type\":\"someType\"}, \"type\":\"type\", \"name\":\"SomeNameFromRequirement\", \"requirements\":[{\"name\":\"SomeNameFromRequirement\"}], \"properties\":[{}], \"capabilities\":[{\"name\":\"SomeNameToCapability\"}],\"type\":\"type\"}]}}}", + "{\"data\":{\"model\":{\"itemId\":\"\",\"nodes\":[{\"capability\":{\"type\":\"someType\"}, \"type\":\"type\", \"name\":\"SomeNameToCapability\", \"requirements\":[{\"name\":\"SomeNameFromRequirement\"}], \"properties\":[{}], \"capabilities\":[{\"name\":\"SomeNameToCapability\"}],\"type\":\"type\"}]}}}"); } - private void mockGetItems() { - when(dcaeRestClient.getItem(ELEMENT_NAME1)).thenReturn(null); - List<Item> items = new ArrayList<>(); - Item item = new Item(); - item.setName(ITEM_NAME1); - Model model = new Model(); - model.setItemId(""); - List<Model> models = Collections.singletonList(model); - item.setModels(models); - items.add(item); - item = new Item(); - item.setName(ITEM_NAME2); - item.setModels(models); - items.add(item); - when(dcaeRestClient.getItem(ELEMENT_NAME2)).thenReturn(items); - items = new ArrayList<>(); - item = new Item(); - item.setName(ITEM_NAME3); - item.setModels(models); - items.add(item); - when(dcaeRestClient.getItem(ELEMENT_NAME3)).thenReturn(items); - } + private void mockGetCatalog() { + Map<String, List<Resource>> catalog = new HashMap<>(); + catalog.put(ELEMENT_NAME1, null); + List<Resource> items = new ArrayList<>(); + Resource item = new Resource(); + item.setName(ITEM_NAME1); + items.add(item); + item = new Resource(); + item.setName(ITEM_NAME2); + items.add(item); + catalog.put(ELEMENT_NAME2, items); + items = new ArrayList<>(); + item = new Resource(); + item.setName(ITEM_NAME3); + items.add(item); + catalog.put(ELEMENT_NAME3, items); + when(dcaeRestClient.getDcaeCatalog()).thenReturn(catalog); + } - private void mockGetElements() { - List<Element> elements = new ArrayList<>(); - Element element = new Element(); - element.setName(ELEMENT_NAME1); - elements.add(element); - element = new Element(); - element.setName(ELEMENT_NAME2); - elements.add(element); - element = new Element(); - element.setName(ELEMENT_NAME3); - elements.add(element); - when(dcaeRestClient.getElements()).thenReturn(elements); - } private void mockGetAllVfcmt() { List<ResourceDetailed> resourceDetaileds = new ArrayList<>(); diff --git a/dcaedt_tools/src/test/java/EntitiesRetrieverTest.java b/dcaedt_tools/src/test/java/EntitiesRetrieverTest.java deleted file mode 100644 index ea7eb2b..0000000 --- a/dcaedt_tools/src/test/java/EntitiesRetrieverTest.java +++ /dev/null @@ -1,29 +0,0 @@ - -import json.response.ItemsResponse.Item; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import tools.EntitiesRetriever; - -import java.util.List; -import java.util.Map; - - -public class EntitiesRetrieverTest extends BaseTest { - - @InjectMocks - EntitiesRetriever entitiesRetriever; - - @Before - @Override - public void setup() { - super.setup(); - } - - @Test - public void getElementsByFolder_returns2Items() { - Map<String, List<Item>> result = entitiesRetriever.getElementsByFolder(); - Assert.assertTrue(result.size() == 2); - } -} diff --git a/dcaedt_tools/src/test/java/TemplateContainerTest.java b/dcaedt_tools/src/test/java/TemplateContainerTest.java index b4ddc17..6b09991 100644 --- a/dcaedt_tools/src/test/java/TemplateContainerTest.java +++ b/dcaedt_tools/src/test/java/TemplateContainerTest.java @@ -1,6 +1,4 @@ import com.google.gson.JsonObject; -import json.response.ItemsResponse.Item; -import json.response.ItemsResponse.Model; import json.templateInfo.Composition; import json.templateInfo.NodeToDelete; import json.templateInfo.Relation; @@ -8,6 +6,7 @@ import json.templateInfo.TemplateInfo; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.onap.sdc.dcae.composition.restmodels.sdc.Resource; import tools.TemplateContainer; import java.util.*; @@ -21,7 +20,7 @@ public class TemplateContainerTest extends BaseTest { private TemplateContainer templateContainer; private List<TemplateInfo> templateInfos; - private Map<String, List<Item>> elementsByFolderNames; + private Map<String, List<Resource>> elementsByFolderNames; @Before @Override public void setup() { @@ -36,14 +35,9 @@ public class TemplateContainerTest extends BaseTest { templateInfo.setComposition(Collections.singletonList(composition)); templateInfos.add(templateInfo); elementsByFolderNames = new HashMap<>(); - Item item = new Item(); + Resource item = new Resource(); item.setName(ELEMENT_NAME3); - item.setItemId(""); - Model model = new Model(); - model.setItemId(""); - List<Model> models = Collections.singletonList(model); - item.setModels(models); - List<Item> items = new ArrayList<>(Collections.singletonList(item)); + List<Resource> items = new ArrayList<>(Collections.singletonList(item)); elementsByFolderNames.put(TEMPLATE_INFO_NAME, items); } @@ -60,9 +54,9 @@ public class TemplateContainerTest extends BaseTest { @Test public void getCdumps_returnNotFoundEmptyList() { elementsByFolderNames = new HashMap<>(); - Item item = new Item(); + Resource item = new Resource(); item.setName(ELEMENT_NAME2); - List<Item> items = new ArrayList<>(Collections.singletonList(item)); + List<Resource> items = new ArrayList<>(Collections.singletonList(item)); elementsByFolderNames.put(TEMPLATE_INFO_NAME, items); templateContainer = new TemplateContainer(report, dcaeRestClient, templateInfos, elementsByFolderNames); @@ -126,22 +120,13 @@ public class TemplateContainerTest extends BaseTest { templateInfo.setRelations(Collections.singletonList(relation)); templateInfos.add(templateInfo); elementsByFolderNames = new HashMap<>(); - List<Item> itemList = new ArrayList<>(); - Item item = new Item(); + List<Resource> itemList = new ArrayList<>(); + Resource item = new Resource(); item.setName(ELEMENT_NAME3); - item.setItemId(""); - Model model = new Model(); - model.setItemId(""); - List<Model> models = Collections.singletonList(model); - item.setModels(models); itemList.add(item); - item = new Item(); + item = new Resource(); item.setName(ELEMENT_NAME2); - item.setItemId(""); - model = new Model(); - model.setItemId(""); - models = Collections.singletonList(model); - item.setModels(models); + itemList.add(item); elementsByFolderNames.put(TEMPLATE_INFO_NAME, itemList); templateContainer = new TemplateContainer(report, dcaeRestClient, templateInfos, elementsByFolderNames); diff --git a/dcaedt_validator/README b/dcaedt_validator/README new file mode 100644 index 0000000..0291fa2 --- /dev/null +++ b/dcaedt_validator/README @@ -0,0 +1,9 @@ +Build commons-pipeline separately, it is not a sub-project. +It also needs to be installed in the local repository with 'mvn install' + +Build the validator itself + + +If runnign into problems, clear the local maven repo, + mvn dependency:purge-local-repository -DreResolve=false +and start from the beginning. diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Checker.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Checker.java index bf1843e..c75dc8d 100644 --- a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Checker.java +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Checker.java @@ -1,7 +1,7 @@ package org.onap.sdc.dcae.checker; -import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.io.File; import java.io.Reader; @@ -11,12 +11,9 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; -import java.util.TreeMap; import java.util.Iterator; -import java.util.ListIterator; import java.util.Map; import java.util.List; -import java.util.LinkedList; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; @@ -24,23 +21,22 @@ import java.util.Collection; import java.util.Collections; import java.util.regex.Pattern; import java.util.regex.Matcher; -import java.util.stream.Collectors; +import java.util.stream.IntStream; +import com.google.common.reflect.Invokable; import org.onap.sdc.common.onaplog.OnapLoggerDebug; import org.onap.sdc.common.onaplog.OnapLoggerError; import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.common.*; +import org.onap.sdc.dcae.checker.validation.TOSCAValidator; import org.yaml.snakeyaml.Yaml; -import com.google.common.collect.Maps; -import com.google.common.collect.MapDifference; -import com.google.common.reflect.Invokable; import com.google.common.collect.Table; import com.google.common.collect.HashBasedTable; import kwalify.Validator; import kwalify.Rule; -import kwalify.Types; import kwalify.ValidationException; import kwalify.SchemaException; @@ -53,41 +49,34 @@ import org.reflections.Reflections; import org.reflections.util.FilterBuilder; import org.reflections.util.ConfigurationBuilder; import org.reflections.scanners.TypeAnnotationsScanner; -import org.reflections.scanners.SubTypesScanner; +import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.MethodAnnotationsScanner; +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; +import static org.onap.sdc.dcae.checker.common.ConstCommon.INTERFACE_TYPES; + /* * To consider: model consistency checking happens now along with validation * (is implemented as part of the validation hooks). It might be better to * separate the 2 stages and perform all the consistency checking once * validation is completed. */ -public class Checker { - private static final String PROPERTIES = "properties"; - private static final String DEFAULT = "default"; - private static final String ATTRIBUTES = "attributes"; - private static final String DATA_TYPES = "data_types"; - private static final String CAPABILITY_TYPES = "capability_types"; - private static final String VALID_SOURCE_TYPES = "valid_source_types"; - private static final String RELATIONSHIP_TYPES = "relationship_types"; - private static final String INTERFACES = "interfaces"; - private static final String VALID_TARGET_TYPES = "valid_target_types"; - private static final String ARTIFACT_TYPES = "artifact_types"; - private static final String INTERFACE_TYPES = "interface_types"; - private static final String NODE_TYPES = "node_types"; - private static final String REQUIREMENTS = "requirements"; - private static final String CAPABILITIES = "capabilities"; - private static final String GROUP_TYPES = "group_types"; - private static final String TARGETS_CONSTANT = "targets"; - private static final String POLICY_TYPES = "policy_types"; - private static final String IS_NONE_OF_THOSE = "' is none of those"; - private static final String INPUTS = "inputs"; - private static final String CAPABILITY = "capability"; - private static final String ARTIFACTS = "artifacts"; - private static final String WAS_DEFINED_FOR_THE_NODE_TYPE = " was defined for the node type "; - private static final String UNKNOWN = "Unknown "; - private static final String TYPE = " type "; - public static final String IMPORTED_FROM = "',imported from "; +public class Checker implements IChecker { + + private CheckCommon checkCommon; + private TypeCommon typeCommon; + private ArtifactCommon artifactCommon; + private CapabilityCommon capabilityCommon; + private FacetCommon facetCommon; + private GroupCommon groupCommon; + private InputsOutputsCommon inputsOutputsCommon; + private InterfaceCommon interfaceCommon; + private PropertiesCommon propertiesCommon; + private RelationshipCommon relationshipCommon; + private NodeCommon nodeCommon; + private PolicyCommon policyCommon; + private RequirementCommon requirementCommon; + private AttributesCommon attributesCommon; private Target target = null; //what we're validating at the moment @@ -104,7 +93,10 @@ public class Checker { private static Catalog commonsCatalogInstance = null; - private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static Class[] validationHookArgTypes = + new Class[]{Object.class, Rule.class, Validator.ValidationContext.class}; + + /* Need a proper way to indicate where the grammars are and how they should be identified */ private static final String[] grammarFiles = new String[]{"tosca/tosca_simple_yaml_1_0.grammar", @@ -120,14 +112,90 @@ public class Checker { new Class[]{Map.class, CheckContext.class}, new Class[]{List.class, CheckContext.class}}; - private static Class[] validationHookArgTypes = - new Class[]{Object.class, Rule.class, Validator.ValidationContext.class}; + public Checker() throws CheckerException { + initCommons(); + loadGrammars(); loadAnnotations(); } + private void initCommons() { + NodeCommon.init(this); + InterfaceCommon.init(this); + checkCommon = CheckCommon.getInstance(); + typeCommon = TypeCommon.getInstance(); + artifactCommon = ArtifactCommon.getInstance(); + capabilityCommon = CapabilityCommon.getInstance(); + facetCommon = FacetCommon.getInstance(); + groupCommon = GroupCommon.getInstance(); + inputsOutputsCommon = InputsOutputsCommon.getInstance(); + interfaceCommon = InterfaceCommon.getInstance(); + propertiesCommon = PropertiesCommon.getInstance(); + relationshipCommon = RelationshipCommon.getInstance(); + nodeCommon = NodeCommon.getInstance(); + policyCommon = PolicyCommon.getInstance(); + requirementCommon = RequirementCommon.getInstance(); + attributesCommon = AttributesCommon.getInstance(); + } + + @FunctionalInterface + interface Function<A, B, C, D> { + void function(String key, Map value, Checker.CheckContext theContext, Catalog catalog); + + } + + @FunctionalInterface + interface FunctionWithoutCatalog<A, B, C> { + void function(String key, Map value, Checker.CheckContext theContext); + + } + @FunctionalInterface + interface FunctionWithTarget<A, B, C, D, E> { + void function(String key, Map value, Checker.CheckContext theContext, Catalog catalog, Target target); + } + + private void abstractCheck(Function function, Map<String, Map> stringMapMap, Checker.CheckContext theContext, String type) { + theContext.enter(type); + try { + if (!checkCommon.checkDefinition(type, stringMapMap, theContext)) { + return; + } + + stringMapMap.forEach((key, value) -> function.function(key, value, theContext, catalog)); + } finally { + theContext.exit(); + } + } + + private void abstractCheck(FunctionWithoutCatalog function, Map<String, Map> stringMapMap, Checker.CheckContext theContext, String type) { + theContext.enter(type); + try { + if (!checkCommon.checkDefinition(type, stringMapMap, theContext)) { + return; + } + + stringMapMap.forEach((key, value) -> function.function(key, value, theContext)); + } finally { + theContext.exit(); + } + } + + private void abstractCheck(FunctionWithTarget function, Map<String, Map> stringMapMap, Checker.CheckContext theContext, String type) { + theContext.enter(type); + try { + if (!checkCommon.checkDefinition(type, stringMapMap, theContext)) { + return; + } + + stringMapMap.forEach((key, value) -> function.function(key, value, theContext, catalog, target)); + } finally { + theContext.exit(); + } + } + + public static void main(String[] theArgs) { if (theArgs.length == 0) { errLogger.log(LogLevel.ERROR, Checker.class.getName(), "checker resource_to_validate [processor]*"); @@ -137,13 +205,9 @@ public class Checker { try { Catalog cat = Checker.check(new File(theArgs[0])); - for (Target t : cat.targets()) { - errLogger.log(LogLevel.ERROR, Checker.class.getName(), "{}\n{}\n{}", t.getLocation(), cat.importString(t), t.getReport()); - } + cat.targets().forEach(t -> errLogger.log(LogLevel.ERROR, Checker.class.getName(), "{}\n{}\n{}", t.getLocation(), cat.importString(t), t.getReport())); - for (Target t : cat.sortedTargets()) { - errLogger.log(LogLevel.ERROR, Checker.class.getName(), t.toString()); - } + cat.sortedTargets().forEach(t -> errLogger.log(LogLevel.ERROR, Checker.class.getName(), t.toString())); } catch (Exception x) { errLogger.log(LogLevel.ERROR, Checker.class.getName(),"Exception {}", x); @@ -206,34 +270,30 @@ public class Checker { Map<Class, Object> handlers = new HashMap<>(); Set<Method> checkHandlers = reflections.getMethodsAnnotatedWith(Checks.class); - for (Method checkHandler : checkHandlers) { - checks.put(checkHandler.getAnnotation(Checks.class).path(), - checkHandler, - handlers.computeIfAbsent(checkHandler.getDeclaringClass(), - type -> { - try { - return (getClass() == type) ? this - : type.newInstance(); - } catch (Exception x) { - throw new RuntimeException(x); - } - })); - } + checkHandlers.forEach(checkHandler -> checks.put(checkHandler.getAnnotation(Checks.class).path(), + checkHandler, + handlers.computeIfAbsent(checkHandler.getDeclaringClass(), + type -> { + try { + return (getClass() == type) ? this + : type.newInstance(); + } catch (Exception x) { + throw new RuntimeException(x); + } + }))); Set<Method> catalogHandlers = reflections.getMethodsAnnotatedWith(Catalogs.class); - for (Method catalogHandler : catalogHandlers) { - catalogs.put(catalogHandler.getAnnotation(Catalogs.class).path(), - catalogHandler, - handlers.computeIfAbsent(catalogHandler.getDeclaringClass(), - type -> { - try { - return (getClass() == type) ? this - : type.newInstance(); - } catch (Exception x) { - throw new RuntimeException(x); - } - })); - } + catalogHandlers.forEach(catalogHandler -> catalogs.put(catalogHandler.getAnnotation(Catalogs.class).path(), + catalogHandler, + handlers.computeIfAbsent(catalogHandler.getDeclaringClass(), + type -> { + try { + return (getClass() == type) ? this + : type.newInstance(); + } catch (Exception x) { + throw new RuntimeException(x); + } + }))); } @@ -341,7 +401,7 @@ public class Checker { throws CheckerException { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "parseTarget {}", theTarget); - Reader source = null; + Reader source; try { source = theTarget.open(); } catch (IOException iox) { @@ -375,15 +435,15 @@ public class Checker { targets.add(theTarget); } else { //the target turned out to be a stream containing multiple documents - for (int i = 0; i < yamlRoots.size(); i++) { -/* -!!We're changing the target below, i.e. we're changing the target implementation hence caching implementation will suffer!! -*/ + /* + !!We're changing the target below, i.e. we're changing the target implementation hence caching implementation will suffer!! + */ + IntStream.range(0, yamlRoots.size()).forEach(i -> { Target newTarget = new Target(theTarget.getName(), fragmentTargetURI(theTarget.getLocation(), String.valueOf(i))); newTarget.setTarget(yamlRoots.get(i)); targets.add(newTarget); - } + }); } debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), getClass().getName(), " exiting parseTarget {}", theTarget); @@ -418,7 +478,7 @@ public class Checker { TOSCAValidator validator = null; try { - validator = new TOSCAValidator(theTarget, grammar.getTarget()); + validator = new TOSCAValidator(theTarget, grammar.getTarget(), this); } catch (SchemaException sx) { throw new CheckerException("Grammar error at: " + sx.getPath(), sx); } @@ -427,7 +487,7 @@ public class Checker { validator.validate(theTarget.getTarget())); if (!theTarget.getReport().hasErrors()) { - applyCanonicals(theTarget.getTarget(), validator.canonicals); + applyCanonicals(theTarget.getTarget(), validator.getCanonicals()); } debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), getClass().getName(), " exiting validateTarget {}", theTarget); @@ -447,74 +507,6 @@ public class Checker { return theTarget; } - public void checkProperties( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(PROPERTIES); - try { - if (!checkDefinition(PROPERTIES, theDefinitions, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkPropertyDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkPropertyDefinition( - String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName); - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - //check the type - if (!checkDataType(theDefinition, theContext)) { - return; - } - //check default value is compatible with type - Object defaultValue = theDefinition.get(DEFAULT); - if (defaultValue != null) { - checkDataValuation(defaultValue, theDefinition, theContext); - } - - theContext.exit(); - } - - private void checkAttributes( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(ATTRIBUTES); - try { - if (!checkDefinition(ATTRIBUTES, theDefinitions, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkAttributeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkAttributeDefinition( - String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - if (!checkDataType(theDefinition, theContext)) { - return; - } - } finally { - theContext.exit(); - } - } - /* top level rule, we collected the whole information set. * this is where checking starts */ @@ -530,760 +522,12 @@ public class Checker { //!!! imports need to be processed first now that catalogging takes place at check time!! //first catalog whatever it is there to be cataloged so that the checks can perform cross-checking - for (Iterator<Map.Entry<String, Object>> ri = theDef.entrySet().iterator(); - ri.hasNext(); ) { - Map.Entry<String, Object> e = ri.next(); - catalogs(e.getKey(), e.getValue(), theContext); - } + theDef.forEach((key, value) -> catalogs(key, value, theContext)); - for (Iterator<Map.Entry<String, Object>> ri = theDef.entrySet().iterator(); - ri.hasNext(); ) { - Map.Entry<String, Object> e = ri.next(); - checks(e.getKey(), e.getValue(), theContext); - } + theDef.forEach((key, value) -> checks(key, value, theContext)); theContext.exit(); } - @Catalogs(path = "/data_types") - protected void catalog_data_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(DATA_TYPES); - try { - catalogTypes(Construct.Data, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - @Checks(path = "/data_types") - protected void check_data_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(DATA_TYPES); - - try { - if (!checkDefinition(DATA_TYPES, theDefinitions, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkDataTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkDataTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Data); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Data, theName, theDefinition, - Facet.properties, theContext); - } - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/capability_types") - protected void catalog_capability_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(CAPABILITY_TYPES); - try { - catalogTypes(Construct.Capability, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/capability_types") - protected void check_capability_types( - Map<String, Map> theTypes, CheckContext theContext) { - theContext.enter(CAPABILITY_TYPES); - try { - if (!checkDefinition(CAPABILITY_TYPES, theTypes, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theTypes.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkCapabilityTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkCapabilityTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Capability); - - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Capability, theName, theDefinition, - Facet.properties, theContext); - } - - if (theDefinition.containsKey(ATTRIBUTES)) { - checkAttributes( - (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext); - checkTypeConstructFacet(Construct.Capability, theName, theDefinition, - Facet.attributes, theContext); - } - - //valid_source_types: see capability_type_definition - //unclear: how is the valid_source_types list definition eveolving across - //the type hierarchy: additive, overwriting, ?? - if (theDefinition.containsKey(VALID_SOURCE_TYPES)) { - checkTypeReference(Construct.Node, theContext, - ((List<String>) theDefinition.get(VALID_SOURCE_TYPES)).toArray(EMPTY_STRING_ARRAY)); - } - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/relationship_types") - protected void catalog_relationship_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(RELATIONSHIP_TYPES); - try { - catalogTypes(Construct.Relationship, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/relationship_types") - protected void check_relationship_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(RELATIONSHIP_TYPES); - try { - if (!checkDefinition(RELATIONSHIP_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkRelationshipTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkRelationshipTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Relationship); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, - Facet.properties, theContext); - } - - if (theDefinition.containsKey(ATTRIBUTES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext); - checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, - Facet.attributes, theContext); - } - - Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get(INTERFACES); - if (interfaces != null) { - theContext.enter(INTERFACES); - for (Iterator<Map.Entry<String, Map>> i = - interfaces.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - check_type_interface_definition( - e.getKey(), e.getValue(), theContext); - } - theContext.exit(); - } - - if (theDefinition.containsKey(VALID_TARGET_TYPES)) { - checkTypeReference(Construct.Capability, theContext, - ((List<String>) theDefinition.get(VALID_TARGET_TYPES)).toArray(EMPTY_STRING_ARRAY)); - } - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/artifact_types") - protected void catalog_artifact_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(ARTIFACT_TYPES); - try { - catalogTypes(Construct.Artifact, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/artifact_types") - protected void check_artifact_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(ARTIFACT_TYPES); - try { - if (!checkDefinition(ARTIFACT_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkArtifactTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkArtifactTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Artifact); - try { - checkDefinition(theName, theDefinition, theContext); - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/interface_types") - protected void catalog_interface_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(INTERFACE_TYPES); - try { - catalogTypes(Construct.Interface, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - @Checks(path = "/interface_types") - protected void check_interface_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(INTERFACE_TYPES); - try { - if (!checkDefinition(INTERFACE_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkInterfaceTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkInterfaceTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Interface); - try { - checkDefinition(theName, theDefinition, theContext); - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/node_types") - protected void catalog_node_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(NODE_TYPES); - try { - catalogTypes(Construct.Node, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/node_types") - protected void check_node_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(NODE_TYPES); - try { - if (!checkDefinition(NODE_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkNodeTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkNodeTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Node); - - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Node, theName, theDefinition, - Facet.properties, theContext); - } - - if (theDefinition.containsKey(ATTRIBUTES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext); - checkTypeConstructFacet(Construct.Node, theName, theDefinition, - Facet.attributes, theContext); - } - - //requirements - if (theDefinition.containsKey(REQUIREMENTS)) { - check_requirements( - (List<Map>) theDefinition.get(REQUIREMENTS), theContext); - } - - //capabilities - if (theDefinition.containsKey(CAPABILITIES)) { - check_capabilities( - (Map<String, Map>) theDefinition.get(CAPABILITIES), theContext); - } - - //interfaces: - Map<String, Map> interfaces = - (Map<String, Map>) theDefinition.get(INTERFACES); - checkMapTypeInterfaceDefinition(theContext, interfaces); - } finally { - theContext.exit(); - } - } - - private void checkMapTypeInterfaceDefinition(CheckContext theContext, Map<String, Map> interfaces) { - if (interfaces != null) { - try { - theContext.enter(INTERFACES); - for (Iterator<Map.Entry<String, Map>> i = - interfaces.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - check_type_interface_definition( - e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - } - - @Catalogs(path = "/group_types") - protected void catalog_group_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(GROUP_TYPES); - try { - catalogTypes(Construct.Group, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - @Checks(path = "/group_types") - protected void check_group_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(GROUP_TYPES); - try { - if (!checkDefinition(GROUP_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkGroupTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkGroupTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Group); - - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Group, theName, theDefinition, - Facet.properties, theContext); - } - - if (theDefinition.containsKey(TARGETS_CONSTANT)) { - checkTypeReference(Construct.Node, theContext, - ((List<String>) theDefinition.get(TARGETS_CONSTANT)).toArray(EMPTY_STRING_ARRAY)); - } - - //interfaces - Map<String, Map> interfaces = - (Map<String, Map>) theDefinition.get(INTERFACES); - checkMapTypeInterfaceDefinition(theContext, interfaces); - - } finally { - theContext.exit(); - } - } - - @Catalogs(path = "/policy_types") - protected void catalog_policy_types( - Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(POLICY_TYPES); - try { - catalogTypes(Construct.Policy, theDefinitions, theContext); - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/policy_types") - protected void check_policy_types( - Map<String, Map> theDefinition, CheckContext theContext) { - theContext.enter(POLICY_TYPES); - try { - if (!checkDefinition(POLICY_TYPES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkPolicyTypeDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkPolicyTypeDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - theContext.enter(theName, Construct.Policy); - - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - - if (theDefinition.containsKey(PROPERTIES)) { - checkProperties( - (Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Policy, theName, theDefinition, - Facet.properties, theContext); - } - - //the targets can be known node types or group types - List<String> targets = (List<String>) theDefinition.get(TARGETS_CONSTANT); - if ((targets != null) && (checkDefinition(TARGETS_CONSTANT, targets, theContext))) { - for (String targetItr : targets) { - if (!(this.catalog.hasType(Construct.Node, targetItr) || - this.catalog.hasType(Construct.Group, targetItr))) { - theContext.addError("The 'targets' entry must contain a reference to a node type or group type, '" + target + IS_NONE_OF_THOSE, null); - } - } - } - } finally { - theContext.exit(); - } - } - - //checking of actual constructs (capability, ..) - - /* First, interface types do not have a hierarchical organization (no - * 'derived_from' in a interface type definition). - * So, when interfaces (with a certain type) are defined in a node - * or relationship type (and they can define new? operations), what - * is there to check: - * Can operations here re-define their declaration from the interface - * type spec?? From A.5.11.3 we are to understand indicates override to be - * the default interpretation .. but they talk about sub-classing so it - * probably intended as a reference to the node or relationship type - * hierarchy and not the interface type (no hierarchy there). - * Or is this a a case of augmentation where new operations can be added?? - */ - private void check_type_interface_definition( - String theName, Map theDef, CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - - if (!checkType(Construct.Interface, theDef, theContext)) { - return; - } - - if (theDef.containsKey(INPUTS)) { - check_inputs((Map<String, Map>) theDef.get(INPUTS), theContext); - } - } finally { - theContext.exit(); - } - } - - private void check_capabilities(Map<String, Map> theDefinition, - CheckContext theContext) { - theContext.enter(CAPABILITIES); - try { - if (!checkDefinition(CAPABILITIES, theDefinition, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkCapabilityDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - /* A capability definition appears within the context ot a node type */ - private void checkCapabilityDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName, Construct.Capability); - - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - - //check capability type - if (!checkType(Construct.Capability, theDef, theContext)) { - return; - } - - //check properties - if (!checkFacetAugmentation( - Construct.Capability, theDef, Facet.properties, theContext)) { - return; - } - - //check attributes - if (!checkFacetAugmentation( - Construct.Capability, theDef, Facet.attributes, theContext)) { - return; - } - - //valid_source_types: should point to valid template nodes - if (theDef.containsKey(VALID_SOURCE_TYPES)) { - checkTypeReference(Construct.Node, theContext, - ((List<String>) theDef.get(VALID_SOURCE_TYPES)).toArray(EMPTY_STRING_ARRAY)); - //per A.6.1.4 there is an additinal check to be performed here: - //"Any Node Type (names) provides as values for the valid_source_types keyname SHALL be type-compatible (i.e., derived from the same parent Node Type) with any Node Types defined using the same keyname in the parent Capability Type." - } - //occurences: were verified in range_definition - - } finally { - theContext.exit(); - } - } - - private void check_requirements(List<Map> theDefinition, - CheckContext theContext) { - theContext.enter(REQUIREMENTS); - try { - if (!checkDefinition(REQUIREMENTS, theDefinition, theContext)) { - return; - } - - for (Iterator<Map> i = theDefinition.iterator(); i.hasNext(); ) { - Map e = i.next(); - Iterator<Map.Entry<String, Map>> ei = - (Iterator<Map.Entry<String, Map>>) e.entrySet().iterator(); - Map.Entry<String, Map> eie = ei.next(); - checkRequirementDefinition(eie.getKey(), eie.getValue(), theContext); - assert !ei.hasNext(); - } - } finally { - theContext.exit(); - } - } - - private void checkRequirementDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName, Construct.Requirement); - - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - //check capability type - String capabilityType = (String) theDef.get(CAPABILITY); - if (null != capabilityType) { - checkTypeReference(Construct.Capability, theContext, capabilityType); - } - - //check node type - String nodeType = (String) theDef.get("node"); - if (null != nodeType) { - checkTypeReference(Construct.Node, theContext, nodeType); - } - - //check relationship type - Map relationshipSpec = (Map) theDef.get("relationship"); - String relationshipType = null; - if (null != relationshipSpec) { - relationshipType = (String) relationshipSpec.get("type"); - if (relationshipType != null) { //should always be the case - checkTypeReference(Construct.Relationship, theContext, relationshipType); - } - - Map<String, Map> interfaces = (Map<String, Map>) - relationshipSpec.get(INTERFACES); - if (interfaces != null) { - //augmentation (additional properties or operations) of the interfaces - //defined by the above relationship types - - //check that the interface types are known - for (Map interfaceDef : interfaces.values()) { - checkType(Construct.Interface, interfaceDef, theContext); - } - } - } - - //cross checks - - //the capability definition might come from the capability type or from the capability definition - //within the node type. We might have more than one as a node might specify multiple capabilities of the - //same type. - //the goal here is to cross check the compatibility of the valid_source_types specification in the - //target capability definition (if that definition contains a valid_source_types entry). - List<Map> capabilityDefs = new LinkedList<>(); - //nodeType exposes capabilityType - if (nodeType != null) { - Map<String, Map> capabilities = - findTypeFacetByType(Construct.Node, nodeType, - Facet.capabilities, capabilityType); - if (capabilities.isEmpty()) { - theContext.addError("The node type " + nodeType + " does not appear to expose a capability of a type compatible with " + capabilityType, null); - } else { - for (Map.Entry<String, Map> capability : capabilities.entrySet()) { - //this is the capability as it was defined in the node type - Map capabilityDef = capability.getValue(); - //if it defines a valid_source_types then we're working with it, - //otherwise we're working with the capability type it points to. - //The spec does not make it clear if the valid_source_types in a capability definition augments or - //overwrites the one from the capabilityType (it just says they must be compatible). - if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { - capabilityDefs.add(capabilityDef); - } else { - capabilityDef = - catalog.getTypeDefinition(Construct.Capability, (String) capabilityDef.get("type")); - if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { - capabilityDefs.add(capabilityDef); - } else { - //!!if there is a capability that does not have a valid_source_type than there is no reason to - //make any further verification (as there is a valid node_type/capability target for this requirement) - capabilityDefs.clear(); - break; - } - } - } - } - } else { - Map capabilityDef = catalog.getTypeDefinition(Construct.Capability, capabilityType); - if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { - capabilityDefs.add(capabilityDef); - } - } - - //check that the node type enclosing this requirement definition - //is in the list of valid_source_types - if (!capabilityDefs.isEmpty()) { - String enclosingNodeType = - theContext.enclosingConstruct(Construct.Node); - assert enclosingNodeType != null; - - if (!capabilityDefs.stream().anyMatch( - (Map capabilityDef) -> { - List<String> valid_source_types = - (List<String>) capabilityDef.get(VALID_SOURCE_TYPES); - return valid_source_types.stream().anyMatch( - (String source_type) -> catalog.isDerivedFrom( - Construct.Node, enclosingNodeType, source_type)); - })) { - theContext.addError("Node type: " + enclosingNodeType + " not compatible with any of the valid_source_types provided in the definition of compatible capabilities", null); - } - } - - //if we have a relationship type, check if it has a valid_target_types - //if it does, make sure that the capability type is compatible with one - //of them - if (relationshipType != null) { //should always be the case - Map relationshipTypeDef = catalog.getTypeDefinition( - Construct.Relationship, relationshipType); - if (relationshipTypeDef != null) { - List<String> valid_target_types = - (List<String>) relationshipTypeDef.get(VALID_TARGET_TYPES); - if (valid_target_types != null) { - boolean found = false; - for (String target_type : valid_target_types) { - if (catalog.isDerivedFrom( - Construct.Capability, capabilityType, target_type)) { - found = true; - break; - } - } - if (!found) { - theContext.addError("Capability type: " + capabilityType + " not compatible with any of the valid_target_types " + valid_target_types + " provided in the definition of relationship type " + relationshipType, null); - } - } - } - } - - //relationship declares the capabilityType in its valid_target_type set - //in A.6.9 'Relationship Type' the spec does not indicate how inheritance - //is to be applied to the valid_target_type spec: cumulative, overwrites, - //so we treat it as an overwrite. - } finally { - theContext.exit(); - } - } //topology_template_definition and sub-rules /* */ @@ -1308,8 +552,7 @@ public class Checker { protected void check_imports(List theImports, CheckContext theContext) { theContext.enter("imports"); - for (ListIterator li = theImports.listIterator(); li.hasNext(); ) { - Object importEntry = li.next(); + for (Object importEntry : theImports) { Object importFile = ((Map) mapEntry(importEntry).getValue()).get("file"); Target tgt = null; try { @@ -1331,1360 +574,11 @@ public class Checker { theContext.exit(); } - /* */ - @Checks(path = "/topology_template/substitution_mappings") - protected void check_substitution_mappings(Map<String, Object> theSub, - CheckContext theContext) { - theContext.enter("substitution_mappings"); - try { - //type is mandatory - String type = (String) theSub.get("node_type"); - if (!checkTypeReference(Construct.Node, theContext, type)) { - theContext.addError("Unknown node type: " + type + "", null); - return; //not much to go on with - } - - Map<String, List> capabilities = (Map<String, List>) theSub.get(CAPABILITIES); - if (null != capabilities) { - for (Map.Entry<String, List> ce : capabilities.entrySet()) { - //the key must be a capability of the type - if (null == findTypeFacetByName(Construct.Node, type, - Facet.capabilities, ce.getKey())) { - theContext.addError("Unknown node type capability: " + ce.getKey() + ", type " + type, null); - } - //the value is a 2 element list: first is a local node, - //second is the name of one of its capabilities - List targetList = ce.getValue(); - if (targetList.size() != 2) { - theContext.addError("Invalid capability mapping: " + target + ", expecting 2 elements", null); - continue; - } - - String targetNode = (String) targetList.get(0); - String targetCapability = (String) targetList.get(1); - - Map<String, Object> targetNodeDef = (Map<String, Object>) - this.catalog.getTemplate(theContext.target(), Construct.Node, targetNode); - if (null == targetNodeDef) { - theContext.addError("Invalid capability mapping node template: " + targetNode, null); - continue; - } - - String targetNodeType = (String) targetNodeDef.get("type"); - if (null == findTypeFacetByName(Construct.Node, targetNodeType, - Facet.capabilities, targetCapability)) { - theContext.addError("Invalid capability mapping capability: " + targetCapability + ". No such capability found for node template " + targetNode + ", of type " + targetNodeType, null); - } - } - } - - Map<String, List> requirements = (Map<String, List>) theSub.get(REQUIREMENTS); - if (null != requirements) { - for (Map.Entry<String, List> re : requirements.entrySet()) { - //the key must be a requirement of the type - if (null == findNodeTypeRequirementByName(type, re.getKey())) { - theContext.addError("Unknown node type requirement: " + re.getKey() + ", type " + type, null); - } - - List targetList = re.getValue(); - if (targetList.size() != 2) { - theContext.addError("Invalid requirement mapping: " + targetList + ", expecting 2 elements", null); - continue; - } - - String targetNode = (String) targetList.get(0); - String targetRequirement = (String) targetList.get(1); - - Map<String, Object> targetNodeDef = (Map<String, Object>) - this.catalog.getTemplate(theContext.target(), Construct.Node, targetNode); - if (null == targetNodeDef) { - theContext.addError("Invalid requirement mapping node template: " + targetNode, null); - continue; - } - - String targetNodeType = (String) targetNodeDef.get("type"); - if (null == findNodeTypeRequirementByName(targetNodeType, targetRequirement)) { - theContext.addError("Invalid requirement mapping requirement: " + targetRequirement + ". No such requirement found for node template " + targetNode + ", of type " + targetNodeType, null); - } - } - } - } finally { - theContext.exit(); - } - } - - - /* */ - @Checks(path = "/topology_template/inputs") - protected void check_inputs(Map<String, Map> theInputs, - CheckContext theContext) { - theContext.enter(INPUTS); - - try { - if (!checkDefinition(INPUTS, theInputs, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theInputs.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkInputDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkInputDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - // - if (!checkDataType(theDef, theContext)) { - return; - } - //check default value - Object defaultValue = theDef.get(DEFAULT); - if (defaultValue != null) { - checkDataValuation(defaultValue, theDef, theContext); - } - } finally { - theContext.exit(); - } - } - - @Checks(path = "topology_template/outputs") - protected void check_outputs(Map<String, Map> theOutputs, - CheckContext theContext) { - theContext.enter("outputs"); - - try { - if (!checkDefinition("outputs", theOutputs, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theOutputs.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkOutputDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkOutputDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName); - try { - checkDefinition(theName, theDef, theContext); - //check the expression - } finally { - theContext.exit(); - } - } - - @Checks(path = "/topology_template/groups") - protected void check_groups(Map<String, Map> theGroups, - CheckContext theContext) { - theContext.enter("groups"); - - try { - if (!checkDefinition("groups", theGroups, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theGroups.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkGroupDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkGroupDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - - if (!checkType(Construct.Group, theDef, theContext)) { - return; - } - - if (!checkFacet( - Construct.Group, theDef, Facet.properties, theContext)) { - return; - } - - if (theDef.containsKey(TARGETS_CONSTANT)) { - - List<String> targetsTypes = (List<String>) - this.catalog.getTypeDefinition(Construct.Group, - (String) theDef.get("type")) - .get(TARGETS_CONSTANT); - - List<String> targets = (List<String>) theDef.get(TARGETS_CONSTANT); - for (String targetItr : targets) { - if (!this.catalog.hasTemplate(theContext.target(), Construct.Node, targetItr)) { - theContext.addError("The 'targets' entry must contain a reference to a node template, '" + targetItr + "' is not one", null); - } else { - if (targetsTypes != null) { - String targetType = (String) - this.catalog.getTemplate(theContext.target(), Construct.Node, targetItr).get("type"); - - boolean found = false; - for (String type : targetsTypes) { - found = this.catalog - .isDerivedFrom(Construct.Node, targetType, type); - if (found) { - break; - } - } - - if (!found) { - theContext.addError("The 'targets' entry '" + targetItr + "' is not type compatible with any of types specified in policy type targets", null); - } - } - } - } - } - } finally { - theContext.exit(); - } - } - - @Checks(path = "/topology_template/policies") - protected void check_policies(List<Map<String, Map>> thePolicies, - CheckContext theContext) { - theContext.enter("policies"); - - try { - if (!checkDefinition("policies", thePolicies, theContext)) { - return; - } - - for (Map<String, Map> policy : thePolicies) { - assert policy.size() == 1; - Map.Entry<String, Map> e = policy.entrySet().iterator().next(); - checkPolicyDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkPolicyDefinition(String theName, - Map theDef, - CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - - if (!checkType(Construct.Policy, theDef, theContext)) { - return; - } - - if (!checkFacet( - Construct.Policy, theDef, Facet.properties, theContext)) { - return; - } - - //targets: must point to node or group templates (that are of a type - //specified in the policy type definition, if targets were specified - //there). - if (theDef.containsKey(TARGETS_CONSTANT)) { - List<String> targetsTypes = (List<String>) - this.catalog.getTypeDefinition(Construct.Policy, - (String) theDef.get("type")) - .get(TARGETS_CONSTANT); - - List<String> targets = (List<String>) theDef.get(TARGETS_CONSTANT); - for (String targetItr : targets) { - Construct targetConstruct = null; - - if (this.catalog.hasTemplate(theContext.target(), Construct.Group, targetItr)) { - targetConstruct = Construct.Group; - } else if (this.catalog.hasTemplate(theContext.target(), Construct.Node, targetItr)) { - targetConstruct = Construct.Node; - } else { - theContext.addError("The 'targets' entry must contain a reference to a node template or group template, '" + target + IS_NONE_OF_THOSE, null); - } - - if (targetConstruct != null && - targetsTypes != null) { - //get the target type and make sure is compatible with the types - //indicated in the type spec - String targetType = (String) - this.catalog.getTemplate(theContext.target(), targetConstruct, targetItr).get("type"); - - boolean found = false; - for (String type : targetsTypes) { - found = this.catalog - .isDerivedFrom(targetConstruct, targetType, type); - if (found) { - break; - } - } - - if (!found) { - theContext.addError("The 'targets' " + targetConstruct + " entry '" + targetItr + "' is not type compatible with any of types specified in policy type targets", null); - } - } - } - } - - } finally { - theContext.exit(); - } - } - - /* */ - @Checks(path = "/topology_template/node_templates") - protected void check_node_templates(Map<String, Map> theTemplates, - CheckContext theContext) { - theContext.enter("node_templates"); - try { - if (!checkDefinition("node_templates", theTemplates, theContext)) { - return; - } - - for (Iterator<Map.Entry<String, Map>> i = theTemplates.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkNodeTemplateDefinition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } - - /* */ - private void checkNodeTemplateDefinition(String theName, - Map theNode, - CheckContext theContext) { - theContext.enter(theName, Construct.Node); - - try { - if (!checkDefinition(theName, theNode, theContext)) { - return; - } - - if (!checkType(Construct.Node, theNode, theContext)) { - return; - } - - //copy - String copy = (String) theNode.get("copy"); - if (copy != null) { - if (!checkTemplateReference(Construct.Node, theContext, copy)) { - theContext.addError("The 'copy' reference " + copy + " does not point to a known node template", null); - } else { - //the 'copy' node specification should be used to provide 'defaults' - //for this specification - } - } - - /* check that we operate on properties and attributes within the scope of - the specified node type */ - if (!checkFacet( - Construct.Node, /*theName,*/theNode, Facet.properties, theContext)) { - return; - } - - if (!checkFacet( - Construct.Node, /*theName,*/theNode, Facet.attributes, theContext)) { - return; - } - - //requirement assignment seq - if (theNode.containsKey(REQUIREMENTS)) { - checkRequirementsAssignmentDefinition( - (List<Map>) theNode.get(REQUIREMENTS), theContext); - } - - //capability assignment map: subject to augmentation - if (theNode.containsKey(CAPABILITIES)) { - checkCapabilitiesAssignmentDefinition( - (Map<String, Map>) theNode.get(CAPABILITIES), theContext); - } - - //interfaces - if (theNode.containsKey(INTERFACES)) { - checkTemplateInterfacesDefinition( - (Map<String, Map>) theNode.get(INTERFACES), theContext); - } - - //artifacts: artifacts do not have different definition forms/syntax - //depending on the context (type or template) but they are still subject - //to 'augmentation' - if (theNode.containsKey(ARTIFACTS)) { - check_template_artifacts_definition( - (Map<String, Object>) theNode.get(ARTIFACTS), theContext); - } - - /* node_filter: the context to which the node filter is applied is very - * wide here as opposed to the node filter specification in a requirement - * assignment which has a more strict context (target node/capability are - * specified). - * We could check that there are nodes in this template having the - * properties/capabilities specified in this filter, i.e. the filter has - * a chance to succeed. - */ - } finally { - theContext.exit(); - } - } - - @Checks(path = "/topology_template/relationship_templates") - protected void check_relationship_templates(Map theTemplates, - CheckContext theContext) { - theContext.enter("relationship_templates"); - - for (Iterator<Map.Entry<String, Map>> i = theTemplates.entrySet().iterator(); i.hasNext(); ) { - Map.Entry<String, Map> e = i.next(); - checkRelationshipTemplateDefinition(e.getKey(), e.getValue(), theContext); - } - theContext.exit(); - } - - private void checkRelationshipTemplateDefinition( - String theName, - Map theRelationship, - CheckContext theContext) { - theContext.enter(theName, Construct.Relationship); - try { - if (!checkDefinition(theName, theRelationship, theContext)) { - return; - } - - if (!checkType(Construct.Relationship, theRelationship, theContext)) { - return; - } - - /* check that we operate on properties and attributes within the scope of - the specified relationship type */ - if (!checkFacet(Construct.Relationship, theRelationship, - Facet.properties, theContext)) { - return; - } - - if (!checkFacet(Construct.Relationship, theRelationship, - Facet.attributes, theContext)) { - return; - } - - /* interface definitions - note: augmentation is allowed here so not clear what to check .. - maybe report augmentations if so configured .. */ - - } finally { - theContext.exit(); - } - } - - //requirements and capabilities assignment appear in a node templates - private void checkRequirementsAssignmentDefinition( - List<Map> theRequirements, CheckContext theContext) { - theContext.enter(REQUIREMENTS); - try { - if (!checkDefinition(REQUIREMENTS, theRequirements, theContext)) { - return; - } - - //the node type for the node template enclosing these requirements - String nodeType = (String) catalog.getTemplate( - theContext.target(), - Construct.Node, - theContext.enclosingConstruct(Construct.Node)) - .get("type"); - - for (Iterator<Map> ri = theRequirements.iterator(); ri.hasNext(); ) { - Map<String, Map> requirement = (Map<String, Map>) ri.next(); - - Iterator<Map.Entry<String, Map>> rai = requirement.entrySet().iterator(); - - Map.Entry<String, Map> requirementEntry = rai.next(); - assert !rai.hasNext(); - - String requirementName = requirementEntry.getKey(); - Map requirementDef = findNodeTypeRequirementByName( - nodeType, requirementName); - - if (requirementDef == null) { - theContext.addError("No requirement " + requirementName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); - continue; - } - - checkRequirementAssignmentDefinition( - requirementName, requirementEntry.getValue(), requirementDef, theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkRequirementAssignmentDefinition( - String theRequirementName, - Map theAssignment, - Map theDefinition, - CheckContext theContext) { - theContext//.enter("requirement_assignment") - .enter(theRequirementName, Construct.Requirement); - - //grab the node type definition to verify compatibility - - try { - //node assignment - boolean targetNodeIsTemplate = false; - String targetNode = (String) theAssignment.get("node"); - if (targetNode == null) { - targetNode = (String) theDefinition.get("node"); - //targetNodeIsTemplate stays false, targetNode must be a type - } else { - //the value must be a node template or a node type - targetNodeIsTemplate = isTemplateReference( - Construct.Node, theContext, targetNode); - if ((!targetNodeIsTemplate) && (!isTypeReference(Construct.Node, targetNode))){ - theContext.addError("The 'node' entry must contain a reference to a node template or node type, '" + targetNode + IS_NONE_OF_THOSE, null); - return; - } - - //additional checks - String targetNodeDef = (String) theDefinition.get("node"); - if (targetNodeDef != null && targetNode != null) { - if (targetNodeIsTemplate) { - //if the target is node template, it must be compatible with the - //node type specification in the requirement defintion - String targetNodeType = (String) - catalog.getTemplate(theContext.target(), Construct.Node, targetNode).get("type"); - if (!catalog.isDerivedFrom( - Construct.Node, targetNodeType, targetNodeDef)) { - theContext.addError("The required target node type '" + targetNodeType + "' of target node " + targetNode + " is not compatible with the target node type found in the requirement definition: " + targetNodeDef, null); - return; - } - } else { - //if the target is a node type it must be compatible (= or derived - //from) with the node type specification in the requirement definition - if (!catalog.isDerivedFrom( - Construct.Node, targetNode, targetNodeDef)) { - theContext.addError("The required target node type '" + targetNode + "' is not compatible with the target node type found in the requirement definition: " + targetNodeDef, null); - return; - } - } - } - } - - String targetNodeType = targetNodeIsTemplate ? - (String) catalog.getTemplate(theContext.target(), Construct.Node, targetNode).get("type") : - targetNode; - - //capability assignment - boolean targetCapabilityIsType = false; - String targetCapability = (String) theAssignment.get(CAPABILITY); - if (targetCapability == null) { - targetCapability = (String) theDefinition.get(CAPABILITY); - //in a requirement definition the target capability can only be a - //capability type (and not a capability name within some target node - //type) - targetCapabilityIsType = true; - } else { - targetCapabilityIsType = isTypeReference(Construct.Capability, targetCapability); - - //check compatibility with the target compatibility type specified - //in the requirement definition, if any - String targetCapabilityDef = (String) theDefinition.get(CAPABILITY); - if (targetCapabilityDef != null && targetCapability != null) { - if (targetCapabilityIsType) { - if (!catalog.isDerivedFrom( - Construct.Capability, targetCapability, targetCapabilityDef)) { - theContext.addError("The required target capability type '" + targetCapability + "' is not compatible with the target capability type found in the requirement definition: " + targetCapabilityDef, null); - return; - } - } else { - //the capability is from a target node. Find its definition and - //check that its type is compatible with the capability type - //from the requirement definition - - //check target capability compatibility with target node - if (targetNode == null) { - theContext.addError("The capability '" + targetCapability + "' is not a capability type, hence it has to be a capability of the node template indicated in 'node', which was not specified", null); - return; - } - if (!targetNodeIsTemplate) { - theContext.addError("The capability '" + targetCapability + "' is not a capability type, hence it has to be a capability of the node template indicated in 'node', but there you specified a node type", null); - return; - } - //check that the targetNode (its type) indeed has the - //targetCapability - - Map<String, Object> targetNodeCapabilityDef = - findTypeFacetByName( - Construct.Node, targetNodeType, - Facet.capabilities, targetCapability); - if (targetNodeCapabilityDef == null) { - theContext.addError("No capability '" + targetCapability + "' was specified in the node " + targetNode + " of type " + targetNodeType, null); - return; - } - - String targetNodeCapabilityType = (String) targetNodeCapabilityDef.get("type"); - - if (!catalog.isDerivedFrom(Construct.Capability, - targetNodeCapabilityType, - targetCapabilityDef)) { - theContext.addError("The required target capability type '" + targetCapabilityDef + "' is not compatible with the target capability type found in the target node type capability definition : " + targetNodeCapabilityType + ", targetNode " + targetNode + ", capability name " + targetCapability, null); - return; - } - } - } - } - - //relationship assignment - Map targetRelationship = (Map) theAssignment.get("relationship"); - if (targetRelationship != null) { - //this has to be compatible with the relationship with the same name - //from the node type - //check the type - } - - //node_filter; used jxpath to simplify the navigation somewhat - //this is too cryptic - JXPathContext jxPath = JXPathContext.newContext(theAssignment); - jxPath.setLenient(true); - - List<Map> propertiesFilter = - (List<Map>) jxPath.getValue("/node_filter/properties"); - if (propertiesFilter != null) { - for (Map propertyFilter : propertiesFilter) { - if (targetNode != null) { - //if we have a target node or node template then it must have - //have these properties - for (Object propertyName : propertyFilter.keySet()) { - if (null == findTypeFacetByName(Construct.Node, - targetNodeType, - Facet.properties, - propertyName.toString())) { - theContext.addError("The node_filter property " + propertyName + " is invalid: requirement target node " + targetNode + " does not have such a property", null); - } - } - } - } - } - - List<Map> capabilitiesFilter = - (List<Map>) jxPath.getValue("node_filter/capabilities"); - if (capabilitiesFilter != null) { - for (Map capabilityFilterDef : capabilitiesFilter) { - assert capabilityFilterDef.size() == 1; - Map.Entry<String, Map> capabilityFilterEntry = - (Map.Entry<String, Map>) capabilityFilterDef.entrySet().iterator().next(); - String targetFilterCapability = capabilityFilterEntry.getKey(); - Map<String, Object> targetFilterCapabilityDef = null; - - //if we have a targetNode capabilityName must be a capability of - //that node (type); or it can be simply capability type (but the node - //must have a capability of that type) - - String targetFilterCapabilityType = null; - if (targetNode != null) { - targetFilterCapabilityDef = - findTypeFacetByName(Construct.Node, targetNodeType, - Facet.capabilities, targetFilterCapability); - if (targetFilterCapabilityDef != null) { - targetFilterCapabilityType = - (String) targetFilterCapabilityDef/*.values().iterator().next()*/.get("type"); - } else { - Map<String, Map> targetFilterCapabilities = - findTypeFacetByType(Construct.Node, targetNodeType, - Facet.capabilities, targetFilterCapability); - - if (!targetFilterCapabilities.isEmpty()) { - if (targetFilterCapabilities.size() > 1) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "checkRequirementAssignmentDefinition: filter check, target node type '{}' has more than one capability of type '{}', not supported", targetNodeType, targetFilterCapability); - } - //pick the first entry, it represents a capability of the required type - Map.Entry<String, Map> capabilityEntry = targetFilterCapabilities.entrySet().iterator().next(); - targetFilterCapabilityDef = Collections.singletonMap(capabilityEntry.getKey(), - capabilityEntry.getValue()); - targetFilterCapabilityType = targetFilterCapability; - } - } - } else { - //no node (type) specified, it can be a straight capability type - targetFilterCapabilityDef = catalog.getTypeDefinition( - Construct.Capability, targetFilterCapability); - //here comes the odd part: it can still be a just a name in which - //case we should look at the requirement definition, see which - //capability (type) it indicates - assert targetCapabilityIsType; //cannot be otherwise, we'd need a node - targetFilterCapabilityDef = catalog.getTypeDefinition( - Construct.Capability, targetCapability); - targetFilterCapabilityType = targetCapability; - } - - if (targetFilterCapabilityDef == null) { - theContext.addError("Capability (name or type) " + targetFilterCapability + " is invalid: not a known capability (type) " + - ((targetNodeType != null) ? (" of node type" + targetNodeType) : ""), null); - continue; - } - - for (Map propertyFilter : - (List<Map>) jxPath.getValue("/node_filter/capabilities/" + targetFilterCapability + "/properties")) { - //check that the properties are in the scope of the - //capability definition - for (Object propertyName : propertyFilter.keySet()) { - if (null == findTypeFacetByName(Construct.Capability, - targetCapability, - Facet.properties, - propertyName.toString())) { - theContext.addError("The capability filter " + targetFilterCapability + " property " + propertyName + " is invalid: target capability " + targetFilterCapabilityType + " does not have such a property", null); - } - } - } - } - } - - } finally { - theContext//.exit() - .exit(); - } - } - - private void checkCapabilitiesAssignmentDefinition( - Map<String, Map> theCapabilities, CheckContext theContext) { - theContext.enter(CAPABILITIES); - try { - if (!checkDefinition(CAPABILITIES, theCapabilities, theContext)) { - return; - } - - //the node type for the node template enclosing these requirements - String nodeType = (String) catalog.getTemplate( - theContext.target(), - Construct.Node, - theContext.enclosingConstruct(Construct.Node)) - .get("type"); - - for (Iterator<Map.Entry<String, Map>> ci = - theCapabilities.entrySet().iterator(); - ci.hasNext(); ) { - - Map.Entry<String, Map> ce = ci.next(); - - String capabilityName = ce.getKey(); - Map capabilityDef = findTypeFacetByName(Construct.Node, nodeType, - Facet.capabilities, capabilityName); - if (capabilityDef == null) { - theContext.addError("No capability " + capabilityName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); - continue; - } - - checkCapabilityAssignmentDefinition( - capabilityName, ce.getValue(), capabilityDef, theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkCapabilityAssignmentDefinition( - String theCapabilityName, - Map theAssignment, - Map theDefinition, - CheckContext theContext) { - - theContext.enter(theCapabilityName, Construct.Capability); - try { - String capabilityType = (String) theDefinition.get("type"); - //list of property and attributes assignments - checkFacet(Construct.Capability, theAssignment, capabilityType, - Facet.properties, theContext); - checkFacet(Construct.Capability, theAssignment, capabilityType, - Facet.attributes, theContext); - } finally { - theContext.exit(); - } - } - - private void checkTemplateInterfacesDefinition( - Map<String, Map> theInterfaces, - CheckContext theContext) { - theContext.enter(INTERFACES); - try { - if (!checkDefinition(INTERFACES, theInterfaces, theContext)) { - return; - } - - //the node type for the node template enclosing these requirements - String nodeType = (String) catalog.getTemplate( - theContext.target(), - Construct.Node, - theContext.enclosingConstruct(Construct.Node)) - .get("type"); - - for (Iterator<Map.Entry<String, Map>> ii = - theInterfaces.entrySet().iterator(); - ii.hasNext(); ) { - - Map.Entry<String, Map> ie = ii.next(); - - String interfaceName = ie.getKey(); - Map interfaceDef = findTypeFacetByName(Construct.Node, nodeType, - Facet.interfaces, interfaceName); - - if (interfaceDef == null) { - /* this is subject to augmentation: this could be a warning but not an error */ - theContext.addError("No interface " + interfaceName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); - continue; - } - - checkTemplateInterfaceDefinition( - interfaceName, ie.getValue(), interfaceDef, theContext); - } - } finally { - theContext.exit(); - } - } - - private void checkTemplateInterfaceDefinition( - String theInterfaceName, - Map theAssignment, - Map theDefinition, - CheckContext theContext) { - - theContext.enter(theInterfaceName, Construct.Interface); - try { - //check the assignment of the common inputs - checkFacet(Construct.Interface, - theAssignment, - (String) theDefinition.get("type"), - Facet.inputs, - theContext); - } finally { - theContext.exit(); - } - } - - - @Checks(path = "/topology_template/artifacts") - protected void check_template_artifacts_definition( - Map<String, Object> theDefinition, - CheckContext theContext) { - theContext.enter(ARTIFACTS); - theContext.exit(); - } - - //generic checking actions, not related to validation rules - - /* will check the validity of the type specification for any construct containing a 'type' entry */ - private boolean checkType(Construct theCategory, Map theSpec, CheckContext theContext) { - String type = (String) theSpec.get("type"); - if (type == null) { - theContext.addError("Missing type specification", null); - return false; - } - - if (!catalog.hasType(theCategory, type)) { - theContext.addError(UNKNOWN + theCategory + " type: " + type, null); - return false; - } - - return true; - } - - /* the type can be: - * a known type: predefined or user-defined - * a collection (list or map) and then check that the entry_schema points to one of the first two cases (is that it?) - */ - private boolean checkDataType(Map theSpec, CheckContext theContext) { - - if (!checkType(Construct.Data, theSpec, theContext)) { - return false; - } - - String type = (String) theSpec.get("type"); - if (/*isCollectionType(type)*/ - "list".equals(type) || "map".equals(type)) { - Map entrySchema = (Map) theSpec.get("entry_schema"); - if (entrySchema == null) { - //maybe issue a warning ?? or is 'string' the default?? - return true; - } - - if (!catalog.hasType(Construct.Data, (String) entrySchema.get("type"))) { - theContext.addError("Unknown entry_schema type: " + entrySchema, null); - return false; - } - } - return true; - } - - /* Check that a particular facet (properties, attributes) of a construct type - * (node type, capability type, etc) is correctly (consistenly) defined - * across a type hierarchy - */ - private boolean checkTypeConstructFacet(Construct theConstruct, - String theTypeName, - Map theTypeSpec, - Facet theFacet, - CheckContext theContext) { - Map<String, Map> defs = - (Map<String, Map>) theTypeSpec.get(theFacet.name()); - if (null == defs) { - return true; - } - - boolean res = true; - - //given that the type was cataloged there will be at least one entry - Iterator<Map.Entry<String, Map>> i = - catalog.hierarchy(theConstruct, theTypeName); - if (!i.hasNext()) { - theContext.addError( - "The type " + theTypeName + " needs to be cataloged before attempting 'checkTypeConstruct'", null); - return false; - } - i.next(); //skip self - while (i.hasNext()) { - Map.Entry<String, Map> e = i.next(); - Map<String, Map> superDefs = (Map<String, Map>) e.getValue() - .get(theFacet.name()); - if (null == superDefs) { - continue; - } - //this computes entries that appear on both collections but with different values, i.e. the re-defined properties - Map<String, MapDifference.ValueDifference<Map>> diff = Maps.difference(defs, superDefs).entriesDiffering(); - - for (Iterator<Map.Entry<String, MapDifference.ValueDifference<Map>>> di = diff.entrySet().iterator(); di.hasNext(); ) { - Map.Entry<String, MapDifference.ValueDifference<Map>> de = di.next(); - MapDifference.ValueDifference<Map> dediff = de.getValue(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "{} type {}: {} has been re-defined between the {} types {} and {}", theConstruct, theFacet, de.getKey(), theConstruct, e.getKey(), theTypeName); - //for now we just check that the type is consistenly re-declared - if (!this.catalog.isDerivedFrom(theFacet.construct(), - (String) dediff.leftValue().get("type"), - (String) dediff.rightValue().get("type"))) { - theContext.addError( - theConstruct + TYPE + theFacet + ", redefiniton changed its type: " + de.getKey() + " has been re-defined between the " + theConstruct + " types " + e.getKey() + " and " + theTypeName + " in an incompatible manner", null); - res = false; - } - } - } - - return res; - } - - /* - * Checks the validity of a certain facet of a construct - * (properties of a node) across a type hierarchy. - * For now the check is limited to a verifying that a a facet was declared - * somewhere in the construct type hierarchy (a node template property has - * been declared in the node type hierarchy). - * - * 2 versions with the more generic allowing the specification of the type - * to be done explicitly. - */ - private boolean checkFacet(Construct theConstruct, - Map theSpec, - Facet theFacet, - CheckContext theContext) { - return checkFacet(theConstruct, theSpec, null, theFacet, theContext); - } - - /** - * We walk the hierarchy and verify the assignment of a property with respect to its definition. - * We also collect the names of those properties defined as required but for which no assignment was provided. - */ - private boolean checkFacet(Construct theConstruct, - Map theSpec, - String theSpecType, - Facet theFacet, - CheckContext theContext) { - - Map<String, Map> defs = (Map<String, Map>) theSpec.get(theFacet.name()); - if (null == defs) { - return true; - } - defs = Maps.newHashMap(defs); // - - boolean res = true; - if (theSpecType == null) { - theSpecType = (String) theSpec.get("type"); - } - if (theSpecType == null) { - theContext.addError("No specification type available", null); - return false; - } - - Map<String, Byte> missed = new HashMap<>(); //keeps track of the missing required properties, the value is - //false if a default was found along the hierarchy - Iterator<Map.Entry<String, Map>> i = - catalog.hierarchy(theConstruct, theSpecType); - while (i.hasNext() && !defs.isEmpty()) { - Map.Entry<String, Map> type = i.next(); - - Map<String, Map> typeDefs = (Map<String, Map>) type.getValue() - .get(theFacet.name()); - if (null == typeDefs) { - continue; - } - - MapDifference<String, Map> diff = Maps.difference(defs, typeDefs); - - //this are the ones this type and the spec have in common (same key, - //different values) - Map<String, MapDifference.ValueDifference<Map>> facetDefs = - diff.entriesDiffering(); - //TODO: this assumes the definition of the facet is not cumulative, i.e. - //subtypes 'add' something to the definition provided by the super-types - //it considers the most specialized definition stands on its own - for (MapDifference.ValueDifference<Map> valdef : facetDefs.values()) { - checkDataValuation(valdef.leftValue(), valdef.rightValue(), theContext); - } - - //remove from properties all those that appear in this type: unfortunately this returns an unmodifiable map .. - defs = Maps.newHashMap(diff.entriesOnlyOnLeft()); - } - - if (!defs.isEmpty()) { - theContext.addError(UNKNOWN + theConstruct + " " + theFacet + " (not declared by the type " + theSpecType + ") were used: " + defs, null); - res = false; - } - - if (!missed.isEmpty()) { - List missedNames = - missed.entrySet() - .stream() - .filter(e -> e.getValue().byteValue() == (byte) 1) - .map(e -> e.getKey()) - .collect(Collectors.toList()); - if (!missedNames.isEmpty()) { - theContext.addError(theConstruct + " " + theFacet + " missing required values for: " + missedNames, null); - res = false; - } - } - - return res; - } - - /* Augmentation occurs in cases such as the declaration of capabilities within a node type. - * In such cases the construct facets (the capabilitity's properties) can redefine (augment) the - * specification found in the construct type. - */ - private boolean checkFacetAugmentation(Construct theConstruct, - Map theSpec, - Facet theFacet, - CheckContext theContext) { - return checkFacetAugmentation(theConstruct, theSpec, null, theFacet, theContext); - } - - private boolean checkFacetAugmentation(Construct theConstruct, - Map theSpec, - String theSpecType, - Facet theFacet, - CheckContext theContext) { - - Map<String, Map> augs = (Map<String, Map>) theSpec.get(theFacet.name()); - if (null == augs) { - return true; - } - - boolean res = true; - if (theSpecType == null) { - theSpecType = (String) theSpec.get("type"); - } - if (theSpecType == null) { - theContext.addError("No specification type available", null); - return false; - } - - for (Map.Entry<String, Map> ae : augs.entrySet()) { - //make sure it was declared by the type - Map facetDef = catalog.getFacetDefinition(theConstruct, theSpecType, theFacet, ae.getKey()); - if (facetDef == null) { - theContext.addError(UNKNOWN + theConstruct + " " + theFacet + " (not declared by the type " + theSpecType + ") were used: " + ae.getKey(), null); - res = false; - continue; - } - - //check the compatibility of the augmentation: only the type cannot be changed - //can the type be changed in a compatible manner ?? - if (!facetDef.get("type").equals(ae.getValue().get("type"))) { - theContext.addError(theConstruct + " " + theFacet + " " + ae.getKey() + " has a different type than its definition: " + ae.getValue().get("type") + " instead of " + facetDef.get("type"), null); - res = false; - continue; - } - - //check any valuation (here just defaults) - Object defaultValue = ae.getValue().get(DEFAULT); - if (defaultValue != null) { - checkDataValuation(defaultValue, ae.getValue(), theContext); - } - } - - return res; - } - - private boolean catalogTypes(Construct theConstruct, Map<String, Map> theTypes, CheckContext theContext) { - - boolean res = true; - for (Map.Entry<String, Map> typeEntry : theTypes.entrySet()) { - res &= catalogType(theConstruct, typeEntry.getKey(), typeEntry.getValue(), theContext); - } - - return res; - } - - private boolean catalogType(Construct theConstruct, - String theName, - Map theDef, - CheckContext theContext) { - - if (!catalog.addType(theConstruct, theName, theDef)) { - theContext.addError(theConstruct + TYPE + theName + " re-declaration", null); - return false; - } - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "{} type {} has been cataloged", theConstruct, theName); - - String parentType = (String) theDef.get("derived_from"); - if (parentType != null && !catalog.hasType(theConstruct, parentType)) { - theContext.addError( - theConstruct + TYPE + theName + " indicates a supertype that has not (yet) been declared: " + parentType, null); - return false; - } - return true; - } - - private boolean checkTypeReference(Construct theConstruct, - CheckContext theContext, - String... theTypeNames) { - boolean res = true; - for (String typeName : theTypeNames) { - if (!isTypeReference(theConstruct, typeName)) { - theContext.addError("Reference to " + theConstruct + " type '" + typeName + "' points to unknown type", null); - res = false; - } - } - return res; - } - - private boolean isTypeReference(Construct theConstruct, - String theTypeName) { - return this.catalog.hasType(theConstruct, theTypeName); - } - - /* node or relationship templates */ - private boolean checkTemplateReference(Construct theConstruct, - CheckContext theContext, - String... theTemplateNames) { - boolean res = true; - for (String templateName : theTemplateNames) { - if (!isTemplateReference(theConstruct, theContext, templateName)) { - theContext.addError("Reference to " + theConstruct + " template '" + templateName + "' points to unknown template", null); - res = false; - } - } - return res; - } - - private boolean isTemplateReference(Construct theConstruct, - CheckContext theContext, - String theTemplateName) { - return this.catalog.hasTemplate(theContext.target(), theConstruct, theTemplateName); - } - - /* - * For inputs/properties/attributes/(parameters). It is the caller's - * responsability to provide the value (from a 'default', inlined, ..) - * - * @param theDef the definition of the given construct/facet as it appears in - * its enclosing type definition. - * @param - */ - private boolean checkDataValuation(Object theExpr, - Map<String, ?> theDef, - CheckContext theContext) { - //first check if the expression is a function, if not handle it as a value assignment - Data.Function f = Data.function(theExpr); - if (f != null) { - return f.evaluator() - .eval(theExpr, theDef, theContext); - } else { - Data.Type type = Data.typeByName((String) theDef.get("type")); - if (type != null) { - Data.Evaluator evaluator; - - evaluator = type.evaluator(); - if (evaluator == null) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "No value evaluator available for type {}", type); - } else { - if ((theExpr != null) && (!evaluator.eval(theExpr, theDef, theContext))) { - return false; - } - } - - - evaluator = type.constraintsEvaluator(); - if (evaluator == null) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "No constraints evaluator available for type {}", type); - } else { - if (theExpr != null) { - if (!evaluator.eval(theExpr, theDef, theContext)) { - return false; - } - } else { - //should have a null value validatorT - } - } - - return true; - } else { - theContext.addError("Expression " + theExpr + " of " + theDef + " could not be evaluated", null); - return false; - } - } - } - - /** - * Given the type of a certain construct (node type for example), look up - * in one of its facets (properties, capabilities, ..) for one of the given - * facet type (if looking in property, one of the given data type). - * - * @return a map of all facets of the given type, will be empty to signal - * none found - * <p> - * Should we look for a facet construct of a compatible type: any type derived - * from the given facet's construct type?? - */ - private Map<String, Map> - findTypeFacetByType(Construct theTypeConstruct, - String theTypeName, - Facet theFacet, - String theFacetType) { - - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType {}, {}: {} {}", theTypeName, theTypeConstruct, theFacetType, theFacet); - Map<String, Map> res = new HashMap<>(); - Iterator<Map.Entry<String, Map>> i = - catalog.hierarchy(theTypeConstruct, theTypeName); - while (i.hasNext()) { - Map.Entry<String, Map> typeSpec = i.next(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, Checking {} type {}", theTypeConstruct, typeSpec.getKey()); - Map<String, Map> typeFacet = - (Map<String, Map>) typeSpec.getValue().get(theFacet.name()); - if (typeFacet == null) { - continue; - } - Iterator<Map.Entry<String, Map>> fi = typeFacet.entrySet().iterator(); - while (fi.hasNext()) { - Map.Entry<String, Map> facet = fi.next(); - String facetType = (String) facet.getValue().get("type"); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, Checking {} type {}", facet.getKey(), facetType); - - //here is the question: do we look for an exact match or .. - //now we check that the type has a capability of a type compatible - //(equal or derived from) the given capability type. - if (catalog.isDerivedFrom( - theFacet.construct(), facetType, theFacetType)) { - res.putIfAbsent(facet.getKey(), facet.getValue()); - } - } - } - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, found {}", res); - - return res; - } - - private Map<String, Object> - findTypeFacetByName(Construct theTypeConstruct, - String theTypeName, - Facet theFacet, - String theFacetName) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByName {} {}", theTypeConstruct, theTypeName); - Iterator<Map.Entry<String, Map>> i = - catalog.hierarchy(theTypeConstruct, theTypeName); - while (i.hasNext()) { - Map.Entry<String, Map> typeSpec = i.next(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByName, Checking {} type {}", theTypeConstruct, typeSpec.getKey()); - Map<String, Map> typeFacet = - (Map<String, Map>) typeSpec.getValue().get(theFacet.name()); - if (typeFacet == null) { - continue; - } - Map<String, Object> facet = typeFacet.get(theFacetName); - if (facet != null) { - return facet; - } - } - return null; - } - - /* Requirements are the odd ball as they are structured as a sequence .. */ - private Map<String, Map> findNodeTypeRequirementByName( - String theNodeType, String theRequirementName) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findNodeTypeRequirementByName {}/{}", theNodeType, theRequirementName); - Iterator<Map.Entry<String, Map>> i = - catalog.hierarchy(Construct.Node, theNodeType); - while (i.hasNext()) { - Map.Entry<String, Map> nodeType = i.next(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findNodeTypeRequirementByName, Checking node type {}", nodeType.getKey()); - List<Map<String, Map>> nodeTypeRequirements = - (List<Map<String, Map>>) nodeType.getValue().get(REQUIREMENTS); - if (nodeTypeRequirements == null) { - continue; - } - - for (Map<String, Map> requirement : nodeTypeRequirements) { - Map requirementDef = requirement.get(theRequirementName); - if (requirementDef != null) { - return requirementDef; - } - } - } - return null; - } - /* * Additional generics checks to be performed on any definition: construct, * construct types, etc .. */ - public boolean checkDefinition(String theName, - Map theDefinition, - CheckContext theContext) { - if (theDefinition == null) { - theContext.addError("Missing definition for " + theName, null); - return false; - } - - if (theDefinition.isEmpty()) { - theContext.addError("Empty definition for " + theName, null); - return false; - } - - return true; - } - private boolean checkDefinition(String theName, - List theDefinition, - CheckContext theContext) { - if (theDefinition == null) { - theContext.addError("Missing definition for " + theName, null); - return false; - } - - if (theDefinition.isEmpty()) { - theContext.addError("Empty definition for " + theName, null); - return false; - } - - return true; - } /* plenty of one entry maps around */ private Map.Entry mapEntry(Object theMap) { @@ -2715,16 +609,16 @@ public class Checker { private String patchWhitespaces(String thePath) { String[] elems = thePath.split("/"); StringBuilder path = new StringBuilder(); - for (int i = 0; i < elems.length; i++) { - if (spacePattern.matcher(elems[i]).find()) { + Arrays.stream(elems).forEach(elem -> { + if (spacePattern.matcher(elem).find()) { path.append("[@name='") - .append(elems[i]) + .append(elem) .append("']"); } else { path.append("/") - .append(elems[i]); + .append(elem); } - } + }); return path.toString(); } @@ -2816,66 +710,23 @@ public class Checker { Catalog catalog = new Catalog(doCommons ? commonsCatalog() : null); if (!doCommons) { //add core TOSCA types - for (Data.CoreType type : Data.CoreType.class.getEnumConstants()) { - catalog.addType(Construct.Data, type.toString(), Collections.emptyMap()); - } + Arrays.stream(Data.CoreType.class.getEnumConstants()).forEach(type -> catalog.addType(Construct.Data, type.toString(), Collections.emptyMap())); } return catalog; } - private boolean invokeHook(String theHookName, - Class[] theArgTypes, - Object... theArgs) { - - Invokable hookHandler = null; - try { - Method m = Checker.class.getDeclaredMethod( - theHookName, theArgTypes); - m.setAccessible(true); - hookHandler = Invokable.from(m); - } catch (NoSuchMethodException nsmx) { - //that's ok, not every rule has to have a handler - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), getClass().getName(), "That's ok, not every rule has to have a handler. Method name is:{}. Exception:{}", theHookName,nsmx); - } - - if (hookHandler != null) { - try { - hookHandler.invoke(this, theArgs); - } catch (InvocationTargetException | IllegalAccessException itx) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "Invocation failed for hook handler {} {}", theHookName, itx); - } catch (Exception x) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "Hook handler failed {} {}", theHookName, x); - } - } - - return hookHandler != null; - } - - private void validationHook(String theTiming, - Object theTarget, - Rule theRule, - Validator.ValidationContext theContext) { - - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "looking up validation handler for {}, {} {}", theRule.getName(), theTiming, theContext.getPath()); - if (!invokeHook(theRule.getName() + "_" + theTiming + "_validation_handler", - validationHookArgTypes, - theTarget, theRule, theContext)) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "no validation handler for {}", theRule.getName() + "_" + theTiming); - } - } - private void checks(String theName, Object theTarget, CheckContext theContext) { Map<Method, Object> handlers = checks.row(/*theName*/theContext.getPath(theName)); if (handlers != null) { - for (Map.Entry<Method, Object> handler : handlers.entrySet()) { + handlers.entrySet().forEach(handler -> { try { handler.getKey().invoke(handler.getValue(), new Object[]{theTarget, theContext}); } catch (Exception x) { errLogger.log(LogLevel.WARN, this.getClass().getName(), "Check {} with {} failed {}", theName, handler.getKey(), x); } - } + }); } else { boolean hasHook = false; for (Class[] argTypes : checkHookArgTypes) { @@ -2897,112 +748,25 @@ public class Checker { Map<Method, Object> handlers = catalogs.row(/*theName*/theContext.getPath(theName)); if (handlers != null) { - for (Map.Entry<Method, Object> handler : handlers.entrySet()) { + handlers.forEach((key, value) -> { try { - handler.getKey().invoke(handler.getValue(), new Object[]{theTarget, theContext}); + key.invoke(value, theTarget, theContext); } catch (Exception x) { - errLogger.log(LogLevel.WARN, this.getClass().getName(), "Cataloging {} with {} failed {}", theName, handler.getKey(), x); + errLogger.log(LogLevel.WARN, this.getClass().getName(), "Cataloging {} with {} failed {}", theName, key, x); } - } + }); } } - private class TOSCAValidator extends Validator { - - //what were validating - private Target target; - - /* Some of the TOSCA entries accept a 'short form/notation' instead of the canonical map representation. - * kwalify cannot easily express these alternatives and as such we handle them here. In the pre-validation phase we detect the presence of a short notation -and compute the canonical form and validate it. In the post-validation phase we -substitute the canonical form for the short form so that checking does not have to deal with it. - */ - - private Map<String, Object> canonicals = new TreeMap<>(); - - TOSCAValidator(Target theTarget, Object theSchema) { - super(theSchema); - this.target = theTarget; - } - - public Target getTarget() { - return this.target; - } - - /* hook method called by Validator#validate() - */ - @Override - protected boolean preValidationHook(Object value, Rule rule, ValidationContext context) { - - validationHook("pre", value, rule, context); - //short form handling - String hint = rule.getShort(); - if (value != null && - hint != null) { - - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Attempting canonical at {}, rule {}", context.getPath(), rule.getName()); - - Object canonical = null; - //if the canonical form requires a collection - if (Types.isCollectionType(rule.getType())) { - //and the actual value isn't one - if (!(value instanceof Map || value instanceof List)) { - //used to use singleton map/list here (was good for catching errors) - //but there is the possibility if short forms within short forms so - //the created canonicals need to accomodate other values. - if (Types.isMapType(rule.getType())) { - canonical = new HashMap(); - ((Map) canonical).put(hint, value); - } else { - //the hint is irrelevant here but we should impose a value when the target is a list - canonical = new LinkedList(); - ((List) canonical).add(value); - } - } else { - //we can accomodate: - // map to list of map transformation - if (!Types.isMapType(rule.getType()) /* a seq */ && - value instanceof Map) { - canonical = new LinkedList(); - ((List) canonical).add(value); - } else { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Grammar for rule {} (at {}) would require unsupported short form transformation: {} to {}", rule.getName(), context.getPath(), value.getClass(), rule.getType()); - return false; - } - } - - int errc = context.errorCount(); - validateRule(canonical, rule, context); - if (errc != context.errorCount()) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Short notation for {} through {} at {} failed validation", rule.getName(), hint, context.getPath()); - } else { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Short notation for {} through {} at {} passed validation. Canonical form is {}", rule.getName(), hint, context.getPath(), canonical); - //replace the short notation with the canonicall one so we don't - //have to deal it again during checking - this.canonicals.put(context.getPath(), canonical); - return true; - } - } else { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Grammar for rule {} (at {}) would require unsupported short form transformation: {} to {}", rule.getName(), context.getPath(), value.getClass(), rule.getType()); - } - } - - //perform default validation process - return false; - } - - /* - * Only gets invoked once the value was succesfully verified against the syntax indicated by the given rule. - */ - @Override - protected void postValidationHook(Object value, - Rule rule, - ValidationContext context) { - validationHook("post", value, rule, context); - } + public boolean checkDefinition(String workflows, Map theDefinition, CheckContext theContext) { + return checkCommon.checkDefinition(workflows, theDefinition, theContext); + } + public void checkProperties(Map<String, Map> inputs, CheckContext theContext) { + propertiesCommon.checkProperties(inputs, theContext, catalog); } + /** * Maintains state across the checking process. */ @@ -3093,23 +857,20 @@ substitute the canonical form for the short form so that checking does not have private String errorReport(List<Throwable> theErrors) { StringBuilder sb = new StringBuilder(theErrors.size() + " errors"); - for (Throwable x : theErrors) { - sb.append("\n"); - if (x instanceof ValidationException) { - ValidationException vx = (ValidationException) x; - // .apend("at ") - // .append(error.getLineNumber()) - // .append(" : ") - sb.append("[").append(vx.getPath()).append("] "); - } else if (x instanceof TargetError) { - TargetError tx = (TargetError) x; - sb.append("[").append(tx.getLocation()).append("] "); - } - sb.append(x.getMessage()); - if (x.getCause() != null) { - sb.append("\n\tCaused by:\n").append(x.getCause()); - } - } + theErrors.forEach(x -> { + sb.append("\n"); + if (x instanceof ValidationException) { + ValidationException vx = (ValidationException) x; + sb.append("[").append(vx.getPath()).append("] "); + } else if (x instanceof TargetError) { + TargetError tx = (TargetError) x; + sb.append("[").append(tx.getLocation()).append("] "); + } + sb.append(x.getMessage()); + if (x.getCause() != null) { + sb.append("\n\tCaused by:\n").append(x.getCause()); + } + }); sb.append("\n"); return sb.toString(); } @@ -3154,42 +915,42 @@ substitute the canonical form for the short form so that checking does not have Target tgt = ((TOSCAValidator) theContext.getValidator()).getTarget(); - applyCanonicals(tgt.getTarget(), ((TOSCAValidator) theContext.getValidator()).canonicals, "/imports", true); + applyCanonicals(tgt.getTarget(), ((TOSCAValidator) theContext.getValidator()).getCanonicals(), "/imports", true); - for (ListIterator li = ((List) theValue).listIterator(); li.hasNext();) { + for (Object o : ((List) theValue)) { - Map.Entry importEntry = mapEntry(li.next()); + Map.Entry importEntry = mapEntry(o); - Map def = (Map) importEntry.getValue(); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Processing import {}", def); + Map def = (Map) importEntry.getValue(); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Processing import {}", def); - String tfile = (String) def.get("file"); - Target tgti = this.locator.resolve(tfile); - if (tgti == null) { - theContext.addError("Failure to resolve import '" + def + "', imported from " + tgt, theRule, null, - null); - continue; - } - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Import {} located at {}", def, - tgti.getLocation()); + String tfile = (String) def.get("file"); + Target tgti = this.locator.resolve(tfile); + if (tgti == null) { + theContext.addError("Failure to resolve import '" + def + "', " + IMPORTED_FROM + " " + tgt, theRule, null, + null); + continue; + } + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Import {} located at {}", def, + tgti.getLocation()); - if (this.catalog.addTarget(tgti, tgt)) { - // we've never seen this import (location) before - try { + if (this.catalog.addTarget(tgti, tgt)) { + // we've never seen this import (location) before + try { List<Target> tgtis = parseTarget(tgti); if (tgtis.isEmpty()) { continue; } - if (tgtis.size() > 1) { - theContext.addError( - "Import '" + tgti + "', imported from " + tgt + ", contains multiple yaml documents", - theRule, null, null); - continue; - } + if (tgtis.size() > 1) { + theContext.addError( + "Import '" + tgti + "', " + IMPORTED_FROM + " " + tgt + ", contains multiple yaml documents", + theRule, null, null); + continue; + } - tgti = tgtis.get(0); + tgti = tgtis.get(0); if (tgt.getReport().hasErrors()) { theContext.addError("Failure parsing import '" + tgti + IMPORTED_FROM + tgt, theRule, null, @@ -3209,59 +970,33 @@ substitute the canonical form for the short form so that checking does not have } } - // replace with the actual location (also because this is what they - // get - // index by .. bad, this exposed catalog inner workings) + // replace with the actual location (also because this is what they + // get + // index by .. bad, this exposed catalog inner workings) - def.put("file", tgti.getLocation()); - } + def.put("file", tgti.getLocation()); + } } protected void node_templates_post_validation_handler(Object theValue, Rule theRule, Validator.ValidationContext theContext) { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "entering node_templates_post_validation_handler {}", theContext.getPath()); - assert "map".equals(theRule.getType()); + assert MAP.equals(theRule.getType()); Map<String, Map> nodeTemplates = (Map<String, Map>) theValue; - for (Iterator<Map.Entry<String, Map>> i = nodeTemplates.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> node = i.next(); - try { - catalog.addTemplate(((TOSCAValidator) theContext.getValidator()).getTarget(), Construct.Node, - node.getKey(), node.getValue()); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Node template {} has been cataloged", - node.getKey()); - } catch (CatalogException cx) { - theContext.addError(cx.toString(), theRule, node, null); - } - } + nodeTemplates.entrySet().forEach(node -> { + try { + catalog.addTemplate(((TOSCAValidator) theContext.getValidator()).getTarget(), Construct.Node, + node.getKey(), node.getValue()); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Node template {} has been cataloged", + node.getKey()); + } catch (CatalogException cx) { + theContext.addError(cx.toString(), theRule, node, null); + } + }); } - protected void inputs_post_validation_handler(Object theValue, Rule theRule, - Validator.ValidationContext theContext) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "entering inputs_post_validation_handler {}", - theContext.getPath()); - assert theRule.getType().equals("map"); - // we'll repeat this test during checking but because we index inputs - // early - // we need it here too - if (theValue == null) { - return; - } - - Map<String, Map> inputs = (Map<String, Map>) theValue; - for (Iterator<Map.Entry<String, Map>> i = inputs.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> input = i.next(); - try { - catalog.addTemplate(((TOSCAValidator) theContext.getValidator()).getTarget(), Construct.Data, - input.getKey(), input.getValue()); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Input {} has been cataloged", - input.getKey()); - } catch (CatalogException cx) { - theContext.addError(cx.toString(), theRule, input, null); - } - } - } private void process(String theProcessorSpec) throws CheckerException { @@ -3288,359 +1023,504 @@ substitute the canonical form for the short form so that checking does not have process(proc); } - protected void check_artifact_definition(String theName, Map theDef, CheckContext theContext) { - theContext.enter(theName, Construct.Artifact); + @Catalogs(path = "/artifact_types") + protected void catalog_artifact_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(ARTIFACT_TYPES); + try { + typeCommon.catalogTypes(Construct.Artifact, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - try { - if (!checkDefinition(theName, theDef, theContext)) { - return; - } - // check artifact type - if (!checkType(Construct.Artifact, theDef, theContext)) { - return; - } - } finally { - theContext.exit(); - } - } + /* */ + @Checks(path = "/artifact_types") + protected void check_artifact_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(artifactCommon::checkArtifactTypeDefinition, theDefinition, theContext, ARTIFACT_TYPES); + } - /* */ - protected void check_policy_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Policy); + @Catalogs(path = "/capability_types") + protected void catalog_capability_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(ConstCommon.CAPABILITY_TYPES); + try { + typeCommon.catalogTypes(Construct.Capability, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + /* */ + @Checks(path = "/capability_types") + protected void check_capability_types( + Map<String, Map> theTypes, Checker.CheckContext theContext) { + abstractCheck(capabilityCommon::checkCapabilityTypeDefinition, theTypes, theContext, CAPABILITY_TYPES); + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Policy, theName, theDefinition, Facet.properties, theContext); - } + @Catalogs(path = "/data_types") + protected void catalog_data_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(DATA_TYPES); + try { + typeCommon.catalogTypes(Construct.Data, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - // the targets can be known node types or group types - List<String> targets = (List<String>) theDefinition.get("targets"); - if (targets != null) { - if (checkDefinition("targets", targets, theContext)) { - for (String target : targets) { - if (!(this.catalog.hasType(Construct.Node, target) - || this.catalog.hasType(Construct.Group, target))) { - theContext.addError( - "The 'targets' entry must contain a reference to a node type or group type, '" - + target + "' is none of those", - null); - } - } - } - } + @Checks(path = "/data_types") + protected void check_data_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + abstractCheck(checkCommon::checkDataTypeDefinition, theDefinitions, theContext, DATA_TYPES); - } finally { - theContext.exit(); - } - } + } - /* */ - protected void check_group_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Group); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + @Catalogs(path = "/group_types") + protected void catalog_group_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(GROUP_TYPES); + try { + typeCommon.catalogTypes(Construct.Group, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Group, theName, theDefinition, Facet.properties, theContext); - } + @Checks(path = "/group_types") + protected void check_group_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(groupCommon::checkGroupTypeDefinition, theDefinition, theContext, GROUP_TYPES); + } - if (theDefinition.containsKey("targets")) { - checkTypeReference(Construct.Node, theContext, - ((List<String>) theDefinition.get("targets")).toArray(EMPTY_STRING_ARRAY)); - } + @Catalogs(path = "/interface_types") + protected void catalog_interface_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(INTERFACE_TYPES); + try { + typeCommon.catalogTypes(Construct.Interface, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - // interfaces - Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get("interfaces"); - if (interfaces != null) { - try { - theContext.enter("interfaces"); - for (Iterator<Map.Entry<String, Map>> i = interfaces.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> e = i.next(); - check_type_interface_definition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } + @Checks(path = "/interface_types") + protected void check_interface_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(interfaceCommon::checkInterfaceTypeDefinition, theDefinition, theContext, INTERFACE_TYPES); + } - } finally { - theContext.exit(); - } - } + @Catalogs(path = "/node_types") + protected void catalog_node_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(NODE_TYPES); + try { + typeCommon.catalogTypes(Construct.Node, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - /* */ - protected void check_node_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Node); + /* */ + @Checks(path = "/node_types") + protected void check_node_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(nodeCommon::checkNodeTypeDefinition, theDefinition, theContext, NODE_TYPES); + } - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + @Catalogs(path = "/policy_types") + protected void catalog_policy_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(POLICY_TYPES); + try { + typeCommon.catalogTypes(Construct.Policy, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Node, theName, theDefinition, Facet.properties, theContext); - } + /* */ + @Checks(path = "/policy_types") + protected void check_policy_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(policyCommon::checkPolicyTypeDefinition, theDefinition, theContext, POLICY_TYPES); + } - if (theDefinition.containsKey("attributes")) { - check_properties((Map<String, Map>) theDefinition.get("attributes"), theContext); - checkTypeConstructFacet(Construct.Node, theName, theDefinition, Facet.attributes, theContext); - } + @Catalogs(path = "/relationship_types") + protected void catalog_relationship_types( + Map<String, Map> theDefinitions, Checker.CheckContext theContext) { + theContext.enter(RELATIONSHIP_TYPES); + try { + typeCommon.catalogTypes(Construct.Relationship, theDefinitions, theContext, catalog); + } finally { + theContext.exit(); + } + } - // requirements - if (theDefinition.containsKey("requirements")) { - check_requirements((List<Map>) theDefinition.get("requirements"), theContext); - } + /* */ + @Checks(path = "/relationship_types") + protected void check_relationship_types( + Map<String, Map> theDefinition, Checker.CheckContext theContext) { + abstractCheck(relationshipCommon::checkRelationshipTypeDefinition, theDefinition, theContext, RELATIONSHIP_TYPES); + } - // capabilities - if (theDefinition.containsKey(CAPABILITIES)) { - check_capabilities((Map<String, Map>) theDefinition.get(CAPABILITIES), theContext); - } + @Checks(path = "/topology_template/groups") + protected void check_groups(Map<String, Map> theGroups, + Checker.CheckContext theContext) { + abstractCheck(groupCommon::checkGroupDefinition, theGroups, theContext, GROUPS); + } - // interfaces: - Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get("interfaces"); - if (interfaces != null) { - try { - theContext.enter("interfaces"); - for (Iterator<Map.Entry<String, Map>> i = interfaces.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> e = i.next(); - check_type_interface_definition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } + @Checks(path = "/topology_template/policies") + protected void check_policies(List<Map<String, Map>> thePolicies, + Checker.CheckContext theContext) { + theContext.enter(POLICIES); - // artifacts + try { + if (!checkCommon.checkDefinition(POLICIES, thePolicies, theContext)) { + return; + } - } finally { - theContext.exit(); - } - } + thePolicies.forEach(policy -> { + assert policy.size() == 1; + Map.Entry<String, Map> e = policy.entrySet().iterator().next(); + policyCommon.checkPolicyDefinition(e.getKey(), e.getValue(), theContext, catalog, target); + }); + } finally { + theContext.exit(); + } + } - /* */ - protected void check_interface_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Interface); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + /* */ + @Checks(path = "/topology_template/substitution_mappings") + protected void check_substitution_mappings(Map<String, Object> theSub, + Checker.CheckContext theContext) { + theContext.enter("substitution_mappings"); + try { + //type is mandatory + String type = (String) theSub.get("node_type"); + if (!typeCommon.checkTypeReference(Construct.Node, theContext, catalog, type)) { + theContext.addError("Unknown node type: " + type + "", null); + return; //not much to go on with + } - // not much else here: a list of operation_definitions, each with - // its - // implementation and inputs + Map<String, List> capabilities = (Map<String, List>) theSub.get(ConstCommon.CAPABILITIES); + if (null != capabilities) { + //the key must be a capability of the type + //the value is a 2 element list: first is a local node, + //second is the name of one of its capabilities + capabilities.entrySet().forEach(ce -> { + if (null == facetCommon.findTypeFacetByName(Construct.Node, type, + Facet.capabilities, ce.getKey(), catalog)) { + theContext.addError("Unknown node type capability: " + ce.getKey() + ", type " + type, null); + } + if (!checkValidationOnCatalog(ce, "capability", theContext, Construct.Node)) { + return; + } + String targetNode = (String) ce.getValue().get(0); + Map<String, Object> targetNodeDef = (Map<String, Object>) + catalog.getTemplate(theContext.target(), Construct.Node, targetNode); + String targetCapability = (String) ce.getValue().get(1); + String targetNodeType = (String) targetNodeDef.get("type"); + if (null == facetCommon.findTypeFacetByName(Construct.Node, targetNodeType, + Facet.capabilities, targetCapability, catalog)) { + theContext.addError("Invalid capability mapping capability: " + targetCapability + ". No such capability found for node template " + targetNode + ", of type " + targetNodeType, null); + } + }); + } - // check that common inputs are re-defined in a compatible manner + Map<String, List> requirements = (Map<String, List>) theSub.get(ConstCommon.REQUIREMENTS); + if (null != requirements) { + //the key must be a requirement of the type + requirements.entrySet().forEach(re -> { + if (null == nodeCommon.findNodeTypeRequirementByName(type, re.getKey(), catalog)) { + theContext.addError("Unknown node type requirement: " + re.getKey() + ", type " + type, null); + } + if (!checkValidationOnCatalog(re, "requirement", theContext, Construct.Node)) { + return; + } + String targetNode = (String) re.getValue().get(0); + Map<String, Object> targetNodeDef = (Map<String, Object>) + catalog.getTemplate(theContext.target(), Construct.Node, targetNode); + String targetRequirement = (String) re.getValue().get(1); + String targetNodeType = (String) targetNodeDef.get("type"); + if (null == nodeCommon.findNodeTypeRequirementByName(targetNodeType, targetRequirement, catalog)) { + theContext.addError("Invalid requirement mapping requirement: " + targetRequirement + ". No such requirement found for node template " + targetNode + ", of type " + targetNodeType, null); + } + }); + } + } finally { + theContext.exit(); + } + } - // check that the interface operations are overwritten in a - // compatible manner - // for (Iterator<Map.Entry<String,Map>> i = theDefinition.entrySet() + private boolean checkValidationOnCatalog(Map.Entry<String, List> target, String name, Checker.CheckContext theContext, Construct construct) { + List targetList = target.getValue(); + if (targetList.size() != 2) { + theContext.addError("Invalid " + name + " mapping: " + target + ", expecting 2 elements", null); + return false; + } - } finally { - theContext.exit(); - } - } + String targetNode = (String) targetList.get(0); - /* */ - protected void check_artifact_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Artifact); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + Map<String, Object> targetNodeDef = (Map<String, Object>) + catalog.getTemplate(theContext.target(), construct, targetNode); + if (null == targetNodeDef) { + theContext.addError("Invalid " + name + " mapping node template: " + targetNode, null); + return false; + } + return true; + } - } finally { - theContext.exit(); - } - } + @Override + @Checks(path = "/topology_template/artifacts") + public void check_template_artifacts_definition( + Map<String, Object> theDefinition, + Checker.CheckContext theContext) { + theContext.enter(ARTIFACTS); + theContext.exit(); + } - /* */ - protected void check_relationship_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Relationship); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + @Checks(path = "/topology_template/relationship_templates") + protected void check_relationship_templates(Map theTemplates, + Checker.CheckContext theContext) { + abstractCheck(relationshipCommon::checkRelationshipTemplateDefinition, theTemplates, theContext, RELATIONSHIP_TEMPLATES); + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, Facet.properties, theContext); - } + @Checks(path = "topology_template/outputs") + protected void check_outputs(Map<String, Map> theOutputs, + Checker.CheckContext theContext) { + abstractCheck(inputsOutputsCommon::checkOutputDefinition, theOutputs, theContext, OUTPUTS); + } - if (theDefinition.containsKey("attributes")) { - check_properties((Map<String, Map>) theDefinition.get("attributes"), theContext); - checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, Facet.attributes, theContext); - } + /* */ + @Checks(path = "/topology_template/node_templates") + protected void check_node_templates(Map<String, Map> theTemplates, + Checker.CheckContext theContext) { + abstractCheck(nodeCommon::checkNodeTemplateDefinition, theTemplates, theContext, NODE_TEMPLATES); + } - Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get("interfaces"); - if (interfaces != null) { - theContext.enter("interfaces"); - for (Iterator<Map.Entry<String, Map>> i = interfaces.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> e = i.next(); - check_type_interface_definition(e.getKey(), e.getValue(), theContext); - } - theContext.exit(); - } + /* */ + @Override + @Checks(path = "/topology_template/inputs") + public void check_inputs(Map<String, Map> theInputs, + Checker.CheckContext theContext) { + abstractCheck(inputsOutputsCommon::checkInputDefinition, theInputs, theContext, INPUTS); + } - if (theDefinition.containsKey(VALID_TARGET_TYPES)) { - checkTypeReference(Construct.Capability, theContext, - ((List<String>) theDefinition.get(VALID_TARGET_TYPES)).toArray(EMPTY_STRING_ARRAY)); - } - } finally { - theContext.exit(); - } - } + @Override + public void validationHook(String theTiming, + Object theTarget, + Rule theRule, + Validator.ValidationContext theContext) { - /* */ - protected void check_capability_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Capability); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "looking up validation handler for {}, {} {}", theRule.getName(), theTiming, theContext.getPath()); + if (!invokeHook(theRule.getName() + "_" + theTiming + "_validation_handler", + validationHookArgTypes, + theTarget, theRule, theContext)) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "no validation handler for {}", theRule.getName() + "_" + theTiming); + } + } + private boolean invokeHook(String theHookName, + Class[] theArgTypes, + Object... theArgs) { - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + Invokable hookHandler = null; + try { + Method m = Checker.class.getDeclaredMethod( + theHookName, theArgTypes); + m.setAccessible(true); + hookHandler = Invokable.from(m); + } catch (NoSuchMethodException nsmx) { + //that's ok, not every rule has to have a handler + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), getClass().getName(), "That's ok, not every rule has to have a handler. Method name =", theHookName); + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Capability, theName, theDefinition, Facet.properties, theContext); - } + if (hookHandler != null) { + try { + hookHandler.invoke(this, theArgs); + } catch (InvocationTargetException | IllegalAccessException itx) { + errLogger.log(LogLevel.WARN, this.getClass().getName(), "Invocation failed for hook handler {} {}", theHookName, itx); + } catch (Exception x) { + errLogger.log(LogLevel.WARN, this.getClass().getName(), "Hook handler failed {} {}", theHookName, x); + } + } - if (theDefinition.containsKey("attributes")) { - check_attributes((Map<String, Map>) theDefinition.get("attributes"), theContext); - checkTypeConstructFacet(Construct.Capability, theName, theDefinition, Facet.attributes, theContext); - } + return hookHandler != null; + } - // valid_source_types: see capability_type_definition - // unclear: how is the valid_source_types list definition eveolving - // across - // the type hierarchy: additive, overwriting, ?? - if (theDefinition.containsKey("valid_source_types")) { - checkTypeReference(Construct.Node, theContext, - ((List<String>) theDefinition.get("valid_source_types")).toArray(EMPTY_STRING_ARRAY)); - } - } finally { - theContext.exit(); - } - } + public void inputs_post_validation_handler(Object theValue, Rule theRule, + Validator.ValidationContext theContext) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "entering inputs_post_validation_handler {}", + theContext.getPath()); + assert MAP.equals(theRule.getType()); - /* */ - protected void check_data_type_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName, Construct.Data); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } + // we'll repeat this test during checking but because we index inputs + // early + // we need it here too + if (theValue == null) { + return; + } - if (theDefinition.containsKey(PROPERTIES)) { - check_properties((Map<String, Map>) theDefinition.get(PROPERTIES), theContext); - checkTypeConstructFacet(Construct.Data, theName, theDefinition, Facet.properties, theContext); - } - } finally { - theContext.exit(); - } - } + Map<String, Map> inputs = (Map<String, Map>) theValue; + inputs.entrySet().forEach(input -> { + try { + catalog.addTemplate(((TOSCAValidator) theContext.getValidator()).getTarget(), Construct.Data, + input.getKey(), input.getValue()); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Input {} has been cataloged", + input.getKey()); + } catch (CatalogException cx) { + theContext.addError(cx.toString(), theRule, input, null); + } + }); + } - /* - * top level rule, we collected the whole information set. this is where - * checking starts - */ - protected void check_service_template_definition(Map<String, Object> theDef, CheckContext theContext) { - theContext.enter(""); + /* */ + public void check_node_type_definition(String theName, Map theDefinition, Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Node); - if (theDef == null) { - theContext.addError("Empty template", null); - return; - } + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } - // !!! imports need to be processed first now that catalogging takes - // place at check time!! + checkProperties(theName, theDefinition, theContext, PROPERTIES, Construct.Node, Facet.properties); + checkProperties(theName, theDefinition, theContext, ATTRIBUTES, Construct.Node, Facet.attributes); + // requirements + checkRequirements(theDefinition, theContext, requirementCommon); + // capabilities + checkCapabilities(theDefinition, theContext, capabilityCommon); + // interfaces: + checkInterfaces(theDefinition, theContext); - // first catalog whatever it is there to be cataloged so that the checks - // can perform cross-checking - for (Iterator<Map.Entry<String, Object>> ri = theDef.entrySet().iterator(); ri.hasNext();) { - Map.Entry<String, Object> e = ri.next(); - catalogs(e.getKey(), e.getValue(), theContext); - } + // artifacts - for (Iterator<Map.Entry<String, Object>> ri = theDef.entrySet().iterator(); ri.hasNext();) { - Map.Entry<String, Object> e = ri.next(); - checks(e.getKey(), e.getValue(), theContext); - } - theContext.exit(); - } + } finally { + theContext.exit(); + } + } - protected void check_attribute_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName); - try { - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - if (!checkDataType(theDefinition, theContext)) { - return; - } - } finally { - theContext.exit(); - } - } + private void checkCapabilities(Map theDefinition, CheckContext theContext, CapabilityCommon capabilityCommon) { + if (theDefinition.containsKey(CAPABILITIES)) { + capabilityCommon.check_capabilities((Map<String, Map>) theDefinition.get(CAPABILITIES), theContext, catalog); + } + } - public void check_attributes(Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter("attributes"); - try { - if (!checkDefinition("attributes", theDefinitions, theContext)) { + private void checkRequirements(Map theDefinition, CheckContext theContext, RequirementCommon requirementCommon) { + if (theDefinition.containsKey(REQUIREMENTS)) { + requirementCommon.check_requirements((List<Map>) theDefinition.get(REQUIREMENTS), theContext, catalog); + } + } + + private void checkProperties(String theName, Map theDefinition, CheckContext theContext, String definition, Construct node, Facet facet) { + if (theDefinition.containsKey(definition)) { + propertiesCommon.check_properties((Map<String, Map>) theDefinition.get(definition), theContext, catalog); + facetCommon.checkTypeConstructFacet(node, theName, theDefinition, facet, theContext, catalog); + } + } + + /* */ + public void check_data_type_definition(String theName, Map theDefinition, Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Data); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { return; } - for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> e = i.next(); - check_attribute_definition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } + checkProperties(theName, theDefinition, theContext, PROPERTIES, Construct.Data, Facet.properties); + } finally { + theContext.exit(); + } + } - protected void check_property_definition(String theName, Map theDefinition, CheckContext theContext) { - theContext.enter(theName); - if (!checkDefinition(theName, theDefinition, theContext)) { - return; - } - // check the type - if (!checkDataType(theDefinition, theContext)) { - return; - } - // check default value is compatible with type - Object defaultValue = theDefinition.get("default"); - if (defaultValue != null) { - checkDataValuation(defaultValue, theDefinition, theContext); - } + /* */ + public void check_capability_type_definition(String theName, Map theDefinition, Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Capability); - theContext.exit(); - } + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } - public void check_properties(Map<String, Map> theDefinitions, CheckContext theContext) { - theContext.enter(PROPERTIES); - try { - if (!checkDefinition(PROPERTIES, theDefinitions, theContext)) { + checkProperties(theName, theDefinition, theContext, PROPERTIES, Construct.Capability, Facet.properties); + + if (theDefinition.containsKey(ATTRIBUTES)) { + attributesCommon.check_attributes((Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Capability, theName, theDefinition, Facet.attributes, theContext, catalog); + } + + // valid_source_types: see capability_type_definition + // unclear: how is the valid_source_types list definition eveolving + // across + // the type hierarchy: additive, overwriting, ?? + if (theDefinition.containsKey("valid_source_types")) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, + ((List<String>) theDefinition.get("valid_source_types")).toArray(EMPTY_STRING_ARRAY)); + } + } finally { + theContext.exit(); + } + } + + + /* */ + public void check_group_type_definition(String theName, Map theDefinition, Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Group); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { return; } - for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, Map> e = i.next(); - check_property_definition(e.getKey(), e.getValue(), theContext); - } - } finally { - theContext.exit(); - } - } + checkProperties(theName, theDefinition, theContext, PROPERTIES, Construct.Group, Facet.properties); + + if (theDefinition.containsKey(TARGETS)) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, + ((List<String>) theDefinition.get(TARGETS)).toArray(EMPTY_STRING_ARRAY)); + } + + // interfaces + checkInterfaces(theDefinition, theContext); + + } finally { + theContext.exit(); + } + } + private void checkInterfaces(Map theDefinition, CheckContext theContext) { + Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get(INTERFACES); + if (interfaces != null) { + try { + theContext.enter(INTERFACES); + interfaces.forEach((key, value) -> interfaceCommon.check_type_interface_definition(key, value, theContext, catalog)); + } finally { + theContext.exit(); + } + } + } + + /* */ + public void check_interface_type_definition(String theName, Map theDefinition, Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Interface); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + // not much else here: a list of operation_definitions, each with + // its + // implementation and inputs + + // check that common inputs are re-defined in a compatible manner + + // check that the interface operations are overwritten in a + // compatible manner + // for (Iterator<Map.Entry<String,Map>> i = theDefinition.entrySet() + + } finally { + theContext.exit(); + } + } } diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/IChecker.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/IChecker.java new file mode 100644 index 0000000..be77500 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/IChecker.java @@ -0,0 +1,21 @@ +package org.onap.sdc.dcae.checker; + +import kwalify.Rule; +import kwalify.Validator; + +import java.util.Map; + +public interface IChecker { + void check_template_artifacts_definition( + Map<String, Object> theDefinition, + Checker.CheckContext theContext); + + /* */ + void check_inputs(Map<String, Map> theInputs, + Checker.CheckContext theContext); + + void validationHook(String theTiming, + Object theTarget, + Rule theRule, + Validator.ValidationContext theContext); +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Target.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Target.java index b630564..9dd5db4 100644 --- a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Target.java +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/Target.java @@ -1,27 +1,16 @@ package org.onap.sdc.dcae.checker; -import org.onap.sdc.common.onaplog.OnapLoggerDebug; -import org.onap.sdc.common.onaplog.OnapLoggerError; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; import java.io.BufferedReader; import java.io.IOException; - +import java.io.InputStreamReader; +import java.io.Reader; import java.net.URI; -import java.net.URL; -import java.net.MalformedURLException; /** * Represents a yaml document to be parsed/validated/checked */ public class Target { - private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); - private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); - - private String name; //maintained mainly for logging private URI location; private Object target; //this is the parsed form of the target @@ -72,7 +61,6 @@ public class Target { } public String toString() { - //return String.format("Target %s (%.20s ...)", this.location, this.target == null ? "" : this.target.toString()); return String.format("Target %s at %s", this.name, this.location); } diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ArtifactCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ArtifactCommon.java new file mode 100644 index 0000000..32a78c1 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ArtifactCommon.java @@ -0,0 +1,31 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.Checker; +import org.onap.sdc.dcae.checker.Construct; + +import java.util.Map; + +public class ArtifactCommon extends BaseCommon { + + private static ArtifactCommon instance; + + public synchronized static ArtifactCommon getInstance() { + if (instance == null) + { + instance = new ArtifactCommon(); + } + return instance; + } + + private ArtifactCommon() {} + public void checkArtifactTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Artifact); + try { + CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext); + } finally { + theContext.exit(); + } + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/AttributesCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/AttributesCommon.java new file mode 100644 index 0000000..afe8ada --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/AttributesCommon.java @@ -0,0 +1,72 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.Catalog; +import org.onap.sdc.dcae.checker.Checker; + +import java.util.Iterator; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.ATTRIBUTES; + +public class AttributesCommon extends BaseCommon { + private static AttributesCommon instance; + + public synchronized static AttributesCommon getInstance() { + if (instance == null) + { + instance = new AttributesCommon(); + } + return instance; + } + + private AttributesCommon() {} + + public void checkAttributes( + Map<String, Map> theDefinitions, Checker.CheckContext theContext, Catalog catalog) { + theContext.enter(ATTRIBUTES); + try { + if (!CheckCommon.getInstance().checkDefinition(ATTRIBUTES, theDefinitions, theContext)) { + return; + } + + for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, Map> e = i.next(); + checkAttributeDefinition(e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + public void checkAttributeDefinition( + String theName, Map theDefinition, Checker.CheckContext theContext, Catalog catalog) { + DataCommon dataCommon = DataCommon.getInstance(); + theContext.enter(theName); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + if (!dataCommon.checkDataType(theDefinition, theContext, catalog)) { + return; + } + } finally { + theContext.exit(); + } + } + + public void check_attributes(Map<String, Map> theDefinitions, Checker.CheckContext theContext, Catalog catalog) { + theContext.enter("attributes"); + try { + if (!CheckCommon.getInstance().checkDefinition("attributes", theDefinitions, theContext)) + return; + + for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, Map> e = i.next(); + checkAttributeDefinition(e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/BaseCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/BaseCommon.java new file mode 100644 index 0000000..43bda09 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/BaseCommon.java @@ -0,0 +1,9 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.common.onaplog.OnapLoggerDebug; +import org.onap.sdc.common.onaplog.OnapLoggerError; + +public class BaseCommon { + protected static OnapLoggerError errLogger = OnapLoggerError.getInstance(); + protected static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CapabilityCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CapabilityCommon.java new file mode 100644 index 0000000..08a1dd2 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CapabilityCommon.java @@ -0,0 +1,190 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.Catalog; +import org.onap.sdc.dcae.checker.Checker; +import org.onap.sdc.dcae.checker.Construct; +import org.onap.sdc.dcae.checker.Facet; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; + +public class CapabilityCommon extends BaseCommon { + + private static CapabilityCommon instance; + + public synchronized static CapabilityCommon getInstance() { + if (instance == null) + { + instance = new CapabilityCommon(); + } + return instance; + } + + private CapabilityCommon() {} + + + + public void check_capabilities(Map<String, Map> theDefinition, + Checker.CheckContext theContext, Catalog catalog) { + theContext.enter(CAPABILITIES); + try { + if (!CheckCommon.getInstance().checkDefinition(CAPABILITIES, theDefinition, theContext)) { + return; + } + + for (Iterator<Map.Entry<String, Map>> i = theDefinition.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, Map> e = i.next(); + checkCapabilityDefinition(e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + /* A capability definition appears within the context ot a node type */ + public void checkCapabilityDefinition(String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName, Construct.Capability); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + + //check capability type + if (!typeCommon.checkType(Construct.Capability, theDef, theContext, catalog)) { + return; + } + + //check properties + if (!facetCommon.checkFacetAugmentation( + Construct.Capability, theDef, Facet.properties, theContext, catalog)) { + return; + } + + //check attributes + if (!facetCommon.checkFacetAugmentation( + Construct.Capability, theDef, Facet.attributes, theContext, catalog)) { + return; + } + + //valid_source_types: should point to valid template nodes + if (theDef.containsKey(VALID_SOURCE_TYPES)) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, + ((List<String>) theDef.get(VALID_SOURCE_TYPES)).toArray(EMPTY_STRING_ARRAY)); + //per A.6.1.4 there is an additinal check to be performed here: + //"Any Node Type (names) provides as values for the valid_source_types keyname SHALL be type-compatible (i.e., derived from the same parent Node Type) with any Node Types defined using the same keyname in the parent Capability Type." + } + //occurences: were verified in range_definition + + } finally { + theContext.exit(); + } + } + + public void checkCapabilityTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + AttributesCommon attributesCommon = AttributesCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName, Construct.Capability); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Capability, theName, theDefinition, + Facet.properties, theContext, catalog); + } + + if (theDefinition.containsKey(ATTRIBUTES)) { + attributesCommon.checkAttributes( + (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Capability, theName, theDefinition, + Facet.attributes, theContext, catalog); + } + + //valid_source_types: see capability_type_definition + //unclear: how is the valid_source_types list definition eveolving across + //the type hierarchy: additive, overwriting, ?? + if (theDefinition.containsKey(VALID_SOURCE_TYPES)) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, + ((List<String>) theDefinition.get(VALID_SOURCE_TYPES)).toArray(EMPTY_STRING_ARRAY)); + } + } finally { + theContext.exit(); + } + } + + public void checkCapabilitiesAssignmentDefinition( + Map<String, Map> theCapabilities, Checker.CheckContext theContext, Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(CAPABILITIES); + try { + if (!CheckCommon.getInstance().checkDefinition(CAPABILITIES, theCapabilities, theContext)) { + return; + } + + //the node type for the node template enclosing these requirements + String nodeType = (String) catalog.getTemplate( + theContext.target(), + Construct.Node, + theContext.enclosingConstruct(Construct.Node)) + .get("type"); + + for (Iterator<Map.Entry<String, Map>> ci = + theCapabilities.entrySet().iterator(); + ci.hasNext(); ) { + + Map.Entry<String, Map> ce = ci.next(); + + String capabilityName = ce.getKey(); + Map capabilityDef = facetCommon.findTypeFacetByName(Construct.Node, nodeType, + Facet.capabilities, capabilityName, catalog); + if (capabilityDef == null) { + theContext.addError("No capability " + capabilityName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); + continue; + } + + checkCapabilityAssignmentDefinition( + capabilityName, ce.getValue(), capabilityDef, theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + public void checkCapabilityAssignmentDefinition( + String theCapabilityName, + Map theAssignment, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(theCapabilityName, Construct.Capability); + try { + String capabilityType = (String) theDefinition.get("type"); + //list of property and attributes assignments + facetCommon.checkFacet(Construct.Capability, theAssignment, capabilityType, + Facet.properties, theContext, catalog); + facetCommon.checkFacet(Construct.Capability, theAssignment, capabilityType, + Facet.attributes, theContext, catalog); + } finally { + theContext.exit(); + } + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CheckCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CheckCommon.java new file mode 100644 index 0000000..300420f --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/CheckCommon.java @@ -0,0 +1,79 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.*; + +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.PROPERTIES; + +public class CheckCommon extends BaseCommon { + private static CheckCommon instance = null; + + public synchronized static CheckCommon getInstance() { + if (instance == null) + { + instance = new CheckCommon(); + } + return instance; + } + + private CheckCommon() {} + + public boolean checkDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext) { + if (theDefinition == null) { + theContext.addError("Missing definition for " + theName, null); + return false; + } + + if (theDefinition.isEmpty()) { + theContext.addError("Empty definition for " + theName, null); + return false; + } + + return true; + } + + public boolean checkDefinition(String theName, + List theDefinition, + Checker.CheckContext theContext) { + if (theDefinition == null) { + theContext.addError("Missing definition for " + theName, null); + return false; + } + + if (theDefinition.isEmpty()) { + theContext.addError("Empty definition for " + theName, null); + return false; + } + + return true; + } + + public void checkDataTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + theContext.enter(theName, Construct.Data); + try { + if (!checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Data, theName, theDefinition, + Facet.properties, theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ConstCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ConstCommon.java new file mode 100644 index 0000000..2a57e77 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/ConstCommon.java @@ -0,0 +1,38 @@ +package org.onap.sdc.dcae.checker.common; + +public class ConstCommon { + public static final String PROPERTIES = "properties"; + public static final String TYPE = " type "; + public static final String DEFAULT = "default"; + public static final String ATTRIBUTES = "attributes"; + public static final String DATA_TYPES = "data_types"; + public static final String VALID_SOURCE_TYPES = "valid_source_types"; + public static final String RELATIONSHIP_TYPES = "relationship_types"; + public static final String INTERFACES = "interfaces"; + public static final String VALID_TARGET_TYPES = "valid_target_types"; + public static final String ARTIFACT_TYPES = "artifact_types"; + public static final String INTERFACE_TYPES = "interface_types"; + public static final String NODE_TYPES = "node_types"; + public static final String REQUIREMENTS = "requirements"; + public static final String CAPABILITIES = "capabilities"; + public static final String GROUP_TYPES = "group_types"; + public static final String TARGETS_CONSTANT = "targets"; + public static final String POLICY_TYPES = "policy_types"; + public static final String IS_NONE_OF_THOSE = "' is none of those"; + public static final String INPUTS = "inputs"; + public static final String CAPABILITY = "capability"; + public static final String ARTIFACTS = "artifacts"; + public static final String WAS_DEFINED_FOR_THE_NODE_TYPE = " was defined for the node type "; + public static final String UNKNOWN = "Unknown "; + public static final String CAPABILITY_TYPES = "capability_types"; + public static final String GROUPS = "groups"; + public static final String RELATIONSHIP_TEMPLATES = "relationship_templates"; + public static final String OUTPUTS = "outputs"; + public static final String NODE_TEMPLATES = "node_templates"; + public static final String POLICIES = "policies"; + public static final String IMPORTED_FROM = "imported from"; + public static final String MAP = "map"; + public static final String TARGETS = "targets"; + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + private ConstCommon() {} +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/DataCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/DataCommon.java new file mode 100644 index 0000000..52ceef3 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/DataCommon.java @@ -0,0 +1,102 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.Map; + +public class DataCommon extends BaseCommon { + + private static DataCommon instance; + + public synchronized static DataCommon getInstance() { + if (instance == null) + { + instance = new DataCommon(); + } + return instance; + } + + private DataCommon() {} + + /* the type can be: + * a known type: predefined or user-defined + * a collection (list or map) and then check that the entry_schema points to one of the first two cases (is that it?) + */ + public boolean checkDataType(Map theSpec, Checker.CheckContext theContext, Catalog catalog) { + TypeCommon typeCommon = TypeCommon.getInstance(); + if (!typeCommon.checkType(Construct.Data, theSpec, theContext, catalog)) { + return false; + } + + String type = (String) theSpec.get("type"); + if (/*isCollectionType(type)*/ + "list".equals(type) || "map".equals(type)) { + Map entrySchema = (Map) theSpec.get("entry_schema"); + if (entrySchema == null) { + //maybe issue a warning ?? or is 'string' the default?? + return true; + } + + if (!catalog.hasType(Construct.Data, (String) entrySchema.get("type"))) { + theContext.addError("Unknown entry_schema type: " + entrySchema, null); + return false; + } + } + return true; + } + + /* + * For inputs/properties/attributes/(parameters). It is the caller's + * responsability to provide the value (from a 'default', inlined, ..) + * + * @param theDef the definition of the given construct/facet as it appears in + * its enclosing type definition. + * @param + */ + public boolean checkDataValuation(Object theExpr, + Map<String, ?> theDef, + Checker.CheckContext theContext) { + //first check if the expression is a function, if not handle it as a value assignment + Data.Function f = Data.function(theExpr); + if (f != null) { + return f.evaluator() + .eval(theExpr, theDef, theContext); + } else { + Data.Type type = Data.typeByName((String) theDef.get("type")); + if (type != null) { + Data.Evaluator evaluator; + + evaluator = type.evaluator(); + if (evaluator == null) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "No value evaluator available for type {}", type); + } else { + if ((theExpr != null) && (!evaluator.eval(theExpr, theDef, theContext))) { + return false; + } + } + + + evaluator = type.constraintsEvaluator(); + if (evaluator == null) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "No constraints evaluator available for type {}", type); + } else { + if (theExpr != null) { + if (!evaluator.eval(theExpr, theDef, theContext)) { + return false; + } + } else { + //should have a null value validatorT + } + } + + return true; + } else { + theContext.addError("Expression " + theExpr + " of " + theDef + " could not be evaluated", null); + return false; + } + } + } + + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/FacetCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/FacetCommon.java new file mode 100644 index 0000000..93c8416 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/FacetCommon.java @@ -0,0 +1,320 @@ +package org.onap.sdc.dcae.checker.common; + +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.DEFAULT; +import static org.onap.sdc.dcae.checker.common.ConstCommon.TYPE; +import static org.onap.sdc.dcae.checker.common.ConstCommon.UNKNOWN; + +public class FacetCommon extends BaseCommon { + + private static FacetCommon instance; + + public synchronized static FacetCommon getInstance() { + if (instance == null) + { + instance = new FacetCommon(); + } + return instance; + } + + private FacetCommon() {} + /** + * Given the type of a certain construct (node type for example), look up + * in one of its facets (properties, capabilities, ..) for one of the given + * facet type (if looking in property, one of the given data type). + * + * @return a map of all facets of the given type, will be empty to signal + * none found + * <p> + * Should we look for a facet construct of a compatible type: any type derived + * from the given facet's construct type?? + */ + public Map<String, Map> + findTypeFacetByType(Construct theTypeConstruct, + String theTypeName, + Facet theFacet, + String theFacetType, + Catalog catalog) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType {}, {}: {} {}", theTypeName, theTypeConstruct, theFacetType, theFacet); + Map<String, Map> res = new HashMap<>(); + Iterator<Map.Entry<String, Map>> i = + catalog.hierarchy(theTypeConstruct, theTypeName); + while (i.hasNext()) { + Map.Entry<String, Map> typeSpec = i.next(); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, Checking {} type {}", theTypeConstruct, typeSpec.getKey()); + Map<String, Map> typeFacet = + (Map<String, Map>) typeSpec.getValue().get(theFacet.name()); + if (typeFacet == null) { + continue; + } + Iterator<Map.Entry<String, Map>> fi = typeFacet.entrySet().iterator(); + while (fi.hasNext()) { + Map.Entry<String, Map> facet = fi.next(); + String facetType = (String) facet.getValue().get("type"); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, Checking {} type {}", facet.getKey(), facetType); + + //here is the question: do we look for an exact match or .. + //now we check that the type has a capability of a type compatible + //(equal or derived from) the given capability type. + if (catalog.isDerivedFrom( + theFacet.construct(), facetType, theFacetType)) { + res.putIfAbsent(facet.getKey(), facet.getValue()); + } + } + } + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByType, found {}", res); + + return res; + } + + public Map<String, Object> + findTypeFacetByName(Construct theTypeConstruct, + String theTypeName, + Facet theFacet, + String theFacetName, + Catalog catalog) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByName {} {}", theTypeConstruct, theTypeName); + Iterator<Map.Entry<String, Map>> i = + catalog.hierarchy(theTypeConstruct, theTypeName); + while (i.hasNext()) { + Map.Entry<String, Map> typeSpec = i.next(); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findTypeFacetByName, Checking {} type {}", theTypeConstruct, typeSpec.getKey()); + Map<String, Map> typeFacet = + (Map<String, Map>) typeSpec.getValue().get(theFacet.name()); + if (typeFacet == null) { + continue; + } + Map<String, Object> facet = typeFacet.get(theFacetName); + if (facet != null) { + return facet; + } + } + return null; + } + + /* Check that a particular facet (properties, attributes) of a construct type + * (node type, capability type, etc) is correctly (consistenly) defined + * across a type hierarchy + */ + public boolean checkTypeConstructFacet(Construct theConstruct, + String theTypeName, + Map theTypeSpec, + Facet theFacet, + Checker.CheckContext theContext, + Catalog catalog) { + Map<String, Map> defs = + (Map<String, Map>) theTypeSpec.get(theFacet.name()); + if (null == defs) { + return true; + } + + boolean res = true; + + //given that the type was cataloged there will be at least one entry + Iterator<Map.Entry<String, Map>> i = + catalog.hierarchy(theConstruct, theTypeName); + if (!i.hasNext()) { + theContext.addError( + "The type " + theTypeName + " needs to be cataloged before attempting 'checkTypeConstruct'", null); + return false; + } + i.next(); //skip self + while (i.hasNext()) { + Map.Entry<String, Map> e = i.next(); + Map<String, Map> superDefs = (Map<String, Map>) e.getValue() + .get(theFacet.name()); + if (null == superDefs) { + continue; + } + //this computes entries that appear on both collections but with different values, i.e. the re-defined properties + Map<String, MapDifference.ValueDifference<Map>> diff = Maps.difference(defs, superDefs).entriesDiffering(); + + for (Iterator<Map.Entry<String, MapDifference.ValueDifference<Map>>> di = diff.entrySet().iterator(); di.hasNext(); ) { + Map.Entry<String, MapDifference.ValueDifference<Map>> de = di.next(); + MapDifference.ValueDifference<Map> dediff = de.getValue(); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "{} type {}: {} has been re-defined between the {} types {} and {}", theConstruct, theFacet, de.getKey(), theConstruct, e.getKey(), theTypeName); + //for now we just check that the type is consistenly re-declared + if (!catalog.isDerivedFrom(theFacet.construct(), + (String) dediff.leftValue().get("type"), + (String) dediff.rightValue().get("type"))) { + theContext.addError( + theConstruct + TYPE + theFacet + ", redefiniton changed its type: " + de.getKey() + " has been re-defined between the " + theConstruct + " types " + e.getKey() + " and " + theTypeName + " in an incompatible manner", null); + res = false; + } + } + } + + return res; + } + + /* Augmentation occurs in cases such as the declaration of capabilities within a node type. + * In such cases the construct facets (the capabilitity's properties) can redefine (augment) the + * specification found in the construct type. + */ + public boolean checkFacetAugmentation(Construct theConstruct, + Map theSpec, + Facet theFacet, + Checker.CheckContext theContext, + Catalog catalog) { + return checkFacetAugmentation(theConstruct, theSpec, null, theFacet, theContext, catalog); + } + + public boolean checkFacetAugmentation(Construct theConstruct, + Map theSpec, + String theSpecType, + Facet theFacet, + Checker.CheckContext theContext, + Catalog catalog) { + + Map<String, Map> augs = (Map<String, Map>) theSpec.get(theFacet.name()); + if (null == augs) { + return true; + } + + boolean res = true; + if (theSpecType == null) { + theSpecType = (String) theSpec.get("type"); + } + if (theSpecType == null) { + theContext.addError("No specification type available", null); + return false; + } + + for (Iterator<Map.Entry<String, Map>> ai = augs.entrySet().iterator(); ai.hasNext(); ) { + Map.Entry<String, Map> ae = ai.next(); + + //make sure it was declared by the type + Map facetDef = catalog.getFacetDefinition(theConstruct, theSpecType, theFacet, ae.getKey()); + if (facetDef == null) { + theContext.addError(UNKNOWN + theConstruct + " " + theFacet + " (not declared by the type " + theSpecType + ") were used: " + ae.getKey(), null); + res = false; + continue; + } + + //check the compatibility of the augmentation: only the type cannot be changed + //can the type be changed in a compatible manner ?? + if (!facetDef.get("type").equals(ae.getValue().get("type"))) { + theContext.addError(theConstruct + " " + theFacet + " " + ae.getKey() + " has a different type than its definition: " + ae.getValue().get("type") + " instead of " + facetDef.get("type"), null); + res = false; + continue; + } + DataCommon dataCommon = DataCommon.getInstance(); + //check any valuation (here just defaults) + Object defaultValue = ae.getValue().get(DEFAULT); + if (defaultValue != null) { + dataCommon.checkDataValuation(defaultValue, ae.getValue(), theContext); + } + } + + return res; + } + + /* + * Checks the validity of a certain facet of a construct + * (properties of a node) across a type hierarchy. + * For now the check is limited to a verifying that a a facet was declared + * somewhere in the construct type hierarchy (a node template property has + * been declared in the node type hierarchy). + * + * 2 versions with the more generic allowing the specification of the type + * to be done explicitly. + */ + public boolean checkFacet(Construct theConstruct, + Map theSpec, + Facet theFacet, + Checker.CheckContext theContext, + Catalog catalog) { + return checkFacet(theConstruct, theSpec, null, theFacet, theContext, catalog); + } + + /** + * We walk the hierarchy and verify the assignment of a property with respect to its definition. + * We also collect the names of those properties defined as required but for which no assignment was provided. + */ + public boolean checkFacet(Construct theConstruct, + Map theSpec, + String theSpecType, + Facet theFacet, + Checker.CheckContext theContext, + Catalog catalog) { + + Map<String, Map> defs = (Map<String, Map>) theSpec.get(theFacet.name()); + if (null == defs) { + return true; + } + defs = Maps.newHashMap(defs); // + + boolean res = true; + if (theSpecType == null) { + theSpecType = (String) theSpec.get("type"); + } + if (theSpecType == null) { + theContext.addError("No specification type available", null); + return false; + } + + Map<String, Byte> missed = new HashMap<>(); //keeps track of the missing required properties, the value is + //false if a default was found along the hierarchy + Iterator<Map.Entry<String, Map>> i = + catalog.hierarchy(theConstruct, theSpecType); + while (i.hasNext() && !defs.isEmpty()) { + Map.Entry<String, Map> type = i.next(); + + Map<String, Map> typeDefs = (Map<String, Map>) type.getValue() + .get(theFacet.name()); + if (null == typeDefs) { + continue; + } + + MapDifference<String, Map> diff = Maps.difference(defs, typeDefs); + + //this are the ones this type and the spec have in common (same key, + //different values) + Map<String, MapDifference.ValueDifference<Map>> facetDefs = + diff.entriesDiffering(); + //TODO: this assumes the definition of the facet is not cumulative, i.e. + //subtypes 'add' something to the definition provided by the super-types + //it considers the most specialized definition stands on its own + for (MapDifference.ValueDifference<Map> valdef : facetDefs.values()) { + DataCommon dataCommon = DataCommon.getInstance(); + dataCommon.checkDataValuation(valdef.leftValue(), valdef.rightValue(), theContext); + } + + //remove from properties all those that appear in this type: unfortunately this returns an unmodifiable map .. + defs = Maps.newHashMap(diff.entriesOnlyOnLeft()); + } + + if (!defs.isEmpty()) { + theContext.addError(UNKNOWN + theConstruct + " " + theFacet + " (not declared by the type " + theSpecType + ") were used: " + defs, null); + res = false; + } + + if (!missed.isEmpty()) { + List missedNames = + missed.entrySet() + .stream() + .filter(e -> e.getValue().byteValue() == (byte) 1) + .map(e -> e.getKey()) + .collect(Collectors.toList()); + if (!missedNames.isEmpty()) { + theContext.addError(theConstruct + " " + theFacet + " missing required values for: " + missedNames, null); + res = false; + } + } + + return res; + } + + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/GroupCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/GroupCommon.java new file mode 100644 index 0000000..13ee692 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/GroupCommon.java @@ -0,0 +1,118 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; + +public class GroupCommon extends BaseCommon{ + private static GroupCommon instance; + + public synchronized static GroupCommon getInstance() { + if (instance == null) + { + instance = new GroupCommon(); + } + return instance; + } + + private GroupCommon() {} + + public void checkGroupTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName, Construct.Group); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Group, theName, theDefinition, + Facet.properties, theContext, catalog); + } + + if (theDefinition.containsKey(TARGETS_CONSTANT)) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, + ((List<String>) theDefinition.get(TARGETS_CONSTANT)).toArray(EMPTY_STRING_ARRAY)); + } + InterfaceCommon interfaceCommon = InterfaceCommon.getInstance(); + //interfaces + Map<String, Map> interfaces = + (Map<String, Map>) theDefinition.get(INTERFACES); + interfaceCommon.checkMapTypeInterfaceDefinition(theContext, interfaces, catalog); + + } finally { + theContext.exit(); + } + } + + public void checkGroupDefinition(String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + + if (!typeCommon.checkType(Construct.Group, theDef, theContext, catalog)) { + return; + } + + if (!facetCommon.checkFacet( + Construct.Group, theDef, Facet.properties, theContext, catalog)) { + return; + } + + if (theDef.containsKey(TARGETS_CONSTANT)) { + + List<String> targetsTypes = (List<String>) + catalog.getTypeDefinition(Construct.Group, + (String) theDef.get("type")) + .get(TARGETS_CONSTANT); + + List<String> targets = (List<String>) theDef.get(TARGETS_CONSTANT); + for (String targetItr : targets) { + if (!catalog.hasTemplate(theContext.target(), Construct.Node, targetItr)) { + theContext.addError("The 'targets' entry must contain a reference to a node template, '" + targetItr + "' is not one", null); + } else { + if (targetsTypes != null) { + String targetType = (String) + catalog.getTemplate(theContext.target(), Construct.Node, targetItr).get("type"); + + boolean found = false; + for (String type : targetsTypes) { + found = catalog + .isDerivedFrom(Construct.Node, targetType, type); + if (found) { + break; + } + } + + if (!found) { + theContext.addError("The 'targets' entry '" + targetItr + "' is not type compatible with any of types specified in policy type targets", null); + } + } + } + } + } + } finally { + theContext.exit(); + } + } + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InputsOutputsCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InputsOutputsCommon.java new file mode 100644 index 0000000..04fd4b1 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InputsOutputsCommon.java @@ -0,0 +1,66 @@ +package org.onap.sdc.dcae.checker.common; + +import kwalify.Rule; +import kwalify.Validator; +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; +import org.onap.sdc.dcae.checker.validation.TOSCAValidator; + +import java.util.Iterator; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.DEFAULT; + +public class InputsOutputsCommon extends BaseCommon { + + private static InputsOutputsCommon instance; + + public synchronized static InputsOutputsCommon getInstance() { + if (instance == null) + { + instance = new InputsOutputsCommon(); + } + return instance; + } + + private InputsOutputsCommon() {} + + public void checkInputDefinition(String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog) { + DataCommon dataCommon = DataCommon.getInstance(); + theContext.enter(theName); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + // + if (!dataCommon.checkDataType(theDef, theContext, catalog)) { + return; + } + //check default value + Object defaultValue = theDef.get(DEFAULT); + if (defaultValue != null) { + dataCommon.checkDataValuation(defaultValue, theDef, theContext); + } + } finally { + theContext.exit(); + } + } + + + + public void checkOutputDefinition(String theName, + Map theDef, + Checker.CheckContext theContext) { + theContext.enter(theName); + try { + CheckCommon.getInstance().checkDefinition(theName, theDef, theContext); + //check the expression + } finally { + theContext.exit(); + } + } + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InterfaceCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InterfaceCommon.java new file mode 100644 index 0000000..3d7dfef --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/InterfaceCommon.java @@ -0,0 +1,164 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.Iterator; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.INPUTS; +import static org.onap.sdc.dcae.checker.common.ConstCommon.INTERFACES; +import static org.onap.sdc.dcae.checker.common.ConstCommon.WAS_DEFINED_FOR_THE_NODE_TYPE; + +public class InterfaceCommon extends BaseCommon { + private static InterfaceCommon instance; + + public synchronized static void init(IChecker checker) { + if (instance == null) + { + instance = new InterfaceCommon(); + instance.setChecker(checker); + } + } + + public synchronized static InterfaceCommon getInstance() { + if (instance == null) + { + errLogger.log(LogLevel.ERROR, InterfaceCommon.class.getSimpleName(),"Need to call init before"); + } + return instance; + } + + private InterfaceCommon() {} + + private IChecker checker; + + //checking of actual constructs (capability, ..) + + /* First, interface types do not have a hierarchical organization (no + * 'derived_from' in a interface type definition). + * So, when interfaces (with a certain type) are defined in a node + * or relationship type (and they can define new? operations), what + * is there to check: + * Can operations here re-define their declaration from the interface + * type spec?? From A.5.11.3 we are to understand indicates override to be + * the default interpretation .. but they talk about sub-classing so it + * probably intended as a reference to the node or relationship type + * hierarchy and not the interface type (no hierarchy there). + * Or is this a a case of augmentation where new operations can be added?? + */ + public void check_type_interface_definition( + String theName, Map theDef, Checker.CheckContext theContext, Catalog catalog) { + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + + if (!typeCommon.checkType(Construct.Interface, theDef, theContext, catalog)) { + return; + } + + if (theDef.containsKey(INPUTS)) { + checker.check_inputs((Map<String, Map>) theDef.get(INPUTS), theContext); + } + } finally { + theContext.exit(); + } + } + + public void checkTemplateInterfacesDefinition( + Map<String, Map> theInterfaces, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(INTERFACES); + try { + if (!CheckCommon.getInstance().checkDefinition(INTERFACES, theInterfaces, theContext)) { + return; + } + + //the node type for the node template enclosing these requirements + String nodeType = (String) catalog.getTemplate( + theContext.target(), + Construct.Node, + theContext.enclosingConstruct(Construct.Node)) + .get("type"); + + for (Iterator<Map.Entry<String, Map>> ii = + theInterfaces.entrySet().iterator(); + ii.hasNext(); ) { + + Map.Entry<String, Map> ie = ii.next(); + + String interfaceName = ie.getKey(); + Map interfaceDef = facetCommon.findTypeFacetByName(Construct.Node, nodeType, + Facet.interfaces, interfaceName, catalog); + + if (interfaceDef == null) { + /* this is subject to augmentation: this could be a warning but not an error */ + theContext.addError("No interface " + interfaceName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); + continue; + } + + checkTemplateInterfaceDefinition( + interfaceName, ie.getValue(), interfaceDef, theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + public void checkTemplateInterfaceDefinition( + String theInterfaceName, + Map theAssignment, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(theInterfaceName, Construct.Interface); + try { + //check the assignment of the common inputs + facetCommon.checkFacet(Construct.Interface, + theAssignment, + (String) theDefinition.get("type"), + Facet.inputs, + theContext, + catalog); + } finally { + theContext.exit(); + } + } + + public void checkMapTypeInterfaceDefinition(Checker.CheckContext theContext, Map<String, Map> interfaces, Catalog catalog) { + if (interfaces != null) { + try { + theContext.enter(INTERFACES); + for (Iterator<Map.Entry<String, Map>> i = + interfaces.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, Map> e = i.next(); + check_type_interface_definition( + e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } + } + + public void checkInterfaceTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext) { + theContext.enter(theName, Construct.Interface); + try { + CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext); + } finally { + theContext.exit(); + } + } + + void setChecker(IChecker checker) { + this.checker = checker; + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/NodeCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/NodeCommon.java new file mode 100644 index 0000000..2fa9752 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/NodeCommon.java @@ -0,0 +1,197 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; + +public class NodeCommon extends BaseCommon { + + private static NodeCommon instance; + + public synchronized static void init(IChecker checker) { + if (instance == null) { + instance = new NodeCommon(); + instance.setChecker(checker); + } + } + + public synchronized static NodeCommon getInstance() { + if (instance == null) + { + errLogger.log(LogLevel.ERROR, InterfaceCommon.class.getSimpleName(),"Need to call init before"); + } + return instance; + } + + private NodeCommon() {} + + private IChecker checker; + + public void checkNodeTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + RequirementCommon requirementCommon = RequirementCommon.getInstance(); + CapabilityCommon capabilityCommon = CapabilityCommon.getInstance(); + InterfaceCommon interfaceCommon = InterfaceCommon.getInstance(); + theContext.enter(theName, Construct.Node); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Node, theName, theDefinition, + Facet.properties, theContext, catalog); + } + + if (theDefinition.containsKey(ATTRIBUTES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Node, theName, theDefinition, + Facet.attributes, theContext, catalog); + } + + //requirements + if (theDefinition.containsKey(REQUIREMENTS)) { + requirementCommon.check_requirements( + (List<Map>) theDefinition.get(REQUIREMENTS), theContext, catalog); + } + + //capabilities + if (theDefinition.containsKey(CAPABILITIES)) { + capabilityCommon.check_capabilities( + (Map<String, Map>) theDefinition.get(CAPABILITIES), theContext, catalog); + } + + //interfaces: + Map<String, Map> interfaces = + (Map<String, Map>) theDefinition.get(INTERFACES); + interfaceCommon.checkMapTypeInterfaceDefinition(theContext, interfaces, catalog); + } finally { + theContext.exit(); + } + } + + /* */ + public void checkNodeTemplateDefinition(String theName, + Map theNode, + Checker.CheckContext theContext, + Catalog catalog) { + TypeCommon typeCommon = TypeCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + RequirementCommon requirementCommon = RequirementCommon.getInstance(); + CapabilityCommon capabilityCommon = CapabilityCommon.getInstance(); + InterfaceCommon interfaceCommon = InterfaceCommon.getInstance(); + theContext.enter(theName, Construct.Node); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theNode, theContext)) { + return; + } + + if (!typeCommon.checkType(Construct.Node, theNode, theContext, catalog)) { + return; + } + + //copy + String copy = (String) theNode.get("copy"); + if (copy != null) { + if (!typeCommon.checkTemplateReference(Construct.Node, theContext, catalog, copy)) { + theContext.addError("The 'copy' reference " + copy + " does not point to a known node template", null); + } else { + //the 'copy' node specification should be used to provide 'defaults' + //for this specification + } + } + + /* check that we operate on properties and attributes within the scope of + the specified node type */ + if (!facetCommon.checkFacet( + Construct.Node, /*theName,*/theNode, Facet.properties, theContext, catalog)) { + return; + } + + if (!facetCommon.checkFacet( + Construct.Node, /*theName,*/theNode, Facet.attributes, theContext, catalog)) { + return; + } + + //requirement assignment seq + if (theNode.containsKey(REQUIREMENTS)) { + requirementCommon.checkRequirementsAssignmentDefinition( + (List<Map>) theNode.get(REQUIREMENTS), theContext, catalog); + } + + //capability assignment map: subject to augmentation + if (theNode.containsKey(CAPABILITIES)) { + capabilityCommon.checkCapabilitiesAssignmentDefinition( + (Map<String, Map>) theNode.get(CAPABILITIES), theContext, catalog); + } + + //interfaces + if (theNode.containsKey(INTERFACES)) { + interfaceCommon.checkTemplateInterfacesDefinition( + (Map<String, Map>) theNode.get(INTERFACES), theContext, catalog); + } + + //artifacts: artifacts do not have different definition forms/syntax + //depending on the context (type or template) but they are still subject + //to 'augmentation' + if (theNode.containsKey(ARTIFACTS)) { + checker.check_template_artifacts_definition( + (Map<String, Object>) theNode.get(ARTIFACTS), theContext); + } + + /* node_filter: the context to which the node filter is applied is very + * wide here as opposed to the node filter specification in a requirement + * assignment which has a more strict context (target node/capability are + * specified). + * We could check that there are nodes in this template having the + * properties/capabilities specified in this filter, i.e. the filter has + * a chance to succeed. + */ + } finally { + theContext.exit(); + } + } + + /* Requirements are the odd ball as they are structured as a sequence .. */ + public Map<String, Map> findNodeTypeRequirementByName( + String theNodeType, String theRequirementName, Catalog catalog) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findNodeTypeRequirementByName {}/{}", theNodeType, theRequirementName); + Iterator<Map.Entry<String, Map>> i = + catalog.hierarchy(Construct.Node, theNodeType); + while (i.hasNext()) { + Map.Entry<String, Map> nodeType = i.next(); + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "findNodeTypeRequirementByName, Checking node type {}", nodeType.getKey()); + List<Map<String, Map>> nodeTypeRequirements = + (List<Map<String, Map>>) nodeType.getValue().get(REQUIREMENTS); + if (nodeTypeRequirements == null) { + continue; + } + + for (Map<String, Map> requirement : nodeTypeRequirements) { + Map requirementDef = requirement.get(theRequirementName); + if (requirementDef != null) { + return requirementDef; + } + } + } + return null; + } + + public void setChecker(IChecker checker) { + this.checker = checker; + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PolicyCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PolicyCommon.java new file mode 100644 index 0000000..9c1d8cd --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PolicyCommon.java @@ -0,0 +1,134 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.*; + +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.IS_NONE_OF_THOSE; +import static org.onap.sdc.dcae.checker.common.ConstCommon.PROPERTIES; +import static org.onap.sdc.dcae.checker.common.ConstCommon.TARGETS_CONSTANT; + +public class PolicyCommon extends BaseCommon { + + private static PolicyCommon instance; + + public synchronized static PolicyCommon getInstance() { + if (instance == null) + { + instance = new PolicyCommon(); + } + return instance; + } + + private PolicyCommon() {} + + + public void checkPolicyTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog, + Target target) { + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(theName, Construct.Policy); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Policy, theName, theDefinition, + Facet.properties, theContext, catalog); + } + + //the targets can be known node types or group types + List<String> targets = (List<String>) theDefinition.get(TARGETS_CONSTANT); + if ((targets != null) && (CheckCommon.getInstance().checkDefinition(TARGETS_CONSTANT, targets, theContext))) { + for (String targetItr : targets) { + if (!(catalog.hasType(Construct.Node, targetItr) || + catalog.hasType(Construct.Group, targetItr))) { + theContext.addError("The 'targets' entry must contain a reference to a node type or group type, '" + target + IS_NONE_OF_THOSE, null); + } + } + } + } finally { + theContext.exit(); + } + } + + public void checkPolicyDefinition(String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog, + Target target) + { + FacetCommon facetCommon = FacetCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + + theContext.enter(theName); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + + if (!typeCommon.checkType(Construct.Policy, theDef, theContext, catalog)) { + return; + } + + if (!facetCommon.checkFacet(Construct.Policy, theDef, Facet.properties, theContext, catalog)) { + return; + } + + //targets: must point to node or group templates (that are of a type + //specified in the policy type definition, if targets were specified + //there). + if (theDef.containsKey(TARGETS_CONSTANT)) { + List<String> targetsTypes = (List<String>) + catalog.getTypeDefinition(Construct.Policy, + (String) theDef.get("type")) + .get(TARGETS_CONSTANT); + + List<String> targets = (List<String>) theDef.get(TARGETS_CONSTANT); + for (String targetItr : targets) { + Construct targetConstruct = null; + + if (catalog.hasTemplate(theContext.target(), Construct.Group, targetItr)) { + targetConstruct = Construct.Group; + } else if (catalog.hasTemplate(theContext.target(), Construct.Node, targetItr)) { + targetConstruct = Construct.Node; + } else { + theContext.addError("The 'targets' entry must contain a reference to a node template or group template, '" + target + IS_NONE_OF_THOSE, null); + } + + if (targetConstruct != null && + targetsTypes != null) { + //get the target type and make sure is compatible with the types + //indicated in the type spec + String targetType = (String) + catalog.getTemplate(theContext.target(), targetConstruct, targetItr).get("type"); + + boolean found = false; + for (String type : targetsTypes) { + found = catalog + .isDerivedFrom(targetConstruct, targetType, type); + if (found) { + break; + } + } + + if (!found) { + theContext.addError("The 'targets' " + targetConstruct + " entry '" + targetItr + "' is not type compatible with any of types specified in policy type targets", null); + } + } + } + } + + } finally { + theContext.exit(); + } + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PropertiesCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PropertiesCommon.java new file mode 100644 index 0000000..f19e19b --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/PropertiesCommon.java @@ -0,0 +1,97 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.Catalog; +import org.onap.sdc.dcae.checker.Checker; +import org.onap.sdc.dcae.checker.IChecker; + +import java.util.Iterator; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.DEFAULT; +import static org.onap.sdc.dcae.checker.common.ConstCommon.PROPERTIES; + +public class PropertiesCommon extends BaseCommon { + + private static PropertiesCommon instance; + + public synchronized static PropertiesCommon getInstance() { + if (instance == null) + { + instance = new PropertiesCommon(); + } + return instance; + } + + private PropertiesCommon() {} + + public void checkProperties( + Map<String, Map> theDefinitions, Checker.CheckContext theContext, Catalog catalog) { + theContext.enter(PROPERTIES); + try { + if (!CheckCommon.getInstance().checkDefinition(PROPERTIES, theDefinitions, theContext)) { + return; + } + + for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, Map> e = i.next(); + checkPropertyDefinition(e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + private void checkPropertyDefinition( + String theName, Map theDefinition, Checker.CheckContext theContext, Catalog catalog) { + DataCommon dataCommon = DataCommon.getInstance(); + theContext.enter(theName); + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + //check the type + if (!dataCommon.checkDataType(theDefinition, theContext, catalog)) { + return; + } + //check default value is compatible with type + Object defaultValue = theDefinition.get(DEFAULT); + if (defaultValue != null) { + dataCommon.checkDataValuation(defaultValue, theDefinition, theContext); + } + + theContext.exit(); + } + + public void check_property_definition(String theName, Map theDefinition, Checker.CheckContext theContext, Catalog catalog) { + DataCommon dataCommon = DataCommon.getInstance(); + theContext.enter(theName); + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + // check the type + if (!dataCommon.checkDataType(theDefinition, theContext, catalog)) { + return; + } + // check default value is compatible with type + Object defaultValue = theDefinition.get("default"); + if (defaultValue != null) { + dataCommon.checkDataValuation(defaultValue, theDefinition, theContext); + } + + theContext.exit(); + } + + public void check_properties(Map<String, Map> theDefinitions, Checker.CheckContext theContext, Catalog catalog) { + theContext.enter("properties"); + try { + if (!CheckCommon.getInstance().checkDefinition("properties", theDefinitions, theContext)) + return; + + for (Iterator<Map.Entry<String, Map>> i = theDefinitions.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, Map> e = i.next(); + check_property_definition(e.getKey(), e.getValue(), theContext, catalog); + } + } finally { + theContext.exit(); + } + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RelationshipCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RelationshipCommon.java new file mode 100644 index 0000000..145873a --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RelationshipCommon.java @@ -0,0 +1,112 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.dcae.checker.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; +import static org.onap.sdc.dcae.checker.common.ConstCommon.EMPTY_STRING_ARRAY; +import static org.onap.sdc.dcae.checker.common.ConstCommon.VALID_TARGET_TYPES; + +public class RelationshipCommon extends BaseCommon { + private static RelationshipCommon instance; + + public synchronized static RelationshipCommon getInstance() { + if (instance == null) + { + instance = new RelationshipCommon(); + } + return instance; + } + + private RelationshipCommon() {} + + public void checkRelationshipTypeDefinition(String theName, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + PropertiesCommon propertiesCommon = PropertiesCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + InterfaceCommon interfaceCommon = InterfaceCommon.getInstance(); + theContext.enter(theName, Construct.Relationship); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDefinition, theContext)) { + return; + } + + if (theDefinition.containsKey(PROPERTIES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(PROPERTIES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, + Facet.properties, theContext, catalog); + } + + if (theDefinition.containsKey(ATTRIBUTES)) { + propertiesCommon.checkProperties( + (Map<String, Map>) theDefinition.get(ATTRIBUTES), theContext, catalog); + facetCommon.checkTypeConstructFacet(Construct.Relationship, theName, theDefinition, + Facet.attributes, theContext, catalog); + } + + Map<String, Map> interfaces = (Map<String, Map>) theDefinition.get(INTERFACES); + if (interfaces != null) { + theContext.enter(INTERFACES); + for (Iterator<Map.Entry<String, Map>> i = + interfaces.entrySet().iterator(); i.hasNext(); ) { + Map.Entry<String, Map> e = i.next(); + interfaceCommon.check_type_interface_definition( + e.getKey(), e.getValue(), theContext, catalog); + } + theContext.exit(); + } + + if (theDefinition.containsKey(VALID_TARGET_TYPES)) { + typeCommon.checkTypeReference(Construct.Capability, theContext , catalog, + ((List<String>) theDefinition.get(VALID_TARGET_TYPES)).toArray(EMPTY_STRING_ARRAY)); + } + } finally { + theContext.exit(); + } + } + + public void checkRelationshipTemplateDefinition( + String theName, + Map theRelationship, + Checker.CheckContext theContext, + Catalog catalog) { + FacetCommon facetCommon = FacetCommon.getInstance(); + TypeCommon typeCommon = TypeCommon.getInstance(); + theContext.enter(theName, Construct.Relationship); + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theRelationship, theContext)) { + return; + } + + if (!typeCommon.checkType(Construct.Relationship, theRelationship, theContext, catalog)) { + return; + } + + /* check that we operate on properties and attributes within the scope of + the specified relationship type */ + if (!facetCommon.checkFacet(Construct.Relationship, theRelationship, + Facet.properties, theContext, catalog)) { + return; + } + + if (!facetCommon.checkFacet(Construct.Relationship, theRelationship, + Facet.attributes, theContext, catalog)) { + return; + } + + /* interface definitions + note: augmentation is allowed here so not clear what to check .. + maybe report augmentations if so configured .. */ + + } finally { + theContext.exit(); + } + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RequirementCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RequirementCommon.java new file mode 100644 index 0000000..ff2c2f2 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/RequirementCommon.java @@ -0,0 +1,464 @@ +package org.onap.sdc.dcae.checker.common; + +import org.apache.commons.jxpath.JXPathContext; +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.*; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; + +public class RequirementCommon extends BaseCommon { + + private static RequirementCommon instance; + + public synchronized static RequirementCommon getInstance() { + if (instance == null) + { + instance = new RequirementCommon(); + } + return instance; + } + + private RequirementCommon() {} + + public void check_requirements(List<Map> theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + theContext.enter(REQUIREMENTS); + try { + if (!CheckCommon.getInstance().checkDefinition(REQUIREMENTS, theDefinition, theContext)) { + return; + } + + for (Iterator<Map> i = theDefinition.iterator(); i.hasNext(); ) { + Map e = i.next(); + Iterator<Map.Entry<String, Map>> ei = + (Iterator<Map.Entry<String, Map>>) e.entrySet().iterator(); + Map.Entry<String, Map> eie = ei.next(); + checkRequirementDefinition(eie.getKey(), eie.getValue(), theContext, catalog); + assert !ei.hasNext(); + } + } finally { + theContext.exit(); + } + } + + public void checkRequirementDefinition(String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog) { + TypeCommon typeCommon = TypeCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext.enter(theName, Construct.Requirement); + + try { + if (!CheckCommon.getInstance().checkDefinition(theName, theDef, theContext)) { + return; + } + //check capability type + String capabilityType = (String) theDef.get(CAPABILITY); + if (null != capabilityType) { + typeCommon.checkTypeReference(Construct.Capability, theContext, catalog, capabilityType); + } + + //check node type + String nodeType = (String) theDef.get("node"); + if (null != nodeType) { + typeCommon.checkTypeReference(Construct.Node, theContext, catalog, nodeType); + } + + //check relationship type + Map relationshipSpec = (Map) theDef.get("relationship"); + String relationshipType = null; + if (null != relationshipSpec) { + relationshipType = (String) relationshipSpec.get("type"); + if (relationshipType != null) { //should always be the case + typeCommon.checkTypeReference(Construct.Relationship, theContext, catalog, relationshipType); + } + + Map<String, Map> interfaces = (Map<String, Map>) + relationshipSpec.get(INTERFACES); + if (interfaces != null) { + //augmentation (additional properties or operations) of the interfaces + //defined by the above relationship types + + //check that the interface types are known + for (Map interfaceDef : interfaces.values()) { + typeCommon.checkType(Construct.Interface, interfaceDef, theContext, catalog); + } + } + } + + //cross checks + + //the capability definition might come from the capability type or from the capability definition + //within the node type. We might have more than one as a node might specify multiple capabilities of the + //same type. + //the goal here is to cross check the compatibility of the valid_source_types specification in the + //target capability definition (if that definition contains a valid_source_types entry). + List<Map> capabilityDefs = new LinkedList<>(); + //nodeType exposes capabilityType + if (nodeType != null) { + Map<String, Map> capabilities = + facetCommon.findTypeFacetByType(Construct.Node, nodeType, + Facet.capabilities, capabilityType, catalog); + if (capabilities.isEmpty()) { + theContext.addError("The node type " + nodeType + " does not appear to expose a capability of a type compatible with " + capabilityType, null); + } else { + for (Map.Entry<String, Map> capability : capabilities.entrySet()) { + //this is the capability as it was defined in the node type + Map capabilityDef = capability.getValue(); + //if it defines a valid_source_types then we're working with it, + //otherwise we're working with the capability type it points to. + //The spec does not make it clear if the valid_source_types in a capability definition augments or + //overwrites the one from the capabilityType (it just says they must be compatible). + if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { + capabilityDefs.add(capabilityDef); + } else { + capabilityDef = + catalog.getTypeDefinition(Construct.Capability, (String) capabilityDef.get("type")); + if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { + capabilityDefs.add(capabilityDef); + } else { + //!!if there is a capability that does not have a valid_source_type than there is no reason to + //make any further verification (as there is a valid node_type/capability target for this requirement) + capabilityDefs.clear(); + break; + } + } + } + } + } else { + Map capabilityDef = catalog.getTypeDefinition(Construct.Capability, capabilityType); + if (capabilityDef.containsKey(VALID_SOURCE_TYPES)) { + capabilityDefs.add(capabilityDef); + } + } + + //check that the node type enclosing this requirement definition + //is in the list of valid_source_types + if (!capabilityDefs.isEmpty()) { + String enclosingNodeType = + theContext.enclosingConstruct(Construct.Node); + assert enclosingNodeType != null; + + if (!capabilityDefs.stream().anyMatch( + (Map capabilityDef) -> { + List<String> valid_source_types = + (List<String>) capabilityDef.get(VALID_SOURCE_TYPES); + return valid_source_types.stream().anyMatch( + (String source_type) -> catalog.isDerivedFrom( + Construct.Node, enclosingNodeType, source_type)); + })) { + theContext.addError("Node type: " + enclosingNodeType + " not compatible with any of the valid_source_types provided in the definition of compatible capabilities", null); + } + } + + //if we have a relationship type, check if it has a valid_target_types + //if it does, make sure that the capability type is compatible with one + //of them + if (relationshipType != null) { //should always be the case + Map relationshipTypeDef = catalog.getTypeDefinition( + Construct.Relationship, relationshipType); + if (relationshipTypeDef != null) { + List<String> valid_target_types = + (List<String>) relationshipTypeDef.get(VALID_TARGET_TYPES); + if (valid_target_types != null) { + boolean found = false; + for (String target_type : valid_target_types) { + if (catalog.isDerivedFrom( + Construct.Capability, capabilityType, target_type)) { + found = true; + break; + } + } + if (!found) { + theContext.addError("Capability type: " + capabilityType + " not compatible with any of the valid_target_types " + valid_target_types + " provided in the definition of relationship type " + relationshipType, null); + } + } + } + } + + //relationship declares the capabilityType in its valid_target_type set + //in A.6.9 'Relationship Type' the spec does not indicate how inheritance + //is to be applied to the valid_target_type spec: cumulative, overwrites, + //so we treat it as an overwrite. + } finally { + theContext.exit(); + } + } + + //requirements and capabilities assignment appear in a node templates + public void checkRequirementsAssignmentDefinition( + List<Map> theRequirements, Checker.CheckContext theContext, Catalog catalog) { + NodeCommon nodeCommon = NodeCommon.getInstance(); + theContext.enter(REQUIREMENTS); + try { + if (!CheckCommon.getInstance().checkDefinition(REQUIREMENTS, theRequirements, theContext)) { + return; + } + + //the node type for the node template enclosing these requirements + String nodeType = (String) catalog.getTemplate( + theContext.target(), + Construct.Node, + theContext.enclosingConstruct(Construct.Node)) + .get("type"); + + for (Iterator<Map> ri = theRequirements.iterator(); ri.hasNext(); ) { + Map<String, Map> requirement = (Map<String, Map>) ri.next(); + + Iterator<Map.Entry<String, Map>> rai = requirement.entrySet().iterator(); + + Map.Entry<String, Map> requirementEntry = rai.next(); + assert !rai.hasNext(); + + String requirementName = requirementEntry.getKey(); + Map requirementDef = nodeCommon.findNodeTypeRequirementByName( + nodeType, requirementName, catalog); + + if (requirementDef == null) { + theContext.addError("No requirement " + requirementName + WAS_DEFINED_FOR_THE_NODE_TYPE + nodeType, null); + continue; + } + + checkRequirementAssignmentDefinition( + requirementName, requirementEntry.getValue(), requirementDef, theContext, catalog); + } + } finally { + theContext.exit(); + } + } + + public void checkRequirementAssignmentDefinition( + String theRequirementName, + Map theAssignment, + Map theDefinition, + Checker.CheckContext theContext, + Catalog catalog) { + TypeCommon typeCommon = TypeCommon.getInstance(); + FacetCommon facetCommon = FacetCommon.getInstance(); + theContext//.enter("requirement_assignment") + .enter(theRequirementName, Construct.Requirement); + + //grab the node type definition to verify compatibility + + try { + //node assignment + boolean targetNodeIsTemplate = false; + String targetNode = (String) theAssignment.get("node"); + if (targetNode == null) { + targetNode = (String) theDefinition.get("node"); + //targetNodeIsTemplate stays false, targetNode must be a type + } else { + //the value must be a node template or a node type + targetNodeIsTemplate = typeCommon.isTemplateReference( + Construct.Node, theContext, targetNode, catalog); + if ((!targetNodeIsTemplate) && (!typeCommon.isTypeReference(Construct.Node, targetNode, catalog))){ + theContext.addError("The 'node' entry must contain a reference to a node template or node type, '" + targetNode + IS_NONE_OF_THOSE, null); + return; + } + + //additional checks + String targetNodeDef = (String) theDefinition.get("node"); + if (targetNodeDef != null && targetNode != null) { + if (targetNodeIsTemplate) { + //if the target is node template, it must be compatible with the + //node type specification in the requirement defintion + String targetNodeType = (String) + catalog.getTemplate(theContext.target(), Construct.Node, targetNode).get("type"); + if (!catalog.isDerivedFrom( + Construct.Node, targetNodeType, targetNodeDef)) { + theContext.addError("The required target node type '" + targetNodeType + "' of target node " + targetNode + " is not compatible with the target node type found in the requirement definition: " + targetNodeDef, null); + return; + } + } else { + //if the target is a node type it must be compatible (= or derived + //from) with the node type specification in the requirement definition + if (!catalog.isDerivedFrom( + Construct.Node, targetNode, targetNodeDef)) { + theContext.addError("The required target node type '" + targetNode + "' is not compatible with the target node type found in the requirement definition: " + targetNodeDef, null); + return; + } + } + } + } + + String targetNodeType = targetNodeIsTemplate ? + (String) catalog.getTemplate(theContext.target(), Construct.Node, targetNode).get("type") : + targetNode; + + //capability assignment + boolean targetCapabilityIsType = false; + String targetCapability = (String) theAssignment.get(CAPABILITY); + if (targetCapability == null) { + targetCapability = (String) theDefinition.get(CAPABILITY); + //in a requirement definition the target capability can only be a + //capability type (and not a capability name within some target node + //type) + targetCapabilityIsType = true; + } else { + targetCapabilityIsType = typeCommon.isTypeReference(Construct.Capability, targetCapability, catalog); + + //check compatibility with the target compatibility type specified + //in the requirement definition, if any + String targetCapabilityDef = (String) theDefinition.get(CAPABILITY); + if (targetCapabilityDef != null && targetCapability != null) { + if (targetCapabilityIsType) { + if (!catalog.isDerivedFrom( + Construct.Capability, targetCapability, targetCapabilityDef)) { + theContext.addError("The required target capability type '" + targetCapability + "' is not compatible with the target capability type found in the requirement definition: " + targetCapabilityDef, null); + return; + } + } else { + //the capability is from a target node. Find its definition and + //check that its type is compatible with the capability type + //from the requirement definition + + //check target capability compatibility with target node + if (targetNode == null) { + theContext.addError("The capability '" + targetCapability + "' is not a capability type, hence it has to be a capability of the node template indicated in 'node', which was not specified", null); + return; + } + if (!targetNodeIsTemplate) { + theContext.addError("The capability '" + targetCapability + "' is not a capability type, hence it has to be a capability of the node template indicated in 'node', but there you specified a node type", null); + return; + } + //check that the targetNode (its type) indeed has the + //targetCapability + + Map<String, Object> targetNodeCapabilityDef = + facetCommon.findTypeFacetByName( + Construct.Node, targetNodeType, + Facet.capabilities, targetCapability, catalog); + if (targetNodeCapabilityDef == null) { + theContext.addError("No capability '" + targetCapability + "' was specified in the node " + targetNode + " of type " + targetNodeType, null); + return; + } + + String targetNodeCapabilityType = (String) targetNodeCapabilityDef.get("type"); + + if (!catalog.isDerivedFrom(Construct.Capability, + targetNodeCapabilityType, + targetCapabilityDef)) { + theContext.addError("The required target capability type '" + targetCapabilityDef + "' is not compatible with the target capability type found in the target node type capability definition : " + targetNodeCapabilityType + ", targetNode " + targetNode + ", capability name " + targetCapability, null); + return; + } + } + } + } + + //relationship assignment + Map targetRelationship = (Map) theAssignment.get("relationship"); + if (targetRelationship != null) { + //this has to be compatible with the relationship with the same name + //from the node type + //check the type + } + + //node_filter; used jxpath to simplify the navigation somewhat + //this is too cryptic + JXPathContext jxPath = JXPathContext.newContext(theAssignment); + jxPath.setLenient(true); + + List<Map> propertiesFilter = + (List<Map>) jxPath.getValue("/node_filter/properties"); + if (propertiesFilter != null) { + for (Map propertyFilter : propertiesFilter) { + if (targetNode != null) { + //if we have a target node or node template then it must have + //have these properties + for (Object propertyName : propertyFilter.keySet()) { + if (null == facetCommon.findTypeFacetByName(Construct.Node, + targetNodeType, + Facet.properties, + propertyName.toString(), + catalog)) { + theContext.addError("The node_filter property " + propertyName + " is invalid: requirement target node " + targetNode + " does not have such a property", null); + } + } + } + } + } + + List<Map> capabilitiesFilter = + (List<Map>) jxPath.getValue("node_filter/capabilities"); + if (capabilitiesFilter != null) { + for (Map capabilityFilterDef : capabilitiesFilter) { + assert capabilityFilterDef.size() == 1; + Map.Entry<String, Map> capabilityFilterEntry = + (Map.Entry<String, Map>) capabilityFilterDef.entrySet().iterator().next(); + String targetFilterCapability = capabilityFilterEntry.getKey(); + Map<String, Object> targetFilterCapabilityDef = null; + + //if we have a targetNode capabilityName must be a capability of + //that node (type); or it can be simply capability type (but the node + //must have a capability of that type) + + String targetFilterCapabilityType = null; + if (targetNode != null) { + targetFilterCapabilityDef = + facetCommon.findTypeFacetByName(Construct.Node, targetNodeType, + Facet.capabilities, targetFilterCapability, catalog); + if (targetFilterCapabilityDef != null) { + targetFilterCapabilityType = + (String) targetFilterCapabilityDef/*.values().iterator().next()*/.get("type"); + } else { + Map<String, Map> targetFilterCapabilities = + facetCommon.findTypeFacetByType(Construct.Node, targetNodeType, + Facet.capabilities, targetFilterCapability, catalog); + + if (!targetFilterCapabilities.isEmpty()) { + if (targetFilterCapabilities.size() > 1) { + errLogger.log(LogLevel.WARN, this.getClass().getName(), "checkRequirementAssignmentDefinition: filter check, target node type '{}' has more than one capability of type '{}', not supported", targetNodeType, targetFilterCapability); + } + //pick the first entry, it represents a capability of the required type + Map.Entry<String, Map> capabilityEntry = targetFilterCapabilities.entrySet().iterator().next(); + targetFilterCapabilityDef = Collections.singletonMap(capabilityEntry.getKey(), + capabilityEntry.getValue()); + targetFilterCapabilityType = targetFilterCapability; + } + } + } else { + //no node (type) specified, it can be a straight capability type + targetFilterCapabilityDef = catalog.getTypeDefinition( + Construct.Capability, targetFilterCapability); + //here comes the odd part: it can still be a just a name in which + //case we should look at the requirement definition, see which + //capability (type) it indicates + assert targetCapabilityIsType; //cannot be otherwise, we'd need a node + targetFilterCapabilityDef = catalog.getTypeDefinition( + Construct.Capability, targetCapability); + targetFilterCapabilityType = targetCapability; + } + + if (targetFilterCapabilityDef == null) { + theContext.addError("Capability (name or type) " + targetFilterCapability + " is invalid: not a known capability (type) " + + ((targetNodeType != null) ? (" of node type" + targetNodeType) : ""), null); + continue; + } + + for (Map propertyFilter : + (List<Map>) jxPath.getValue("/node_filter/capabilities/" + targetFilterCapability + "/properties")) { + //check that the properties are in the scope of the + //capability definition + for (Object propertyName : propertyFilter.keySet()) { + if (null == facetCommon.findTypeFacetByName(Construct.Capability, + targetCapability, + Facet.properties, + propertyName.toString(), + catalog)) { + theContext.addError("The capability filter " + targetFilterCapability + " property " + propertyName + " is invalid: target capability " + targetFilterCapabilityType + " does not have such a property", null); + } + } + } + } + } + + } finally { + theContext.exit(); + } + } + +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/TypeCommon.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/TypeCommon.java new file mode 100644 index 0000000..9fb4226 --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/common/TypeCommon.java @@ -0,0 +1,115 @@ +package org.onap.sdc.dcae.checker.common; + +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.dcae.checker.*; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.onap.sdc.dcae.checker.common.ConstCommon.*; + +public class TypeCommon extends BaseCommon { + + private static TypeCommon instance; + + public synchronized static TypeCommon getInstance() { + if (instance == null) + { + instance = new TypeCommon(); + } + return instance; + } + + private TypeCommon() {} + + public boolean catalogTypes(Construct theConstruct, Map<String, Map> theTypes, Checker.CheckContext theContext, Catalog catalog) { + + boolean res = true; + for (Map.Entry<String, Map> typeEntry : theTypes.entrySet()) { + res &= catalogType(theConstruct, typeEntry.getKey(), typeEntry.getValue(), theContext, catalog); + } + + return res; + } + + public boolean catalogType(Construct theConstruct, + String theName, + Map theDef, + Checker.CheckContext theContext, + Catalog catalog) { + + if (!catalog.addType(theConstruct, theName, theDef)) { + theContext.addError(theConstruct + TYPE + theName + " re-declaration", null); + return false; + } + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "{} type {} has been cataloged", theConstruct, theName); + + String parentType = (String) theDef.get("derived_from"); + if (parentType != null && !catalog.hasType(theConstruct, parentType)) { + theContext.addError( + theConstruct + TYPE + theName + " indicates a supertype that has not (yet) been declared: " + parentType, null); + return false; + } + return true; + } + + public boolean checkTypeReference(Construct theConstruct, + Checker.CheckContext theContext, + Catalog catalog, + String... theTypeNames) { + boolean res = true; + for (String typeName : theTypeNames) { + if (!isTypeReference(theConstruct, typeName, catalog)) { + theContext.addError("Reference to " + theConstruct + " type '" + typeName + "' points to unknown type", null); + res = false; + } + } + return res; + } + + public boolean isTypeReference(Construct theConstruct, + String theTypeName, Catalog catalog) { + return catalog.hasType(theConstruct, theTypeName); + } + + //generic checking actions, not related to validation rules + + /* will check the validity of the type specification for any construct containing a 'type' entry */ + public boolean checkType(Construct theCategory, Map theSpec, Checker.CheckContext theContext, Catalog catalog) { + String type = (String) theSpec.get("type"); + if (type == null) { + theContext.addError("Missing type specification", null); + return false; + } + + if (!catalog.hasType(theCategory, type)) { + theContext.addError(UNKNOWN + theCategory + " type: " + type, null); + return false; + } + + return true; + } + + /* node or relationship templates */ + public boolean checkTemplateReference(Construct theConstruct, + Checker.CheckContext theContext, + Catalog catalog, + String... theTemplateNames) { + boolean res = true; + for (String templateName : theTemplateNames) { + if (!isTemplateReference(theConstruct, theContext, templateName, catalog)) { + theContext.addError("Reference to " + theConstruct + " template '" + templateName + "' points to unknown template", null); + res = false; + } + } + return res; + } + + public boolean isTemplateReference(Construct theConstruct, + Checker.CheckContext theContext, + String theTemplateName, + Catalog catalog) { + return catalog.hasTemplate(theContext.target(), theConstruct, theTemplateName); + } +} diff --git a/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/validation/TOSCAValidator.java b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/validation/TOSCAValidator.java new file mode 100644 index 0000000..38bd84f --- /dev/null +++ b/dcaedt_validator/checker/src/main/java/org/onap/sdc/dcae/checker/validation/TOSCAValidator.java @@ -0,0 +1,115 @@ +package org.onap.sdc.dcae.checker.validation; + +import kwalify.Rule; +import kwalify.Types; +import kwalify.Validator; +import org.onap.sdc.common.onaplog.Enums.LogLevel; +import org.onap.sdc.common.onaplog.OnapLoggerDebug; +import org.onap.sdc.common.onaplog.OnapLoggerError; +import org.onap.sdc.dcae.checker.IChecker; +import org.onap.sdc.dcae.checker.Target; + +import java.util.*; + +public class TOSCAValidator extends Validator { + private static OnapLoggerError errLogger = OnapLoggerError.getInstance(); + private static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance(); + private final IChecker checker; + //what were validating + private Target target; + + /* Some of the TOSCA entries accept a 'short form/notation' instead of the canonical map representation. + * kwalify cannot easily express these alternatives and as such we handle them here. In the pre-validation phase we detect the presence of a short notation +and compute the canonical form and validate it. In the post-validation phase we +substitute the canonical form for the short form so that checking does not have to deal with it. + */ + + public Map<String, Object> getCanonicals() { + return canonicals; + } + + private Map<String, Object> canonicals = new TreeMap<>(); + + public TOSCAValidator(Target theTarget, Object theSchema, IChecker checker) { + super(theSchema); + this.checker = checker; + this.target = theTarget; + } + + public Target getTarget() { + return this.target; + } + + /* hook method called by Validator#validate() + */ + @Override + protected boolean preValidationHook(Object value, Rule rule, ValidationContext context) { + + checker.validationHook("pre", value, rule, context); + //short form handling + String hint = rule.getShort(); + if (value != null && + hint != null) { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Attempting canonical at {}, rule {}", context.getPath(), rule.getName()); + + Object canonical = null; + //if the canonical form requires a collection + if (Types.isCollectionType(rule.getType())) { + //and the actual value isn't one + if (!(value instanceof Map || value instanceof List)) { + //used to use singleton map/list here (was good for catching errors) + //but there is the possibility if short forms within short forms so + //the created canonicals need to accomodate other values. + if (Types.isMapType(rule.getType())) { + canonical = new HashMap(); + ((Map) canonical).put(hint, value); + } else { + //the hint is irrelevant here but we should impose a value when the target is a list + canonical = new LinkedList(); + ((List) canonical).add(value); + } + } else { + //we can accomodate: + // map to list of map transformation + if (!Types.isMapType(rule.getType()) /* a seq */ && + value instanceof Map) { + canonical = new LinkedList(); + ((List) canonical).add(value); + } else { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Grammar for rule {} (at {}) would require unsupported short form transformation: {} to {}", rule.getName(), context.getPath(), value.getClass(), rule.getType()); + return false; + } + } + + int errc = context.errorCount(); + validateRule(canonical, rule, context); + if (errc != context.errorCount()) { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Short notation for {} through {} at {} failed validation", rule.getName(), hint, context.getPath()); + } else { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Short notation for {} through {} at {} passed validation. Canonical form is {}", rule.getName(), hint, context.getPath(), canonical); + //replace the short notation with the canonicall one so we don't + //have to deal it again during checking + this.canonicals.put(context.getPath(), canonical); + return true; + } + } else { + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Grammar for rule {} (at {}) would require unsupported short form transformation: {} to {}", rule.getName(), context.getPath(), value.getClass(), rule.getType()); + } + } + + //perform default validation process + return false; + } + + /* + * Only gets invoked once the value was succesfully verified against the syntax indicated by the given rule. + */ + @Override + protected void postValidationHook(Object value, + Rule rule, + ValidationContext context) { + checker.validationHook("post", value, rule, context); + } + +}
\ No newline at end of file @@ -0,0 +1,221 @@ +[INFO] Scanning for projects...
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-deploy-plugin/2.8.2/maven-deploy-plugin-2.8.2.pom
+3/7 KB
+5/7 KB
+7/7 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-deploy-plugin/2.8.2/maven-deploy-plugin-2.8.2.pom (7 KB at 8.5 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.5.1/maven-site-plugin-3.5.1.pom
+3/18 KB
+5/18 KB
+8/18 KB
+11/18 KB
+13/18 KB
+16/18 KB
+18/18 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.5.1/maven-site-plugin-3.5.1.pom (18 KB at 91.8 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/28/maven-plugins-28.pom
+3/12 KB
+5/12 KB
+8/12 KB
+11/12 KB
+12/12 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/28/maven-plugins-28.pom (12 KB at 10.0 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/maven-parent/27/maven-parent-27.pom
+3/40 KB
+5/40 KBorg.onap
+8/40 KB
+11/40 KB
+13/40 KB
+16/40 KB
+19/40 KB
+21/40 KB
+24/40 KB
+27/40 KB
+29/40 KB
+32/40 KB
+36/40 KB
+40/40 KB
+40/40 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/maven-parent/27/maven-parent-27.pom (40 KB at 98.4 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/apache/17/apache-17.pom
+4/16 KB
+8/16 KB
+12/16 KB
+16/16 KB
+16/16 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/apache/17/apache-17.pom (16 KB at 112.0 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/jooq/jooq-codegen-maven/3.8.4/jooq-codegen-maven-3.8.4.pom
+3/3 KB
+3/3 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/jooq/jooq-codegen-maven/3.8.4/jooq-codegen-maven-3.8.4.pom (3 KB at 16.4 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/jooq/jooq-parent/3.8.4/jooq-parent-3.8.4.pom
+3/10 KB
+5/10 KB
+8/10 KB
+10/10 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/jooq/jooq-parent/3.8.4/jooq-parent-3.8.4.pom (10 KB at 83.6 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/jooq/jooq-codegen-maven/3.8.4/jooq-codegen-maven-3.8.4.jar
+3/15 KB
+5/15 KB
+8/15 KB
+11/15 KB
+13/15 KB
+15/15 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/jooq/jooq-codegen-maven/3.8.4/jooq-codegen-maven-3.8.4.jar (15 KB at 97.7 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.8/maven-antrun-plugin-1.8.pom
+3/4 KB
+4/4 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.8/maven-antrun-plugin-1.8.pom (4 KB at 20.5 KB/sec)
+Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.8/maven-antrun-plugin-1.8.jar
+3/36 KB
+5/36 KB
+8/36 KB
+11/36 KB
+13/36 KB
+16/36 KB
+19/36 KB
+21/36 KB
+24/36 KB
+27/36 KB
+29/36 KB
+32/36 KB
+35/36 KB
+36/36 KB
+
+Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.8/maven-antrun-plugin-1.8.jar (36 KB at 205.6 KB/sec)
+[INFO]
+[INFO] ------------------------------------------------------------------------
+[INFO] Building CCDLogAdminSystem 0.0.1-SNAPSHOT
+[INFO] ------------------------------------------------------------------------
+[INFO]
+[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ logparser ---
+[INFO] org.onap.sdc.dcae.composition:logparser:jar:0.0.1-SNAPSHOT
+[INFO] +- org.springframework.boot:spring-boot-starter-jersey:jar:1.4.1.RELEASE:compile
+[INFO] | +- org.springframework.boot:spring-boot-starter:jar:1.4.1.RELEASE:compile
+[INFO] | | +- org.springframework.boot:spring-boot:jar:1.4.1.RELEASE:compile
+[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:1.4.1.RELEASE:compile
+[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:1.4.1.RELEASE:compile
+[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.1.7:compile
+[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.1.7:compile
+[INFO] | | | +- org.slf4j:jul-to-slf4j:jar:1.7.21:compile
+[INFO] | | | \- org.slf4j:log4j-over-slf4j:jar:1.7.21:compile
+[INFO] | | \- org.yaml:snakeyaml:jar:1.17:runtime
+[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.4.1.RELEASE:compile
+[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.5:compile
+[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.5:compile
+[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.5:compile
+[INFO] | +- org.springframework.boot:spring-boot-starter-validation:jar:1.4.1.RELEASE:compile
+[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.3:compile
+[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.3:compile
+[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.8.3:compile
+[INFO] | +- org.springframework:spring-web:jar:4.3.3.RELEASE:compile
+[INFO] | | +- org.springframework:spring-aop:jar:4.3.3.RELEASE:compile
+[INFO] | | +- org.springframework:spring-beans:jar:4.3.3.RELEASE:compile
+[INFO] | | \- org.springframework:spring-context:jar:4.3.3.RELEASE:compile
+[INFO] | +- org.glassfish.jersey.core:jersey-server:jar:2.23.2:compile
+[INFO] | | +- org.glassfish.jersey.core:jersey-common:jar:2.23.2:compile
+[INFO] | | | +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.23.2:compile
+[INFO] | | | \- org.glassfish.hk2:osgi-resource-locator:jar:1.0.1:compile
+[INFO] | | +- org.glassfish.jersey.core:jersey-client:jar:2.23.2:compile
+[INFO] | | +- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile
+[INFO] | | +- org.glassfish.jersey.media:jersey-media-jaxb:jar:2.23.2:compile
+[INFO] | | +- javax.annotation:javax.annotation-api:jar:1.2:compile
+[INFO] | | +- org.glassfish.hk2:hk2-api:jar:2.5.0-b05:compile
+[INFO] | | | +- org.glassfish.hk2:hk2-utils:jar:2.5.0-b05:compile
+[INFO] | | | \- org.glassfish.hk2.external:aopalliance-repackaged:jar:2.5.0-b05:compile
+[INFO] | | +- org.glassfish.hk2.external:javax.inject:jar:2.5.0-b05:compile
+[INFO] | | +- org.glassfish.hk2:hk2-locator:jar:2.5.0-b05:compile
+[INFO] | | \- javax.validation:validation-api:jar:1.1.0.Final:compile
+[INFO] | +- org.glassfish.jersey.containers:jersey-container-servlet-core:jar:2.23.2:compile
+[INFO] | +- org.glassfish.jersey.containers:jersey-container-servlet:jar:2.23.2:compile
+[INFO] | +- org.glassfish.jersey.ext:jersey-bean-validation:jar:2.23.2:compile
+[INFO] | +- org.glassfish.jersey.ext:jersey-spring3:jar:2.23.2:compile
+[INFO] | | +- org.glassfish.hk2:hk2:jar:2.5.0-b05:compile
+[INFO] | | | +- org.glassfish.hk2:config-types:jar:2.5.0-b05:compile
+[INFO] | | | +- org.glassfish.hk2:hk2-core:jar:2.5.0-b05:compile
+[INFO] | | | +- org.glassfish.hk2:hk2-config:jar:2.5.0-b05:compile
+[INFO] | | | +- org.glassfish.hk2:hk2-runlevel:jar:2.5.0-b05:compile
+[INFO] | | | \- org.glassfish.hk2:class-model:jar:2.5.0-b05:compile
+[INFO] | | | \- org.glassfish.hk2.external:asm-all-repackaged:jar:2.5.0-b05:compile
+[INFO] | | \- org.glassfish.hk2:spring-bridge:jar:2.5.0-b05:compile
+[INFO] | \- org.glassfish.jersey.media:jersey-media-json-jackson:jar:2.23.2:compile
+[INFO] | +- org.glassfish.jersey.ext:jersey-entity-filtering:jar:2.23.2:compile
+[INFO] | +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.8.3:compile
+[INFO] | \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.8.3:compile
+[INFO] | \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.8.3:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:1.4.1.RELEASE:compile
+[INFO] | +- org.hibernate:hibernate-validator:jar:5.2.4.Final:compile
+[INFO] | | +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
+[INFO] | | \- com.fasterxml:classmate:jar:1.3.1:compile
+[INFO] | \- org.springframework:spring-webmvc:jar:4.3.3.RELEASE:compile
+[INFO] | \- org.springframework:spring-expression:jar:4.3.3.RELEASE:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-web-services:jar:1.4.1.RELEASE:compile
+[INFO] | +- org.springframework:spring-oxm:jar:4.3.3.RELEASE:compile
+[INFO] | \- org.springframework.ws:spring-ws-core:jar:2.3.0.RELEASE:compile
+[INFO] | \- org.springframework.ws:spring-xml:jar:2.3.0.RELEASE:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-websocket:jar:1.4.1.RELEASE:compile
+[INFO] | +- org.springframework:spring-messaging:jar:4.3.3.RELEASE:compile
+[INFO] | \- org.springframework:spring-websocket:jar:4.3.3.RELEASE:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:1.4.1.RELEASE:test
+[INFO] | +- org.springframework.boot:spring-boot-test:jar:1.4.1.RELEASE:test
+[INFO] | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:1.4.1.RELEASE:test
+[INFO] | +- com.jayway.jsonpath:json-path:jar:2.2.0:test
+[INFO] | | +- net.minidev:json-smart:jar:2.2.1:test
+[INFO] | | | \- net.minidev:accessors-smart:jar:1.1:test
+[INFO] | | | \- org.ow2.asm:asm:jar:5.0.3:test
+[INFO] | | \- org.slf4j:slf4j-api:jar:1.7.21:compile
+[INFO] | +- junit:junit:jar:4.12:test
+[INFO] | +- org.assertj:assertj-core:jar:2.5.0:test
+[INFO] | +- org.mockito:mockito-core:jar:1.10.19:test
+[INFO] | | \- org.objenesis:objenesis:jar:2.1:test
+[INFO] | +- org.hamcrest:hamcrest-core:jar:1.3:test
+[INFO] | +- org.hamcrest:hamcrest-library:jar:1.3:test
+[INFO] | +- org.skyscreamer:jsonassert:jar:1.3.0:test
+[INFO] | +- org.springframework:spring-core:jar:4.3.3.RELEASE:compile
+[INFO] | \- org.springframework:spring-test:jar:4.3.3.RELEASE:test
+[INFO] +- commons-lang:commons-lang:jar:2.6:compile
+[INFO] +- commons-net:commons-net:jar:3.3:compile
+[INFO] +- com.jcraft:jsch:jar:0.1.54:compile
+[INFO] +- com.google.code.gson:gson:jar:2.7:compile
+[INFO] +- org.json:json:jar:20090211:compile
+[INFO] +- org.postgresql:postgresql:jar:9.4-1206-jdbc42:compile
+[INFO] +- org.eclipse.persistence:javax.persistence:jar:2.0.0:compile
+[INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:1.4.1.RELEASE:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-aop:jar:1.4.1.RELEASE:compile
+[INFO] | \- org.aspectj:aspectjweaver:jar:1.8.9:compile
+[INFO] +- org.springframework.boot:spring-boot-starter-jdbc:jar:1.4.1.RELEASE:compile
+[INFO] | +- org.apache.tomcat:tomcat-jdbc:jar:8.5.5:compile
+[INFO] | | \- org.apache.tomcat:tomcat-juli:jar:8.5.5:compile
+[INFO] | \- org.springframework:spring-jdbc:jar:4.3.3.RELEASE:compile
+[INFO] +- org.hibernate:hibernate-core:jar:5.0.11.Final:compile
+[INFO] | +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile
+[INFO] | +- org.javassist:javassist:jar:3.20.0-GA:compile
+[INFO] | +- antlr:antlr:jar:2.7.7:compile
+[INFO] | +- org.jboss:jandex:jar:2.0.0.Final:compile
+[INFO] | +- dom4j:dom4j:jar:1.6.1:compile
+[INFO] | | \- xml-apis:xml-apis:jar:1.4.01:compile
+[INFO] | \- org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile
+[INFO] +- org.hibernate:hibernate-entitymanager:jar:5.0.11.Final:compile
+[INFO] +- javax.transaction:javax.transaction-api:jar:1.2:compile
+[INFO] +- org.springframework.data:spring-data-jpa:jar:1.10.3.RELEASE:compile
+[INFO] | +- org.springframework.data:spring-data-commons:jar:1.12.3.RELEASE:compile
+[INFO] | +- org.springframework:spring-orm:jar:4.3.3.RELEASE:compile
+[INFO] | +- org.springframework:spring-tx:jar:4.3.3.RELEASE:compile
+[INFO] | \- org.slf4j:jcl-over-slf4j:jar:1.7.21:compile
+[INFO] \- org.springframework:spring-aspects:jar:4.3.3.RELEASE:compile
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESS
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 8.670 s
+[INFO] Finished at: 2016-11-02T13:59:41-04:00
+[INFO] Final Memory: 26M/178M
+[INFO] ------------------------------------------------------------------------
diff --git a/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/recipes/consumer_creation.rb b/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/recipes/consumer_creation.rb index cd651dd..b6edb82 100644 --- a/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/recipes/consumer_creation.rb +++ b/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/recipes/consumer_creation.rb @@ -1,4 +1,4 @@ -sdc_be_vip = node['SDC_BE_FQDN'] +sdc_be_vip = node['BE_VIP'] if node['disableHttp'] protocol = "https" diff --git a/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/templates/default/dcae-application.properties.erb b/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/templates/default/dcae-application.properties.erb index 6251043..a2a3201 100644 --- a/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/templates/default/dcae-application.properties.erb +++ b/docker/docker_be/chef-solo/cookbooks/Deploy-DCAE/templates/default/dcae-application.properties.erb @@ -31,6 +31,12 @@ compositionConfig.flowTypes={"Syslog":{"entryPointPhaseName":"syslog_map","lastP "SNMP PM Poller":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publilsh"},\ "Discovery and MIB Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ "Nagios docker MSE":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "Discovery Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ + "MIB Poller":{"entryPointPhaseName":"snmp_pm_map","lastPhaseName":"snmp_pm_publish"},\ + "VES Fault SE":{"entryPointPhaseName":"ves_fault_map","lastPhaseName":"ves_fault_publish"},\ + "Docker Supplement":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "Docker Enrich":{"entryPointPhaseName":"docker_map","lastPhaseName":"docker_publish"},\ + "VES Collector":{"entryPointPhaseName":"sam_collector_map","lastPhaseName":"sam_collector_publish"},\ "VES Fault":{"entryPointPhaseName":"ves_fault_map","lastPhaseName":"ves_fault_publish"},\ "VES Heartbeat":{"entryPointPhaseName":"ves_heartbeat_map","lastPhaseName":"ves_heartbeat_publish"},\ "VES Measurement":{"entryPointPhaseName":"ves_measurement_map","lastPhaseName":"ves_measurement_publish"},\ diff --git a/docker/docker_be/startup.sh b/docker/docker_be/startup.sh index 25c367b..a88cd36 100644 --- a/docker/docker_be/startup.sh +++ b/docker/docker_be/startup.sh @@ -1,6 +1,5 @@ #!/bin/sh -#set -x - +set -x # Run chef-solo for configuration cd /var/opt/dcae-be/chef-solo chef-solo -c solo.rb -E ${ENVNAME} --log_level "debug" --logfile "/tmp/Chef-Solo.log" @@ -15,5 +14,5 @@ fi cd /var/lib/jetty /docker-entrypoint.sh & -while true; do sleep 2; done -#exec "$@"; +#while true; do sleep 2; done +exec "$@";
\ No newline at end of file diff --git a/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/files/default/config.json b/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/files/default/config.json index a243dc7..202ee54 100644 --- a/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/files/default/config.json +++ b/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/files/default/config.json @@ -1,6 +1,7 @@ + { "templateInfo": [{ - "name": "Syslog Collector Template", + "name": "Syslog Collector", "flowType": "Syslog Collector", "description": "Syslog Collector", "category": "Template", @@ -8,24 +9,10 @@ "updateIfExist": "false", "composition": [{ "type": "SyslogCollector", - "alias": "Syslog" - }, { - "type": "Existing Topic", - "alias": "eTopic" - }], - "relations": [{ - "fromComponent": "Syslog.SyslogCollector", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "SyslogCollector", - "nodeName": "topic0" - }] + "alias": "" + }] },{ - "name": "Syslog MSEA Template", + "name": "Syslog MSEA", "flowType": "Syslog MSEA", "description": "Syslog MSEA", "category": "Template", @@ -33,175 +20,231 @@ "updateIfExist": "false", "composition": [{ "type": "Map", - "alias": "Map" + "alias": "" }, { "type": "Supplement", - "alias": "Sup" + "alias": "" }, { "type": "Enrich", - "alias": "Enr" + "alias": "" }, { "type": "Alert", - "alias": "Ale" + "alias": "" }], "relations": [{ - "fromComponent": "Sup.Supplement", + "fromComponent": "Supplement", "fromRequirement": "dependency", - "toComponent": "Map.Map", + "toComponent": "Map", "toCapability": "feature" },{ - "fromComponent": "Enr.Enrich", + "fromComponent": "Enrich", "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", + "toComponent": "Supplement", "toCapability": "feature" },{ - "fromComponent": "Ale.Alert", + "fromComponent": "Alert", "fromRequirement": "dependency", - "toComponent": "Enr.Enrich", + "toComponent": "Enrich", "toCapability": "feature" }] - },{ - "name": "Status Poller Collector Template", - "flowType": "Status Poller Collector", - "description": "Status Poller Collector", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "StatusPoller", - "alias": "sPoller" - }, { - "type": "Existing Topic", - "alias": "eTopic0" - }], - "relations": [{ - "fromComponent": "sPoller.StatusPoller", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic0.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "StatusPoller", - "nodeName": "topic0" + }, + + { + "name": "Status Poller MSE", + "flowType": "Status Poller MSE", + "description": "Status Poller MSE", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Map", + "alias": "" + }, { + "type": "Supplement", + "alias": "" + }, { + "type": "Enrich", + "alias": "" + }], + "relations": [{ + "fromComponent": "Supplement", + "fromRequirement": "dependency", + "toComponent": "Map", + "toCapability": "feature" + },{ + "fromComponent": "Enrich", + "fromRequirement": "dependency", + "toComponent": "Supplement", + "toCapability": "feature" }] - }, { - "name": "Status Poller MSE Template", - "flowType": "Status Poller MSE", - "description": "Status Poller MSE", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "Map", - "alias": "Map" - }, { - "type": "Supplement", - "alias": "Sup" }, { - "type": "Enrich", - "alias": "Enr" - }], - "relations": [{ - "fromComponent": "Sup.Supplement", - "fromRequirement": "dependency", - "toComponent": "Map.Map", - "toCapability": "feature" - },{ - "fromComponent": "Enr.Enrich", - "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", - "toCapability": "feature" - }] - }, { - "name": "FOI Collector Template", - "flowType": "FOI Collector", - "description": "FOI Collector", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "FOICollector", - "alias": "fCollector" - }, { - "type": "Existing Feed", - "alias": "eFeed" - }], - "relations": [{ - "fromComponent": "fCollector.FoiSftp", - "fromRequirement": "stream_publish_0", - "toComponent": "eFeed.feed", - "toCapability": "feed" - }], - "nodesToDelete": [ - { + "name": "FOI Collector", + "flowType": "FOI Collector", + "description": "FOI Collector", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ "type": "FOICollector", - "nodeName": "feed0" + "alias": "" }] - }, { - "name": "SNMP MSE Template", - "flowType": "SNMP MSE", - "description": "SNMP MSE", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "Map", - "alias": "Map" - }, { - "type": "Supplement", - "alias": "Sup" + }, { - "type": "Enrich", - "alias": "Enr" - }], - "relations": [{ - "fromComponent": "Sup.Supplement", - "fromRequirement": "dependency", - "toComponent": "Map.Map", - "toCapability": "feature" - },{ - "fromComponent": "Enr.Enrich", - "fromRequirement": "dependency", - "toComponent": "Sup.Supplement", - "toCapability": "feature" - }] - }, { - "name": "Docker Map Template", - "flowType": "Docker Map", - "description": "Docker Map", - "category": "Template", - "subCategory":"Base Monitoring Template", - "updateIfExist": "false", - "composition": [{ - "type": "DockerMap", - "alias": "dMp" - }, { - "type": "Existing Feed", - "alias": "eFeed" - }, { - "type": "Existing Topic", - "alias": "eTopic" - }], - "relations": [{ - "fromComponent": "dMp.DockerMap", - "fromRequirement": "stream_subscribe_0", - "toComponent": "eFeed.feed", - "toCapability": "feed" + "name": "SNMP MSE", + "flowType": "SNMP MSE", + "description": "SNMP MSE", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Map", + "alias": "" + }, { + "type": "Supplement", + "alias": "" + }, { + "type": "Enrich", + "alias": "" + }], + "relations": [{ + "fromComponent": "Supplement", + "fromRequirement": "dependency", + "toComponent": "Map", + "toCapability": "feature" + },{ + "fromComponent": "Enrich", + "fromRequirement": "dependency", + "toComponent": "Supplement", + "toCapability": "feature" + }] }, { - "fromComponent": "dMp.DockerMap", - "fromRequirement": "stream_publish_0", - "toComponent": "eTopic.topic", - "toCapability": "topic" - }], - "nodesToDelete": [ - { - "type": "DockerMap", - "nodeName": "feed0" - }, - { + "name": "Docker Map", + "flowType": "Docker Map", + "description": "Docker Map", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ "type": "DockerMap", - "nodeName": "topic0" + "alias": "" }] - }] + }, + { + "name": "SAM Collector", + "flowType": "SAM Collector", + "description": "SAM Collector", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "SAMCollector1806", + "alias": "" + }] + }, + { + "name": "SNMP PM Poller", + "flowType": "SNMP PM Poller", + "description": "SNMP PM Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "PM Poller", + "alias": "" + }] + }, + { + "name": "Status Poller Collector", + "flowType": "Status Poller Collector", + "description": "Status Poller Collector", + "category": "Template", + "subCategory": "Base Monitoring Template", + "updateIfExist": "false", + "composition": [ + { + "type": "StatusPoller", + "alias": "" + }] + }, + { + "name": "VES Collector", + "flowType": "VES Collector", + "description": "VES Collector", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "VES Collector", + "alias": "" + }] + }, + { + "name": "VES Fault SE", + "flowType": "VES Fault SE", + "description": "VES Fault SE", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Supplement", + "alias": "" + }, { + "type": "Enrich", + "alias": "" + }], + "relations": [{ + "fromComponent": "Enrich", + "fromRequirement": "dependency", + "toComponent": "Supplement", + "toCapability": "feature" + }] + }, + { + "name": "Docker Supplement", + "flowType": "Docker Supplement", + "description": "Docker Supplement", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Docker_Supplement", + "alias": "" + }] + }, + { + "name": "Docker Enrich", + "flowType": "Docker Enrich", + "description": "Docker Enrich", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "DockerEnrich", + "alias": "" + }] + }, + { + "name": "MIB Poller", + "flowType": "MIB Poller", + "description": "MIB Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "MIBPoller", + "alias": "" + }] + }, + { + "name": "Discovery Poller", + "flowType": "Discovery Poller", + "description": "Discovery Poller", + "category": "Template", + "subCategory":"Base Monitoring Template", + "updateIfExist": "false", + "composition": [{ + "type": "Discovery", + "alias": "" + }] + }] }
\ No newline at end of file diff --git a/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/templates/default/environment.json.erb b/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/templates/default/environment.json.erb index a792cf9..d30881c 100644 --- a/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/templates/default/environment.json.erb +++ b/docker/docker_tools/chef-solo/cookbooks/Deploy-DCAE/templates/default/environment.json.erb @@ -3,8 +3,8 @@ "dcaeBePort": "<%= @dcae_be_port %>", "apiPath": "/dcae", "credential" :{ - "editor": "Carlos_Santana", - "username": "cs0008", + "editor": "", + "username": "jh0003", "password": "", "firstName": "", "lastName": "" @@ -0,0 +1,233 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..2b934e8 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE%
\ No newline at end of file |