From 3121b5bee2e70b1f753f9988344d41f3132edf69 Mon Sep 17 00:00:00 2001 From: Vidyashree-Huawei Date: Wed, 4 Mar 2020 19:22:08 +0530 Subject: CLAMP-CDS integration to display all CDS actions for blueprint in CL CLAMP-CDS integration to display all CDS actions for blueprint in CL Change-Id: I18b972b8952e5de9ac8e39d6c9cc4ecba0ec9b02 Issue-ID: CLAMP-491 Signed-off-by: Vidyashree-Huawei --- .../org/onap/clamp/clds/client/CdsServices.java | 171 +++++++++++++++++++++ .../clds/model/cds/CdsBpWorkFlowListResponse.java | 67 ++++++++ .../clamp/loop/service/CsarServiceInstaller.java | 58 ++++++- .../operational/LegacyOperationalPolicy.java | 55 ++++++- .../policy/operational/OperationalPolicy.java | 3 +- .../OperationalPolicyRepresentationBuilder.java | 69 ++++++++- 6 files changed, 414 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/onap/clamp/clds/client/CdsServices.java create mode 100644 src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java (limited to 'src/main/java') diff --git a/src/main/java/org/onap/clamp/clds/client/CdsServices.java b/src/main/java/org/onap/clamp/clds/client/CdsServices.java new file mode 100644 index 00000000..fe1937ab --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/client/CdsServices.java @@ -0,0 +1,171 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * ================================================================================ + * + */ + +package org.onap.clamp.clds.client; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.util.Date; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.builder.ExchangeBuilder; +import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.LoggingUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * This class implements the communication with CDS for the service inventory. + */ +@Component +public class CdsServices { + + @Autowired + CamelContext camelContext; + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsServices.class); + + /** + * Constructor. + */ + @Autowired + public CdsServices() { + } + + + /** + * Query CDS to get blueprint's workflow list. + * + * @param blueprintName CDS blueprint name + * @param blueprintVersion CDS blueprint version + * @return CdsBpWorkFlowListResponse CDS blueprint's workflow list + */ + public CdsBpWorkFlowListResponse getBlueprintWorkflowList(String blueprintName, String blueprintVersion) { + LoggingUtils.setTargetContext("CDS", "getBlueprintWorkflowList"); + + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext) + .withProperty("blueprintName", blueprintName).withProperty("blueprintVersion", blueprintVersion) + .build(); + + Exchange exchangeResponse = camelContext.createProducerTemplate() + .send("direct:get-blueprint-workflow-list", myCamelExchange); + + if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) { + String cdsResponse = (String) exchangeResponse.getIn().getBody(); + logger.info("getBlueprintWorkflowList, response from CDS:" + cdsResponse); + LoggingUtils.setResponseContext("0", "Get Blueprint workflow list", this.getClass().getName()); + Date startTime = new Date(); + LoggingUtils.setTimeContext(startTime, new Date()); + return JsonUtils.GSON_JPA_MODEL.fromJson(cdsResponse, CdsBpWorkFlowListResponse.class); + } + return null; + } + + /** + * Query CDS to get input properties of workflow. + * + * @param blueprintName CDS blueprint name + * @param blueprintVersion CDS blueprint name + * @param workflow CDS blueprint's workflow + * @return input properties in json format + */ + public JsonObject getWorkflowInputProperties(String blueprintName, String blueprintVersion, + String workflow) { + LoggingUtils.setTargetContext("CDS", "getWorkflowInputProperties"); + + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext) + .withBody(getCdsPayloadForWorkFlow(blueprintName, blueprintVersion, workflow)) + .build(); + + Exchange exchangeResponse = camelContext.createProducerTemplate() + .send("direct:get-blueprint-workflow-input-properties", myCamelExchange); + + if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) { + String cdsResponse = (String) exchangeResponse.getIn().getBody(); + logger.info("getWorkflowInputProperties, response from CDS:" + cdsResponse); + LoggingUtils.setResponseContext("0", "Get Blueprint workflow input properties", this.getClass().getName()); + Date startTime = new Date(); + LoggingUtils.setTimeContext(startTime, new Date()); + return parseCdsResponse(cdsResponse); + } + return null; + } + + private JsonObject parseCdsResponse(String response) { + JsonObject root = JsonParser.parseString(response).getAsJsonObject(); + JsonObject inputs = root.getAsJsonObject("workFlowData").getAsJsonObject("inputs"); + JsonObject dataTypes = root.getAsJsonObject("dataTypes"); + + JsonObject workFlowProperties = new JsonObject(); + workFlowProperties.add("inputs", getInputProperties(inputs, dataTypes)); + return workFlowProperties; + } + + private JsonObject getInputProperties(JsonObject inputs, JsonObject dataTypes) { + JsonObject inputObject = new JsonObject(); + for (Map.Entry entry : inputs.entrySet()) { + String key = entry.getKey(); + JsonObject inputProperty = inputs.getAsJsonObject(key); + String type = inputProperty.get("type").getAsString(); + if (isComplexType(type, dataTypes)) { + inputObject.add(key, handleComplexType(type, dataTypes)); + } else { + inputObject.addProperty(key, ""); + } + } + return inputObject; + } + + private JsonObject handleComplexType(String key, JsonObject dataTypes) { + JsonObject properties = dataTypes.get(key).getAsJsonObject().get("properties").getAsJsonObject(); + return getInputProperties(properties, dataTypes); + } + + private boolean isComplexType(String type, JsonObject dataTypes) { + return dataTypes.get(type) != null; + } + + /** + * Creates payload to query CDS to get workflow input properties. + * + * @param blueprintName CDS blueprint name + * @param version CDS blueprint version + * @param workflow CDS blueprint workflow + * @return returns payload in json format + */ + public String getCdsPayloadForWorkFlow(String blueprintName, String version, String workflow) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("blueprintName", blueprintName); + jsonObject.addProperty("version", version); + jsonObject.addProperty("returnContent", "json"); + jsonObject.addProperty("workflowName", workflow); + jsonObject.addProperty("specType", "TOSCA"); + return jsonObject.toString(); + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java b/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java new file mode 100644 index 00000000..66025c47 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * ================================================================================ + * + */ + +package org.onap.clamp.clds.model.cds; + +import com.google.gson.annotations.Expose; + +import java.util.LinkedList; +import java.util.List; + +/** + * This class maps the CDS response to a pojo. + */ +public class CdsBpWorkFlowListResponse { + + @Expose + private String blueprintName; + + @Expose + private String version; + + @Expose + private List workflows = new LinkedList(); + + public String getBlueprintName() { + return blueprintName; + } + + public void setBlueprintName(String blueprintName) { + this.blueprintName = blueprintName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getWorkflows() { + return workflows; + } + + public void setWorkflows(List workflows) { + this.workflows = workflows; + } +} diff --git a/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java index 277fe004..889125fe 100644 --- a/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java +++ b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2020 AT&T Intellectual Property. All rights * reserved. + * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +30,9 @@ import com.google.gson.JsonObject; import java.util.Map.Entry; +import org.onap.clamp.clds.client.CdsServices; import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse; import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; import org.onap.clamp.clds.util.JsonUtils; import org.onap.sdc.tosca.parser.api.IEntityDetails; @@ -53,9 +56,12 @@ public class CsarServiceInstaller { @Autowired ServiceRepository serviceRepository; + @Autowired + CdsServices cdsServices; + /** * Install the Service from the csar. - * + * * @param csar The Csar Handler * @return The service object */ @@ -77,7 +83,7 @@ public class CsarServiceInstaller { return modelService; } - private static JsonObject createServicePropertiesByType(CsarHandler csar) { + private JsonObject createServicePropertiesByType(CsarHandler csar) { JsonObject resourcesProp = new JsonObject(); // Iterate on all types defined in the tosca lib for (SdcTypes type : SdcTypes.values()) { @@ -86,6 +92,13 @@ public class CsarServiceInstaller { for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) { resourcesPropByType.add(nodeTemplate.getName(), JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties())); + // get cds artifact information and save in resources Prop + if (SdcTypes.PNF == type || SdcTypes.VF == type) { + JsonObject controllerProperties = createCdsArtifactProperties(nodeTemplate); + if (controllerProperties != null) { + resourcesPropByType.getAsJsonObject(nodeTemplate.getName()).add("controllerProperties", controllerProperties); + } + } } resourcesProp.add(type.getValue(), resourcesPropByType); } @@ -114,7 +127,7 @@ public class CsarServiceInstaller { /** * Verify whether Service in Csar is deployed. - * + * * @param csar The Csar Handler * @return The flag indicating whether Service is deployed * @throws SdcArtifactInstallerException The SdcArtifactInstallerException @@ -127,4 +140,43 @@ public class CsarServiceInstaller { return alreadyInstalled; } + + /** + * Retrive CDS artifacts information from node template and save in resource object. + * + * @param nodeTemplate node template + * @return Returns CDS artifacts information + */ + private JsonObject createCdsArtifactProperties(NodeTemplate nodeTemplate) { + Object artifactName = nodeTemplate.getPropertyValue("sdnc_model_name"); + Object artifactVersion = nodeTemplate.getPropertyValue("sdnc_model_version"); + if (artifactName != null && artifactVersion != null) { + CdsBpWorkFlowListResponse response = queryCdsToGetWorkFlowList(artifactName.toString(), artifactVersion.toString()); + if (response == null) { + return null; + } + + JsonObject workFlowProps = new JsonObject(); + for (String workFlow : response.getWorkflows()) { + JsonObject inputs = queryCdsToGetWorkFlowInputProperties(response.getBlueprintName(), + response.getVersion(), workFlow); + workFlowProps.add(workFlow, inputs); + } + + JsonObject controllerProperties = new JsonObject(); + controllerProperties.addProperty("sdnc_model_name", artifactName.toString()); + controllerProperties.addProperty("sdnc_model_version", artifactVersion.toString()); + controllerProperties.add("workflows", workFlowProps); + return controllerProperties; + } + return null; + } + + private CdsBpWorkFlowListResponse queryCdsToGetWorkFlowList(String artifactName, String artifactVersion) { + return cdsServices.getBlueprintWorkflowList(artifactName, artifactVersion); + } + + private JsonObject queryCdsToGetWorkFlowInputProperties(String artifactName, String artifactVersion, String workFlow) { + return cdsServices.getWorkflowInputProperties(artifactName, artifactVersion, workFlow); + } } diff --git a/src/main/java/org/onap/clamp/policy/operational/LegacyOperationalPolicy.java b/src/main/java/org/onap/clamp/policy/operational/LegacyOperationalPolicy.java index ff7777f7..033f2ceb 100644 --- a/src/main/java/org/onap/clamp/policy/operational/LegacyOperationalPolicy.java +++ b/src/main/java/org/onap/clamp/policy/operational/LegacyOperationalPolicy.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights * reserved. + * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +47,11 @@ import org.yaml.snakeyaml.Yaml; */ public class LegacyOperationalPolicy { + private static final String ACTOR = "actor"; + private static final String RECIPE = "recipe"; + private static final String POLICIES = "policies"; + private static final String PAYLOAD = "payload"; + private LegacyOperationalPolicy() { } @@ -79,7 +85,7 @@ public class LegacyOperationalPolicy { /** * This method rework the payload attribute (yaml) that is normally wrapped in a * string when coming from the UI. - * + * * @param policyJson The operational policy json config * @return The same object reference but modified */ @@ -150,7 +156,7 @@ public class LegacyOperationalPolicy { /** * This method transforms the configuration json to a Yaml format. - * + * * @param operationalPolicyJsonElement The operational policy json config * @return The Yaml as string */ @@ -162,13 +168,13 @@ public class LegacyOperationalPolicy { // Policy can't support { } in the yaml options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); return (new Yaml(options)).dump(createMap(fulfillPoliciesTreeField( - removeAllQuotes(reworkPayloadAttributes(operationalPolicyJsonElement.getAsJsonObject().deepCopy()))))); + removeAllQuotes(reworkActorAttributes(operationalPolicyJsonElement.getAsJsonObject().deepCopy()))))); } /** * This method load mandatory field in the operational policy configuration * JSON. - * + * * @param configurationsJson The operational policy JSON * @param loop The parent loop object */ @@ -182,4 +188,45 @@ public class LegacyOperationalPolicy { configurationsJson.add("operational_policy", controlLoop); } } + + /** + * This method rework on the actor/recipe and payload attribute. + * + * @param policyJson The operational policy json config + * @return The same object reference but modified + */ + public static JsonElement reworkActorAttributes(JsonElement policyJson) { + for (JsonElement policy : policyJson.getAsJsonObject().get(POLICIES).getAsJsonArray()) { + JsonObject actor = policy.getAsJsonObject().get(ACTOR).getAsJsonObject(); + policy.getAsJsonObject().remove(ACTOR); + String actorStr = actor.getAsJsonObject().get(ACTOR).getAsString(); + policy.getAsJsonObject().addProperty(ACTOR, actorStr); + policy.getAsJsonObject().addProperty(RECIPE, getRecipe(actor)); + + if ("CDS".equalsIgnoreCase(actorStr)) { + addPayloadAttributes(actor.getAsJsonObject(ACTOR).getAsJsonObject(RECIPE), policy); + } else { + addPayloadAttributes(actor, policy); + } + } + return policyJson; + } + + private static void addPayloadAttributes(JsonObject jsonObject, + JsonElement policy) { + JsonElement payloadElem = jsonObject.getAsJsonObject().get(PAYLOAD); + String payloadString = payloadElem != null ? payloadElem.getAsString() : ""; + if (!payloadString.isEmpty()) { + Map testMap = new Yaml().load(payloadString); + String json = new GsonBuilder().create().toJson(testMap); + policy.getAsJsonObject().add(PAYLOAD, + new GsonBuilder().create().fromJson(json, JsonElement.class)); + } else { + policy.getAsJsonObject().addProperty(PAYLOAD, ""); + } + } + + private static String getRecipe(JsonObject actor) { + return actor.getAsJsonObject().get("type").getAsString(); + } } diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java index aab30bfb..7cf06dcf 100644 --- a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights * reserved. + * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -222,7 +223,7 @@ public class OperationalPolicy extends Policy implements Serializable { metadata.addProperty("policy-id", this.name); operationalPolicyDetails.add("properties", LegacyOperationalPolicy - .reworkPayloadAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy())); + .reworkActorAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy())); DumperOptions options = new DumperOptions(); options.setIndent(2); diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java index 1d0d9908..244f4c27 100644 --- a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights * reserved. + * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +43,7 @@ public class OperationalPolicyRepresentationBuilder { * used by ui for rendering. It uses the model (VF and VFModule) defined in the * loop object to do so, so it's dynamic. It also uses the operational policy * schema template defined in the resource folder. - * + * * @param modelJson The loop model json * @return The json representation * @throws JsonSyntaxException If the schema template cannot be parsed @@ -58,6 +59,22 @@ public class OperationalPolicyRepresentationBuilder { .get("operational_policy").getAsJsonObject().get("properties").getAsJsonObject().get("policies") .getAsJsonObject().get("items").getAsJsonObject().get("properties").getAsJsonObject().get("target") .getAsJsonObject().get("anyOf").getAsJsonArray().addAll(createAnyOfArray(modelJson)); + + // update CDS recipe and payload information to schema + JsonArray actors = jsonSchema.get("schema").getAsJsonObject().get("items").getAsJsonObject().get("properties") + .getAsJsonObject().get("configurationsJson").getAsJsonObject().get("properties").getAsJsonObject() + .get("operational_policy").getAsJsonObject().get("properties").getAsJsonObject().get("policies") + .getAsJsonObject().get("items").getAsJsonObject().get("properties").getAsJsonObject().get("actor") + .getAsJsonObject().get("anyOf").getAsJsonArray(); + + for (JsonElement actor : actors) { + if ("CDS".equalsIgnoreCase(actor.getAsJsonObject().get("title").getAsString())) { + actor.getAsJsonObject().get("properties").getAsJsonObject().get("type").getAsJsonObject() + .get("anyOf").getAsJsonArray() + .addAll(createAnyOfArrayForCdsRecipe(modelJson.getResourceDetails())); + } + } + return jsonSchema; } @@ -143,4 +160,54 @@ public class OperationalPolicyRepresentationBuilder { targetOneOfStructure.addAll(createVfModuleSchema(modelJson)); return targetOneOfStructure; } + + private static JsonArray createAnyOfArrayForCdsRecipe(JsonObject resourceDetails) { + JsonArray anyOfStructure = new JsonArray(); + anyOfStructure.addAll(createAnyOfCdsRecipe(resourceDetails.getAsJsonObject("VF"))); + anyOfStructure.addAll(createAnyOfCdsRecipe(resourceDetails.getAsJsonObject("PNF"))); + return anyOfStructure; + } + + private static JsonArray createAnyOfCdsRecipe(JsonObject jsonObject) { + JsonArray schemaArray = new JsonArray(); + for (Entry entry : jsonObject.entrySet()) { + JsonObject controllerProperties = entry.getValue().getAsJsonObject() + .getAsJsonObject("controllerProperties"); + + if (controllerProperties != null) { + JsonObject workflows = controllerProperties.getAsJsonObject("workflows"); + for (Entry workflowsEntry : workflows.entrySet()) { + JsonObject obj = new JsonObject(); + obj.addProperty("title", workflowsEntry.getKey()); + obj.add("properties", createPayloadProperty(workflowsEntry.getValue().getAsJsonObject(), + controllerProperties)); + schemaArray.add(obj); + } + + } + } + return schemaArray; + } + + private static JsonObject createPayloadProperty(JsonObject workFlow, JsonObject controllerProperties) { + JsonObject type = new JsonObject(); + type.addProperty("title", "Payload (YAML)"); + type.addProperty("type", "string"); + type.addProperty("default", createDefaultStringForPayload(workFlow, controllerProperties)); + type.addProperty("format", "textarea"); + JsonObject properties = new JsonObject(); + properties.add("type", type); + return properties; + } + + private static String createDefaultStringForPayload(JsonObject workFlow, JsonObject controllerProperties) { + String artifactName = controllerProperties.get("sdnc_model_name").toString(); + String artifactVersion = controllerProperties.get("sdnc_model_version").toString(); + String data = workFlow.getAsJsonObject("inputs").toString(); + StringBuilder builder = new StringBuilder("'").append("artifact_name : ").append(artifactName).append("\n") + .append("artifact_version : ").append(artifactVersion).append("\n") + .append("mode : async").append("\n") + .append("data : ").append("'").append("\\").append("'").append(data).append("\\").append("'").append("'"); + return builder.toString(); + } } -- cgit 1.2.3-korg