diff options
author | Sébastien Determe <sebastien.determe@intl.att.com> | 2019-03-29 08:47:17 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2019-03-29 08:47:17 +0000 |
commit | 911167cc45c8d6fdab59674e67a8373e894c2979 (patch) | |
tree | 5e92106f94a49bbae296c7df6d2bbc729f6bcab8 | |
parent | e10910d9070a80e47e81a6cd7c350a627080b6a2 (diff) | |
parent | 937c480aac2d675e70c94908febddb42aefc8dcc (diff) |
Merge "Rework the deploy/undeploy method"
6 files changed, 340 insertions, 18 deletions
diff --git a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java index 300d6066..47b4f9ab 100644 --- a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java +++ b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java @@ -38,6 +38,7 @@ import java.util.Date; import java.util.TimeZone;
import java.util.UUID;
+import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
@@ -259,6 +260,36 @@ public class LoggingUtils { this.mLogger.info(ONAPLogConstants.Markers.INVOKE_SYNC + "{"+ invocationID +"}");
return con;
}
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param builder request builder, for setting headers.
+ * @param sync whether synchronous, nullable.
+ * @return invocation ID to be passed with invocation.
+ */
+ public HttpsURLConnection invokeHttps(final HttpsURLConnection con, String targetEntity, String targetServiceName) {
+ final String invocationID = UUID.randomUUID().toString();
+
+ // Set standard HTTP headers on (southbound request) builder.
+ con.setRequestProperty(ONAPLogConstants.Headers.REQUEST_ID,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)));
+ con.setRequestProperty(ONAPLogConstants.Headers.INVOCATION_ID,
+ invocationID);
+ con.setRequestProperty(ONAPLogConstants.Headers.PARTNER_NAME,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.PARTNER_NAME)));
+
+ invokeContext(targetEntity, targetServiceName, invocationID);
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+ this.mLogger.info(ONAPLogConstants.Markers.INVOKE);
+ this.mLogger.info(ONAPLogConstants.Markers.INVOKE_SYNC + "{"+ invocationID +"}");
+ return con;
+ }
+
public void invokeReturn() {
// Add the Invoke-return marker and clear the needed MDC
this.mLogger.info(ONAPLogConstants.Markers.INVOKE_RETURN);
diff --git a/src/main/java/org/onap/clamp/exception/OperationException.java b/src/main/java/org/onap/clamp/exception/OperationException.java new file mode 100644 index 00000000..0233b092 --- /dev/null +++ b/src/main/java/org/onap/clamp/exception/OperationException.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.exception; + +/** + * New exception to CldsUser errors. + * + */ +public class OperationException extends RuntimeException { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 2788967876393519620L; + + /** + * This constructor can be used to create a new CldsUsersException. + * + * @param message + * A string message detailing the problem + * @param e + * The exception sent by the code + */ + public OperationException(String message, Throwable e) { + super(message, e); + } + + /** + * This constructor can be used to create a new CldsUsersException. Use this + * constructor only if you are creating a new exception stack, not if an + * exception was already raised by another code. + * + * @param message + * A string message detailing the problem + */ + public OperationException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/loop/Loop.java b/src/main/java/org/onap/clamp/loop/Loop.java index 64e0108e..6dc73e98 100644 --- a/src/main/java/org/onap/clamp/loop/Loop.java +++ b/src/main/java/org/onap/clamp/loop/Loop.java @@ -139,7 +139,7 @@ public class Loop implements Serializable { return dcaeDeploymentId; } - void setDcaeDeploymentId(String dcaeDeploymentId) { + public void setDcaeDeploymentId(String dcaeDeploymentId) { this.dcaeDeploymentId = dcaeDeploymentId; } @@ -147,7 +147,7 @@ public class Loop implements Serializable { return dcaeDeploymentStatusUrl; } - void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { + public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl; } @@ -167,11 +167,11 @@ public class Loop implements Serializable { this.blueprint = blueprint; } - LoopState getLastComputedState() { + public LoopState getLastComputedState() { return lastComputedState; } - void setLastComputedState(LoopState lastComputedState) { + public void setLastComputedState(LoopState lastComputedState) { this.lastComputedState = lastComputedState; } @@ -222,7 +222,7 @@ public class Loop implements Serializable { log.setLoop(this); } - String getDcaeBlueprintId() { + public String getDcaeBlueprintId() { return dcaeBlueprintId; } @@ -230,7 +230,7 @@ public class Loop implements Serializable { this.dcaeBlueprintId = dcaeBlueprintId; } - JsonObject getModelPropertiesJson() { + public JsonObject getModelPropertiesJson() { return modelPropertiesJson; } diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java index b4995734..34e1b4be 100644 --- a/src/main/java/org/onap/clamp/loop/LoopService.java +++ b/src/main/java/org/onap/clamp/loop/LoopService.java @@ -54,7 +54,7 @@ public class LoopService { this.operationalPolicyService = operationalPolicyService; } - Loop saveOrUpdateLoop(Loop loop) { + public Loop saveOrUpdateLoop(Loop loop) { return loopsRepository.save(loop); } @@ -62,7 +62,7 @@ public class LoopService { return loopsRepository.getAllLoopNames(); } - Loop getLoop(String loopName) { + public Loop getLoop(String loopName) { return loopsRepository .findById(loopName) .orElse(null); diff --git a/src/main/java/org/onap/clamp/operation/LoopOperation.java b/src/main/java/org/onap/clamp/operation/LoopOperation.java new file mode 100644 index 00000000..af615af1 --- /dev/null +++ b/src/main/java/org/onap/clamp/operation/LoopOperation.java @@ -0,0 +1,212 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +package org.onap.clamp.operation; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.camel.Exchange; +import org.onap.clamp.clds.client.DcaeDispatcherServices; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.clds.util.ONAPLogConstants; +import org.onap.clamp.exception.OperationException; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.LoopService; +import org.onap.clamp.loop.LoopState; +import org.slf4j.event.Level; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +/** + * Closed loop operations + */ +@Component +public class LoopOperation { + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger(); + private final DcaeDispatcherServices dcaeDispatcherServices; + private final LoopService loopService; + private LoggingUtils util = new LoggingUtils(logger); + + @Autowired + private HttpServletRequest request; + + @Autowired + public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices) { + this.loopService = loopService; + this.dcaeDispatcherServices = dcaeDispatcherServices; + } + + /** + * Deploy the closed loop. + * + * @param loopName the loop name + * @return the updated loop + * @throws Exceptions during the operation + */ + public Loop deployLoop(Exchange camelExchange, String loopName) throws OperationException { + util.entering(request, "CldsService: Deploy model"); + Date startTime = new Date(); + Loop loop = loopService.getLoop(loopName); + + if (loop == null) { + String msg = "Deploy loop exception: Not able to find closed loop:" + loopName; + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // verify the current closed loop state + if (loop.getLastComputedState() != LoopState.SUBMITTED) { + String msg = "Deploy loop exception: This closed loop is in state:" + loop.getLastComputedState() + + ". It could be deployed only when it is in SUBMITTED state."; + util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // Set the deploymentId if not present yet + String deploymentId = ""; + // If model is already deployed then pass same deployment id + if (loop.getDcaeDeploymentId() != null && !loop.getDcaeDeploymentId().isEmpty()) { + deploymentId = loop.getDcaeDeploymentId(); + } else { + loop.setDcaeDeploymentId(deploymentId = "closedLoop_" + loopName + "_deploymentId"); + } + + Yaml yaml = new Yaml(); + Map<String, Object> yamlMap = yaml.load(loop.getBlueprint()); + JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject(); + + loop.setDcaeDeploymentStatusUrl(dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint)); + loop.setLastComputedState(LoopState.DEPLOYED); + // save the updated loop + loopService.saveOrUpdateLoop (loop); + + // audit log + LoggingUtils.setTimeContext(startTime, new Date()); + auditLogger.info("Deploy model completed"); + util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); + return loop; + } + + /** + * Un deploy closed loop. + * + * @param loopName the loop name + * @return the updated loop + */ + public Loop unDeployLoop(String loopName) throws OperationException { + util.entering(request, "LoopOperation: Undeploy the closed loop"); + Date startTime = new Date(); + Loop loop = loopService.getLoop(loopName); + + if (loop == null) { + String msg = "Undeploy loop exception: Not able to find closed loop:" + loopName; + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + // verify the current closed loop state + if (loop.getLastComputedState() != LoopState.DEPLOYED) { + String msg = "Unploy loop exception: This closed loop is in state:" + loop.getLastComputedState() + + ". It could be undeployed only when it is in DEPLOYED state."; + util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, + ONAPLogConstants.ResponseStatus.ERROR); + throw new OperationException(msg); + } + + loop.setDcaeDeploymentStatusUrl( + dcaeDispatcherServices.deleteExistingDeployment(loop.getDcaeDeploymentId(), loop.getDcaeBlueprintId())); + + // clean the deployment ID + loop.setDcaeDeploymentId(null); + loop.setLastComputedState(LoopState.SUBMITTED); + + // save the updated loop + loopService.saveOrUpdateLoop (loop); + + // audit log + LoggingUtils.setTimeContext(startTime, new Date()); + auditLogger.info("Undeploy model completed"); + util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED); + return loop; + } + + private JsonElement wrapSnakeObject(Object o) { + //NULL => JsonNull + if (o == null) + return JsonNull.INSTANCE; + + // Collection => JsonArray + if (o instanceof Collection) { + JsonArray array = new JsonArray(); + for (Object childObj : (Collection<?>)o) + array.add(wrapSnakeObject(childObj)); + return array; + } + + // Array => JsonArray + if (o.getClass().isArray()) { + JsonArray array = new JsonArray(); + + int length = Array.getLength(array); + for (int i=0; i<length; i++) + array.add(wrapSnakeObject(Array.get(array, i))); + return array; + } + + // Map => JsonObject + if (o instanceof Map) { + Map<?, ?> map = (Map<?, ?>)o; + + JsonObject jsonObject = new JsonObject(); + for (final Map.Entry<?, ?> entry : map.entrySet()) { + final String name = String.valueOf(entry.getKey()); + final Object value = entry.getValue(); + jsonObject.add(name, wrapSnakeObject(value)); + } + return jsonObject; + } + + // otherwise take it as a string + return new JsonPrimitive(String.valueOf(o)); + } +} diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml index d4872ef4..c5828b28 100644 --- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -10,7 +10,6 @@ </get> <get uri="/v2/loop/{loopName}" outType="org.onap.clamp.loop.Loop" - produces="application/json"> <route> <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> @@ -19,19 +18,22 @@ </get> <get uri="/v2/loop/svgRepresentation/{loopName}" outType="java.lang.String" - produces="application/xml"> - <to - uri="bean:org.onap.clamp.loop.LoopController?method=getSVGRepresentation(${header.loopName})" /> + <route> + <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> + <to uri="bean:org.onap.clamp.loop.LoopController?method=getSVGRepresentation(${header.loopName})" /> + </route> </get> <post uri="/v2/loop/updateGlobalProperties/{loopName}" - type="com.google.gson.JsonObject" - consumes="application/json" - outType="org.onap.clamp.loop.Loop" - produces="application/json"> - <to - uri="bean:org.onap.clamp.loop.LoopController?method=updateGlobalPropertiesJson(${header.loopName},${body})" /> + type="com.google.gson.JsonObject" + consumes="application/json" + outType="org.onap.clamp.loop.Loop" + produces="application/json"> + <route> + <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="bean:org.onap.clamp.loop.LoopController?method=updateGlobalPropertiesJson(${header.loopName},${body})" /> + </route> </post> <post uri="/v2/loop/updateOperationalPolicies/{loopName}" type="com.google.gson.JsonArray" @@ -53,6 +55,22 @@ <to uri="bean:org.onap.clamp.loop.LoopController?method=updateMicroservicePolicy(${header.loopName},${body})" /> </route> </post> + <put uri="/v2/loop/deployLoop/{loopName}" + outType="org.onap.clamp.loop.Loop" + produces="application/json"> + <route> + <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="bean:org.onap.clamp.operation.LoopOperation?method=deployLoop(*,${header.loopName})" /> + </route> + </put> + <put uri="/v2/loop/undeployLoop/{loopName}" + outType="org.onap.clamp.loop.Loop" + produces="application/json"> + <route> + <to uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="bean:org.onap.clamp.operation.LoopOperation?method=unDeployLoop(${header.loopName})" /> + </route> + </put> </rest> </rests> |