aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopOperation.java160
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopService.java4
-rw-r--r--src/main/java/org/onap/clamp/loop/log/LoopLogService.java4
-rw-r--r--src/main/resources/clds/camel/rest/clamp-api-v2.xml89
-rw-r--r--src/main/resources/clds/camel/routes/flexible-flow.xml14
-rw-r--r--src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java43
6 files changed, 132 insertions, 182 deletions
diff --git a/src/main/java/org/onap/clamp/loop/LoopOperation.java b/src/main/java/org/onap/clamp/loop/LoopOperation.java
index 5b55ab0de..d9ea24871 100644
--- a/src/main/java/org/onap/clamp/loop/LoopOperation.java
+++ b/src/main/java/org/onap/clamp/loop/LoopOperation.java
@@ -31,7 +31,6 @@ import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
-import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Date;
@@ -213,163 +212,4 @@ public class LoopOperation {
return new JsonPrimitive(String.valueOf(o));
}
- /**
- * Submit the Ms policies.
- *
- * @param loopName
- * the loop name
- * @return the updated loop
- * @throws IOException
- * IO exception
- * @throws Exceptions
- * during the operation
- */
- public Loop submitMsPolicies(String loopName) throws OperationException, IOException {
- util.entering(request, "LoopOperation: delete microservice policies");
- Date startTime = new Date();
- Loop loop = loopService.getLoop(loopName);
-
- if (loop == null) {
- String msg = "Submit MS policies 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 && loop.getLastComputedState() != LoopState.DESIGN) {
- String msg = "Submit MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
- + ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
- throw new OperationException(msg);
- }
-
- // Establish the api call to Policy to create the ms services
- // policyOp.createMsPolicy(loop.getMicroServicePolicies());
-
- // audit log
- LoggingUtils.setTimeContext(startTime, new Date());
- auditLogger.info("Deletion of MS policies completed");
- util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
- }
-
- /**
- * Delete the Ms policies.
- *
- * @param loopName
- * the loop name
- * @return the updated loop
- * @throws IOException
- * IO exception
- * @throws Exceptions
- * during the operation
- */
- public Loop deleteMsPolicies(Exchange camelExchange, String loopName) throws OperationException, IOException {
- util.entering(request, "LoopOperation: delete microservice policies");
- Date startTime = new Date();
- Loop loop = loopService.getLoop(loopName);
-
- if (loop == null) {
- String msg = "Delete MS policies 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 = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
- + ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
- throw new OperationException(msg);
- }
-
- // Establish the api call to Policy to create the ms services
- // policyOp.deleteMsPolicy(loop.getMicroServicePolicies());
-
- // audit log
- LoggingUtils.setTimeContext(startTime, new Date());
- auditLogger.info("Deletion of MS policies completed");
- util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
- }
-
- /**
- * Delete the operational policy.
- *
- * @param loopName
- * the loop name
- * @return the updated loop
- * @throws Exceptions
- * during the operation
- */
- public Loop deleteOpPolicy(Exchange camelExchange, String loopName) throws OperationException {
- util.entering(request, "LoopOperation: delete guard policy");
- Date startTime = new Date();
- Loop loop = loopService.getLoop(loopName);
-
- if (loop == null) {
- String msg = "Delete guard policy 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 = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
- + ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
- throw new OperationException(msg);
- }
-
- // Establish the api call to Policy to delete operational policy
- // client.deleteOpPolicy();
-
- // audit log
- LoggingUtils.setTimeContext(startTime, new Date());
- auditLogger.info("Deletion of Guard policy completed");
- util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
- }
-
- /**
- * Delete the Guard policy.
- *
- * @param loopName
- * the loop name
- * @return the updated loop
- * @throws Exceptions
- * during the operation
- */
- public Loop deleteGuardPolicy(Exchange camelExchange, String loopName) throws OperationException {
- util.entering(request, "LoopOperation: delete operational policy");
- Date startTime = new Date();
- Loop loop = loopService.getLoop(loopName);
-
- if (loop == null) {
- String msg = "Delete operational policy 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 = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
- + ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
- throw new OperationException(msg);
- }
-
- // Establish the api call to Policy to delete Guard policy
- // client.deleteOpPolicy();
-
- // audit log
- LoggingUtils.setTimeContext(startTime, new Date());
- auditLogger.info("Deletion of operational policy completed");
- util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
- }
}
diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java
index 8d61b877b..4c1392253 100644
--- a/src/main/java/org/onap/clamp/loop/LoopService.java
+++ b/src/main/java/org/onap/clamp/loop/LoopService.java
@@ -67,6 +67,10 @@ public class LoopService {
return loopsRepository.findById(loopName).orElse(null);
}
+ public void deleteLoop(String loopName) {
+ loopsRepository.deleteById(loopName);
+ }
+
Loop updateAndSaveOperationalPolicies(String loopName, List<OperationalPolicy> newOperationalPolicies) {
Loop loop = findClosedLoopByName(loopName);
Set<OperationalPolicy> newPolicies = operationalPolicyService.updatePolicies(loop, newOperationalPolicies);
diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLogService.java b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java
index b593b41ed..b02bc11c4 100644
--- a/src/main/java/org/onap/clamp/loop/log/LoopLogService.java
+++ b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java
@@ -40,4 +40,8 @@ public class LoopLogService {
public void addLog(String message, String logType, Loop loop) {
repository.save(new LoopLog(message, LogType.valueOf(logType), loop));
}
+
+ public boolean isExisting(Long logId) {
+ return repository.existsById(logId);
+ }
}
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 8a39f1358..ffa4719f0 100644
--- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml
+++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
@@ -97,14 +97,14 @@
</put>
<put uri="/v2/loop/submit/{loopName}">
<route>
- <setBody>
- <simple>${header.loopName}</simple>
- </setBody>
<log
loggingLevel="INFO"
- message="Receive SUBMIT request for loop: ${body}" />
+ message="Receive SUBMIT request for loop: ${header.loopName}" />
<to
uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" />
+ <setBody>
+ <simple>${header.loopName}</simple>
+ </setBody>
<to uri="direct:load-loop" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Receive SUBMIT request','INFO',${header.LoopObject})" />
@@ -120,12 +120,12 @@
<log
loggingLevel="INFO"
message="Processing Micro Service Policy: ${header.microServicePolicy.getName()}" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">false</simple>
</setHeader>
<to uri="direct:delete-micro-service-policy" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">true</simple>
</setHeader>
<to uri="direct:create-micro-service-policy" />
@@ -143,12 +143,12 @@
<log
loggingLevel="INFO"
message="Processing Operational Policy: ${header.operationalPolicy.getName()}" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">false</simple>
</setHeader>
<to uri="direct:delete-operational-policy" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">true</simple>
</setHeader>
<to uri="direct:create-operational-policy" />
@@ -165,18 +165,18 @@
loggingLevel="INFO"
message="Processing Guard Policy: ${header.guardPolicy.getKey()}" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">false</simple>
</setHeader>
<to uri="direct:delete-guard-policy" />
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">true</simple>
</setHeader>
<to uri="direct:create-guard-policy" />
</split>
</split>
- <setHeader headerName="HttpQueryExceptionFlag">
+ <setHeader headerName="RaiseHttpExceptionFlag">
<simple resultType="java.lang.Boolean">true</simple>
</setHeader>
<to uri="direct:create-pdp-group-policy" />
@@ -190,14 +190,73 @@
</put>
<put uri="/v2/loop/delete/{loopName}">
<route>
+ <log
+ loggingLevel="INFO"
+ message="Receive DELETE request for loop: ${header.loopName}" />
<to
uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" />
+ <setBody>
+ <simple>${header.loopName}</simple>
+ </setBody>
+ <to uri="direct:load-loop" />
<to
- uri="bean:org.onap.clamp.operation.LoopOperation?method=deleteMsPolicies(${header.loopName})" />
- <to
- uri="bean:org.onap.clamp.operation.LoopOperation?method=deleteOpPolicy(${header.loopName})" />
+ uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Receive DELETE request','INFO',${header.LoopObject})" />
+ <split>
+ <simple>${header.LoopObject.getMicroServicePolicies()}
+ </simple>
+ <setHeader headerName="microServicePolicy">
+ <simple>${body}</simple>
+ </setHeader>
+ <log
+ loggingLevel="INFO"
+ message="Processing Micro Service Policy: ${header.microServicePolicy.getName()}" />
+ <setHeader headerName="RaiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setHeader>
+ <to uri="direct:delete-micro-service-policy" />
+ </split>
+
+ <log
+ loggingLevel="INFO"
+ message="Processing all OPERATIONAL policies defined in loop ${header.LoopObject.getName()}" />
+ <split>
+ <simple>${header.LoopObject.getOperationalPolicies()}
+ </simple>
+ <setHeader headerName="operationalPolicy">
+ <simple>${body}</simple>
+ </setHeader>
+ <log
+ loggingLevel="INFO"
+ message="Processing Operational Policy: ${header.operationalPolicy.getName()}" />
+ <setHeader headerName="RaiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setHeader>
+ <to uri="direct:delete-operational-policy" />
+ <log
+ loggingLevel="INFO"
+ message="Processing all GUARD policies defined in loop ${header.LoopObject.getName()}" />
+ <split>
+ <simple>${header.operationalPolicy.createGuardPolicyPayloads().entrySet()}
+ </simple>
+ <setHeader headerName="guardPolicy">
+ <simple>${body}</simple>
+ </setHeader>
+ <log
+ loggingLevel="INFO"
+ message="Processing Guard Policy: ${header.guardPolicy.getKey()}" />
+
+ <setHeader headerName="RaiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setHeader>
+ <to uri="direct:delete-guard-policy" />
+ </split>
+ </split>
+ <to uri="bean:org.onap.clamp.loop.log.LoopService?method=deleteLoop(${header.loopName})" />
+ <log
+ loggingLevel="INFO"
+ message="DELETE request successfully executed for loop: ${body}" />
<to
- uri="bean:org.onap.clamp.operation.LoopOperation?method=deleteGuardPolicy(${header.loopName})" />
+ uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DELETE request successfully executed','INFO',${header.LoopObject})" />
</route>
</put>
</rest>
diff --git a/src/main/resources/clds/camel/routes/flexible-flow.xml b/src/main/resources/clds/camel/routes/flexible-flow.xml
index 64af7b264..1ce67ccee 100644
--- a/src/main/resources/clds/camel/routes/flexible-flow.xml
+++ b/src/main/resources/clds/camel/routes/flexible-flow.xml
@@ -120,7 +120,7 @@
loggingLevel="INFO"
message="Endpoint to create microservice policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('MicroService policy created successfully','INFO',${header.LoopObject})" />
</route>
@@ -143,7 +143,7 @@
loggingLevel="INFO"
message="Endpoint to delete microservice policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('MicroService policy deleted successfully','INFO',${header.LoopObject})" />
</route>
@@ -171,7 +171,7 @@
loggingLevel="INFO"
message="Endpoint to create operational policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Operational policy created successfully','INFO',${header.LoopObject})" />
</route>
@@ -194,7 +194,7 @@
loggingLevel="INFO"
message="Endpoint to delete operational policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Operational policy deleted successfully','INFO',${header.LoopObject})" />
</route>
@@ -222,7 +222,7 @@
loggingLevel="INFO"
message="Endpoint to create guard policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Guard policy created successfully','INFO',${header.LoopObject})" />
</route>
@@ -245,7 +245,7 @@
loggingLevel="INFO"
message="Endpoint to delete guard policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Guard policy deleted successfully','INFO',${header.LoopObject})" />
</route>
@@ -273,7 +273,7 @@
loggingLevel="INFO"
message="Endpoint to create PDP Group policy: ${header.CamelHttpMethod} ${header.CamelHttpUri}"></log>
<toD
- uri="http4://policyhost:8085?throwExceptionOnFailure=${header.HttpQueryExceptionFlag}" />
+ uri="http4://policyhost:8085?throwExceptionOnFailure=${header.RaiseHttpExceptionFlag}" />
<to
uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Pdp Group created successfully','INFO',${header.LoopObject})" />
</route>
diff --git a/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java
index 23723386b..c4254ec8c 100644
--- a/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java
+++ b/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java
@@ -38,8 +38,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.onap.clamp.clds.Application;
import org.onap.clamp.clds.util.JsonUtils;
+import org.onap.clamp.loop.log.LogType;
+import org.onap.clamp.loop.log.LoopLog;
+import org.onap.clamp.loop.log.LoopLogService;
import org.onap.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.clamp.policy.microservice.MicroservicePolicyService;
import org.onap.clamp.policy.operational.OperationalPolicy;
+import org.onap.clamp.policy.operational.OperationalPolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@@ -57,6 +62,15 @@ public class LoopServiceTestItCase {
@Autowired
LoopsRepository loopsRepository;
+ @Autowired
+ MicroservicePolicyService microServicePolicyService;
+
+ @Autowired
+ OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ LoopLogService loopLogService;
+
@After
public void tearDown() {
loopsRepository.deleteAll();
@@ -276,6 +290,35 @@ public class LoopServiceTestItCase {
assertThat(returnedGlobalProperties.getAsJsonObject()).isEqualTo(updatedGlobalProperites);
}
+ @Test
+ @Transactional
+ public void deleteAttempt() {
+ saveTestLoopToDb();
+ // Add log
+ Loop loop = loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null);
+ loop.addLog(new LoopLog("test", LogType.INFO, loop));
+ loop = loopService.saveOrUpdateLoop(loop);
+ // Add op policy
+ OperationalPolicy operationalPolicy = new OperationalPolicy("opPolicy", null,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+ loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(operationalPolicy));
+
+ // Add Micro service policy
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("microPolicy", "",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", false,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null);
+ loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(microServicePolicy));
+
+ // Verify it's there
+ assertThat(loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null)).isNotNull();
+ loopService.deleteLoop(EXAMPLE_LOOP_NAME);
+ // Verify it's well deleted and has been cascaded
+ assertThat(loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null)).isNull();
+ assertThat(microServicePolicyService.isExisting("microPolicy")).isFalse();
+ assertThat(operationalPolicyService.isExisting("opPolicy")).isFalse();
+ assertThat(loopLogService.isExisting(((LoopLog) loop.getLoopLogs().toArray()[0]).getId())).isFalse();
+ }
+
private Loop createTestLoop(String loopName, String loopBlueprint, String loopSvg) {
return new Loop(loopName, loopBlueprint, loopSvg);
}