diff options
Diffstat (limited to 'src')
337 files changed, 47055 insertions, 0 deletions
diff --git a/src/main/docker/backend/Dockerfile b/src/main/docker/backend/Dockerfile new file mode 100644 index 000000000..8712f1934 --- /dev/null +++ b/src/main/docker/backend/Dockerfile @@ -0,0 +1,45 @@ +###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2018 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============================================
+# ===================================================================
+#
+###
+
+FROM onap/integration-java11:7.1.0
+
+MAINTAINER "The Onap Team"
+LABEL Description="This image contains alpine, openjdk 11 and clamp"
+
+ARG http_proxy
+ARG https_proxy
+ENV HTTP_PROXY=$http_proxy
+ENV HTTPS_PROXY=$https_proxy
+ENV http_proxy=$HTTP_PROXY
+ENV https_proxy=$HTTPS_PROXY
+USER root
+RUN mkdir /opt/clamp
+RUN chown -R onap:onap /opt/clamp
+
+VOLUME /opt/clamp/config
+
+COPY --chown=onap:onap onap-clamp-backend/clamp.jar /opt/clamp/app.jar
+
+USER onap
+WORKDIR /opt/clamp/
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-XX:MinRAMPercentage=50 -XX:MaxRAMPercentage=75","-jar" ,"./app.jar"]
\ No newline at end of file diff --git a/src/main/docker/backend/backend-files.xml b/src/main/docker/backend/backend-files.xml new file mode 100644 index 000000000..c73c47f64 --- /dev/null +++ b/src/main/docker/backend/backend-files.xml @@ -0,0 +1,43 @@ +<!-- + ============LICENSE_START======================================================= + ECOMP 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========================================================= + --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd"> + <id>clamp-files</id> + + <formats> + <format>tar.gz</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <!-- include config files --> + <fileSet> + <includes> + <include>${project.build.finalName}.jar</include> + </includes> + <directory>${project.build.directory}</directory> + <outputDirectory></outputDirectory> + </fileSet> + </fileSets> + +</assembly> diff --git a/src/main/docker/frontend/Dockerfile b/src/main/docker/frontend/Dockerfile new file mode 100644 index 000000000..660fb8240 --- /dev/null +++ b/src/main/docker/frontend/Dockerfile @@ -0,0 +1,67 @@ +###
+# ============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============================================
+# ===================================================================
+#
+###
+
+# build environment
+FROM node:12.10.0-alpine as build
+WORKDIR /app
+#ENV PATH /app/node_modules/.bin:$PATH
+COPY onap-clamp-frontend/ /app/
+RUN npm install --silent
+RUN npm run build
+
+FROM nginx:1.17.0-alpine
+
+MAINTAINER "The Onap Team"
+LABEL Description="This image contains Clamp frontend"
+
+ARG http_proxy
+ARG https_proxy
+ENV HTTP_PROXY=$http_proxy
+ENV HTTPS_PROXY=$https_proxy
+ENV http_proxy=$HTTP_PROXY
+ENV https_proxy=$HTTPS_PROXY
+
+RUN addgroup onap && adduser -D -G onap clamp
+RUN mkdir /var/log/onap
+RUN chmod a+rwx /var/log/onap
+
+COPY --from=build /app/build /usr/share/nginx/html
+COPY --from=build /app/ssl /etc/ssl
+RUN rm /etc/nginx/conf.d/default.conf
+RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
+
+COPY nginx/nginx.conf /etc/nginx/nginx.conf
+COPY nginx/default.conf /etc/nginx/conf.d/default.conf
+
+WORKDIR /app
+
+RUN chown -R clamp:onap /app && chmod -R 755 /app && \
+ chown -R clamp:onap /var/cache/nginx && \
+ chown -R clamp:onap /var/log/nginx && \
+ chown -R clamp:onap /etc/nginx/conf.d
+RUN touch /var/run/nginx.pid && \
+ chown -R clamp:onap /var/run/nginx.pid
+
+USER clamp
+EXPOSE 2443
+CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file diff --git a/src/main/docker/frontend/frontend-files.xml b/src/main/docker/frontend/frontend-files.xml new file mode 100644 index 000000000..aaf32be81 --- /dev/null +++ b/src/main/docker/frontend/frontend-files.xml @@ -0,0 +1,48 @@ +<!-- + ============LICENSE_START======================================================= + ECOMP 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========================================================= + --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd"> + <id>clamp-files</id> + + <formats> + <format>tar.gz</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <!-- include config files --> + <fileSet> + <excludes> + <exclude>node_modules</exclude> + </excludes> + <directory>${project.build.directory}/${ui.react.src}</directory> + <outputDirectory></outputDirectory> + </fileSet> + <!-- include ssl certificates files obtain from aaf p12 --> + <fileSet> + <directory>${project.basedir}/src/main/resources/clds/aaf/ssl</directory> + <outputDirectory>ssl</outputDirectory> + </fileSet> + </fileSets> + +</assembly> diff --git a/src/main/docker/frontend/nginx/default.conf b/src/main/docker/frontend/nginx/default.conf new file mode 100644 index 000000000..b15429c74 --- /dev/null +++ b/src/main/docker/frontend/nginx/default.conf @@ -0,0 +1,25 @@ +server { + + listen 2443 default ssl; + ssl_protocols TLSv1.2; + ssl_certificate /etc/ssl/clamp.pem; + ssl_certificate_key /etc/ssl/clamp.key; + ssl_verify_client optional_no_ca; + location /restservices/clds/ { + proxy_pass https://clamp-backend:8443; + proxy_set_header X-SSL-Cert $ssl_client_escaped_cert; + } + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /usr/share/nginx/html; + } + +}
\ No newline at end of file diff --git a/src/main/docker/frontend/nginx/nginx.conf b/src/main/docker/frontend/nginx/nginx.conf new file mode 100644 index 000000000..beeb2b1eb --- /dev/null +++ b/src/main/docker/frontend/nginx/nginx.conf @@ -0,0 +1,18 @@ +worker_processes 1; +pid /var/run/nginx.pid; +error_log /dev/stdout info; +events { +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + #tcp_nopush on; + keepalive_timeout 65; + #gzip on; + include /etc/nginx/conf.d/*.conf; + }
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/authorization/AuthorizationController.java b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java new file mode 100644 index 000000000..f4da09a2e --- /dev/null +++ b/src/main/java/org/onap/clamp/authorization/AuthorizationController.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.authorization; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.util.Date; +import org.apache.camel.Exchange; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.exception.NotAuthorizedException; +import org.onap.clamp.clds.model.ClampInformation; +import org.onap.clamp.clds.util.LoggingUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +/** + * Verify user has right permissions. + */ +@Component +public class AuthorizationController { + + protected static final EELFLogger logger = + EELFManager.getInstance().getLogger(AuthorizationController.class); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + protected static final EELFLogger securityLogger = + EELFManager.getInstance().getSecurityLogger(); + + // By default we'll set it to a default handler + @Autowired + private ClampProperties refProp; + + private SecurityContext securityContext = SecurityContextHolder.getContext(); + + public static final String PERM_PREFIX = "security.permission.type."; + private static final String PERM_INSTANCE = "security.permission.instance"; + + private static String retrieveUserName(SecurityContext securityContext) { + if (securityContext == null || securityContext.getAuthentication() == null) { + return null; + } + if ((securityContext.getAuthentication().getPrincipal()) instanceof String) { + // anonymous case + return ((String) securityContext.getAuthentication().getPrincipal()); + } else { + return ((UserDetails) securityContext.getAuthentication().getPrincipal()).getUsername(); + } + } + + /** + * Get the principal name. + * + * @return The principal name + */ + public static String getPrincipalName(SecurityContext securityContext) { + String principal = AuthorizationController.retrieveUserName(securityContext); + String name = "Not found"; + if (principal != null) { + name = principal; + } + return name; + } + + /** + * Insert authorize the api based on the permission. + * + * @param camelExchange The Camel Exchange object containing the properties + * @param typeVar The type of the permissions + * @param instanceVar The instance of the permissions. e.g. dev + * @param action The action of the permissions. e.g. read + */ + public void authorize(Exchange camelExchange, String typeVar, String instanceVar, + String action) { + String type = refProp.getStringValue(PERM_PREFIX + typeVar); + String instance = refProp.getStringValue(PERM_INSTANCE); + + if (null == type || type.isEmpty()) { + // authorization is turned off, since the permission is not defined + return; + } + if (null != instanceVar && !instanceVar.isEmpty()) { + instance = instanceVar; + } + String principalName = AuthorizationController.getPrincipalName(this.securityContext); + SecureServicePermission perm = SecureServicePermission.create(type, instance, action); + Date startTime = new Date(); + LoggingUtils.setTargetContext("Clamp", "authorize"); + LoggingUtils.setTimeContext(startTime, new Date()); + securityLogger.debug("checking if {} has permission: {}", principalName, perm); + + if (!isUserPermitted(perm)) { + String msg = principalName + " does not have permission: " + perm; + LoggingUtils.setErrorContext("100", "Authorization Error"); + securityLogger.warn(msg); + throw new NotAuthorizedException(msg); + } + } + + /** + * Insert authorize the api based on the permission. + * + * @param inPermission Security permission in input + * @return True if user is permitted + */ + public boolean isUserPermitted(SecureServicePermission inPermission) { + + String principalName = AuthorizationController.getPrincipalName(this.securityContext); + // check if the user has the permission key or the permission key with a + // combination of all instance and/or all action. + if (hasRole(inPermission.getKey()) || hasRole(inPermission.getKeyAllInstance())) { + auditLogger.info("{} authorized because user has permission with * for instance: {}", + principalName, inPermission.getKey().replace("|", ":")); + return true; + // the rest of these don't seem to be required - isUserInRole method + // appears to take * as a wildcard + } else if (hasRole(inPermission.getKeyAllInstanceAction())) { + auditLogger.info( + "{} authorized because user has permission with * for instance and * for action: {}", + principalName, inPermission.getKey().replace("|", ":")); + return true; + } else if (hasRole(inPermission.getKeyAllAction())) { + auditLogger.info("{} authorized because user has permission with * for action: {}", + principalName, inPermission.getKey().replace("|", ":")); + return true; + } else { + return false; + } + } + + protected boolean hasRole(String role) { + Authentication authentication = securityContext.getAuthentication(); + if (authentication == null) { + return false; + } + for (GrantedAuthority auth : authentication.getAuthorities()) { + if (role.equals(auth.getAuthority())) { + return true; + } + } + return false; + } + + /** + * Gets clds info. CLDS IFO service will return 3 things 1. User Name 2. CLDS + * code version that is currently installed from pom.xml file 3. User + * permissions + * + * @return the clds info + */ + public ClampInformation getClampInformation() { + ClampInformation clampInfo = new ClampInformation(); + Authentication authentication = securityContext.getAuthentication(); + if (authentication == null) { + return new ClampInformation(); + } + clampInfo.setUserName(AuthorizationController.getPrincipalName(this.securityContext)); + for (GrantedAuthority auth : authentication.getAuthorities()) { + clampInfo.getAllPermissions().add(auth.getAuthority()); + } + return clampInfo; + } +} diff --git a/src/main/java/org/onap/clamp/authorization/CldsUser.java b/src/main/java/org/onap/clamp/authorization/CldsUser.java new file mode 100644 index 000000000..b50f50cb2 --- /dev/null +++ b/src/main/java/org/onap/clamp/authorization/CldsUser.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.authorization; + +import java.util.Arrays; + +/** + * The class represents the CldsUser that can be extracted from cldsusers.json. + */ +public class CldsUser { + + private String user; + private String password; + private SecureServicePermission[] permissions; + + /** + * Returns the user. + * + * @return the user + */ + public String getUser() { + return user; + } + + /** + * Sets the user. + * + * @param user + * the user to set + */ + public void setUser(String user) { + this.user = user; + } + + /** + * Returns the password. + * + * @return the password + */ + public String getPassword() { + return password; + } + + /** + * Sets the password. + * + * @param password + * the password to set + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Returns the permissions. + * + * @return the permissions + */ + public SecureServicePermission[] getPermissions() { + return Arrays.copyOf(permissions, permissions.length); + } + + public String[] getPermissionsString() { + return Arrays.stream(getPermissions()).map(SecureServicePermission::getKey).toArray(String[]::new); + } + + /** + * Sets the permissions. + * + * @param permissionsArray + * the permissions to set + */ + public void setPermissions(SecureServicePermission[] permissionsArray) { + this.permissions = Arrays.copyOf(permissionsArray, permissionsArray.length); + } +} diff --git a/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java new file mode 100644 index 000000000..374aab90c --- /dev/null +++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermission.java @@ -0,0 +1,203 @@ +/*- + * ============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.authorization; + +/** + * Permission class that can be instantiated easily using constructor or factory + * methods. + */ +public class SecureServicePermission { + public static final String ALL = "*"; + + private String type; + private String instance; + private String action; + + /** + * Factory method to create permission given type, instance, and action. + * + * @param type type of the permission + * @param instance instance of the permission + * @param action action of the permission + * @return instance of SecureServicePermission with type, instance and action + */ + public static SecureServicePermission create(String type, String instance, String action) { + return new SecureServicePermission(type, instance, action); + } + + /** + * Factory method to create permission given type and instance. Default + * action to ALL/*. + * + * @param type type of the permission + * @param instance instance of the permission + * @return instance of SecureServicePermission with type, instance and default action + */ + public static SecureServicePermission create(String type, String instance) { + return new SecureServicePermission(type, instance, ALL); + } + + /** + * Factory method to create permission given type. Default instance and + * action to ALL/*. + * + * @param type type of the permission + * @return instance of SecureServicePermission with type and default instance and action + */ + public static SecureServicePermission create(String type) { + return new SecureServicePermission(type, ALL, ALL); + } + + /** + * Instantiate permission given type, instance, and action. + * + * @param type type of the permission + * @param instance instance of the permission + * @param action action of the permission + */ + public SecureServicePermission(String type, String instance, String action) { + this.type = type; + this.instance = instance; + this.action = action; + } + + /** + * Instantiate permission given type from concatenated string + * + * @param concatenatedString + * the string type|instance|action, less than 3 params can be + * provided (e.g. "permission-type-cl", "permission-type-cl|dev", + * "permission-type-cl|dev|update" ) + */ + public SecureServicePermission(String concatenatedString) { + String[] userInfo = concatenatedString.split("[|]"); + // We should have at least 1 string + this.type = userInfo[0]; + this.instance = (userInfo.length > 1 ? userInfo[1] : ALL); + this.action = (userInfo.length > 2 ? userInfo[2] : ALL); + } + + /** + * Override toString - return permission in key format. + */ + @Override + public String toString() { + return getKey(); + } + + /** + * Return Permission in Key format = type, instance, and action separate by + * pipe character. + * + * @return permission in key format + */ + public String getKey() { + return type + "|" + instance + "|" + action; + } + + /** + * Return Permission in Key format = type, all instance, and action separate + * by pipe character. + * + * @return permission in key format + */ + public String getKeyAllInstance() { + return type + "|" + ALL + "|" + action; + } + + /** + * Return Permission in Key format = type, all instance, and all action + * separate by pipe character. + * + * @return permission in key format + */ + public String getKeyAllInstanceAction() { + return type + "|" + ALL + "|" + ALL; + } + + /** + * Return Permission in Key format = type, instance, and all action separate + * by pipe character. + * + * @return permission in key format + */ + public String getKeyAllAction() { + return type + "|" + instance + "|" + ALL; + } + + /** + * Returns the permission type. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * Sets the type of permission. + * + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * Returns the instance of permission. + * + * @return the instance + */ + public String getInstance() { + return instance; + } + + /** + * Sets the instance of permission. + * + * @param instance the instance to set + */ + public void setInstance(String instance) { + this.instance = instance; + } + + /** + * Returns the action of permission. + * + * @return the action + */ + public String getAction() { + return action; + } + + /** + * Sets the action of permission. + * + * @param action the action to set + */ + public void setAction(String action) { + this.action = action; + } + +} diff --git a/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java new file mode 100644 index 000000000..026ee802c --- /dev/null +++ b/src/main/java/org/onap/clamp/authorization/SecureServicePermissionDeserializer.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.authorization; + + +import com.google.gson.Gson; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import java.lang.reflect.Type; + +public class SecureServicePermissionDeserializer implements JsonDeserializer<SecureServicePermission> { + + @Override + public SecureServicePermission deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + if (json.isJsonPrimitive()) { + return new SecureServicePermission(json.getAsString()); + } else { + // if not string try default deserialization + return new Gson().fromJson(json, SecureServicePermission.class); + } + } +} diff --git a/src/main/java/org/onap/clamp/authorization/UserService.java b/src/main/java/org/onap/clamp/authorization/UserService.java new file mode 100644 index 000000000..b4f51c95b --- /dev/null +++ b/src/main/java/org/onap/clamp/authorization/UserService.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.authorization; + + +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; + +/** + * User service used for authorization verification at the login page. Do not + * remove this class. + */ +@Controller +public class UserService { + + private SecurityContext securityContext = SecurityContextHolder.getContext(); + + /** + * REST service that returns the username. + * + * @return the user name + */ + public String getUser() { + return AuthorizationController.getPrincipalName(securityContext); + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/Application.java b/src/main/java/org/onap/clamp/clds/Application.java new file mode 100644 index 000000000..e83ff3e76 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/Application.java @@ -0,0 +1,182 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import org.apache.catalina.connector.Connector; +import org.onap.clamp.clds.util.ClampVersioning; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.util.PassDecoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@ComponentScan(basePackages = { "org.onap.clamp" }) +@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class }) +@EnableJpaRepositories(basePackages = { "org.onap.clamp" }) +@EntityScan(basePackages = { "org.onap.clamp" }) +@EnableTransactionManagement +@EnableConfigurationProperties +@EnableAsync +@EnableScheduling +@EnableJpaAuditing +public class Application extends SpringBootServletInitializer { + + protected static final EELFLogger eelfLogger = EELFManager.getInstance().getLogger(Application.class); + // This settings is an additional one to Spring config, + // only if we want to have an additional port automatically redirected to + // HTTPS + @Value("${server.http-to-https-redirection.port:none}") + private String httpRedirectedPort; + /** + * This 8080 is the default port used by spring if this parameter is not + * specified in application.properties. + */ + @Value("${server.port:8080}") + private String springServerPort; + @Value("${server.ssl.key-store:none}") + private String sslKeystoreFile; + + @Autowired + private Environment env; + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + public static void main(String[] args) { + // Start the Spring application + SpringApplication.run(Application.class, args); + } + + /** + * This method is used to declare the camel servlet. + * + * @return A servlet bean + * @throws IOException IO Exception + */ + @Bean + public ServletRegistrationBean camelServletRegistrationBean() throws IOException { + eelfLogger.info(ResourceFileUtils.getResourceAsString("boot-message.txt") + "(v" + + ClampVersioning.getCldsVersionFromProps() + ")" + System.getProperty("line.separator") + + getSslExpirationDate()); + ServletRegistrationBean registration = new ServletRegistrationBean(new ClampServlet(), "/restservices/clds/*"); + registration.setName("CamelServlet"); + return registration; + } + + /** + * This method is used by Spring to create the servlet container factory. + * + * @return The TomcatEmbeddedServletContainerFactory just created + */ + @Bean + public ServletWebServerFactory getEmbeddedServletContainerFactory() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + if (!"none".equals(httpRedirectedPort) && !"none".equals(sslKeystoreFile)) { + // Automatically redirect to HTTPS + tomcat = new TomcatEmbeddedServletContainerFactoryRedirection(); + Connector newConnector = createRedirectConnector(Integer.parseInt(springServerPort)); + if (newConnector != null) { + tomcat.addAdditionalTomcatConnectors(newConnector); + } + } + return tomcat; + } + + private Connector createRedirectConnector(int redirectSecuredPort) { + if (redirectSecuredPort <= 0) { + eelfLogger.warn("HTTP port redirection to HTTPS is disabled because the HTTPS port is 0 (random port) or -1" + + " (Connector disabled)"); + return null; + } + Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); + connector.setScheme("http"); + connector.setSecure(false); + connector.setPort(Integer.parseInt(httpRedirectedPort)); + connector.setRedirectPort(redirectSecuredPort); + return connector; + } + + private String getSslExpirationDate() throws IOException { + StringBuilder result = new StringBuilder(" :: SSL Certificates :: "); + try { + if (env.getProperty("server.ssl.key-store") != null) { + + KeyStore keystore = KeyStore.getInstance(env.getProperty("server.ssl.key-store-type")); + String password = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"), + env.getProperty("clamp.config.keyFile")); + String keyStore = env.getProperty("server.ssl.key-store"); + InputStream is = ResourceFileUtils.getResourceAsStream(keyStore.replaceAll("classpath:", "")); + keystore.load(is, password.toCharArray()); + + Enumeration<String> aliases = keystore.aliases(); + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + if ("X.509".equals(keystore.getCertificate(alias).getType())) { + result.append("* " + alias + " expires " + + ((X509Certificate) keystore.getCertificate(alias)).getNotAfter() + + System.getProperty("line.separator")); + } + } + } else { + result.append("* NONE HAS been configured"); + } + } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) { + eelfLogger.warn("SSL certificate access error ", e); + + } + return result.toString(); + } +} diff --git a/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java b/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java new file mode 100644 index 000000000..9351db23c --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/ClampInUserAuditorAware.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds; + +import java.util.Optional; +import org.onap.clamp.authorization.AuthorizationController; +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component +public class ClampInUserAuditorAware implements AuditorAware<String> { + + @Override + public Optional<String> getCurrentAuditor() { + return Optional.of(AuthorizationController.getPrincipalName(SecurityContextHolder.getContext())); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/ClampServlet.java b/src/main/java/org/onap/clamp/clds/ClampServlet.java new file mode 100644 index 000000000..8ebc7a16b --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/ClampServlet.java @@ -0,0 +1,142 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import fj.data.Array; +import java.io.IOException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import java.util.stream.Collector; +import java.util.stream.Collectors; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.camel.component.servlet.CamelHttpTransportServlet; +import org.onap.clamp.authorization.SecureServicePermission; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.web.context.support.WebApplicationContextUtils; + +public class ClampServlet extends CamelHttpTransportServlet { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = -4198841134910211542L; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampServlet.class); + private static final String PERM_INSTANCE = "clamp.config.security.permission.instance"; + private static final String PERM_CL = "clamp.config.security.permission.type.cl"; + private static final String PERM_TEMPLATE = "clamp.config.security.permission.type.template"; + private static final String PERM_VF = "clamp.config.security.permission.type.filter.vf"; + private static final String PERM_MANAGE = "clamp.config.security.permission.type.cl.manage"; + private static final String PERM_TOSCA = "clamp.config.security.permission.type.tosca"; + private static final String AUTHENTICATION_CLASS = "clamp.config.security.authentication.class"; + private static final String READ = "read"; + private static final String UPDATE = "update"; + + private static List<SecureServicePermission> permissionList; + + private synchronized List<String> loadDynamicAuthenticationClasses() { + return Arrays.stream(WebApplicationContextUtils.getWebApplicationContext(getServletContext()) + .getEnvironment().getProperty(AUTHENTICATION_CLASS).split(",")).map(className -> className.trim()) + .collect(Collectors.toList()); + } + + private synchronized List<SecureServicePermission> getPermissionList() { + if (permissionList == null) { + permissionList = new ArrayList<>(); + ApplicationContext applicationContext = WebApplicationContextUtils + .getWebApplicationContext(getServletContext()); + String cldsPermissionInstance = applicationContext.getEnvironment().getProperty(PERM_INSTANCE); + permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL), + cldsPermissionInstance, READ)); + permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL), + cldsPermissionInstance, UPDATE)); + permissionList.add(SecureServicePermission.create( + applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, READ)); + permissionList.add(SecureServicePermission.create( + applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, UPDATE)); + permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_VF), + cldsPermissionInstance, "*")); + permissionList.add(SecureServicePermission + .create(applicationContext.getEnvironment().getProperty(PERM_MANAGE), cldsPermissionInstance, "*")); + permissionList.add(SecureServicePermission + .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA), cldsPermissionInstance, READ)); + permissionList.add(SecureServicePermission + .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA), + cldsPermissionInstance, UPDATE)); + } + return permissionList; + } + + /** + * When AAF is enabled, request object will contain a cadi Wrapper, so queries + * to isUserInRole will invoke a http call to AAF server. + */ + @Override + protected void doService(HttpServletRequest request, HttpServletResponse response) { + Principal principal = request.getUserPrincipal(); + if (principal != null && loadDynamicAuthenticationClasses().stream() + .anyMatch(className -> className.equals(principal.getClass().getName()))) { + // When AAF is enabled, there is a need to provision the permissions to Spring + // system + List<GrantedAuthority> grantedAuths = new ArrayList<>(); + for (SecureServicePermission perm : getPermissionList()) { + String permString = perm.toString(); + if (request.isUserInRole(permString)) { + grantedAuths.add(new SimpleGrantedAuthority(permString)); + } + } + Authentication auth = new UsernamePasswordAuthenticationToken(new User(principal.getName(), "", + grantedAuths), "", grantedAuths); + SecurityContextHolder.getContext().setAuthentication(auth); + } + try { + super.doService(request, response); + } catch (ServletException | IOException ioe) { + logger.error("Exception caught when executing doService in servlet", ioe); + try { + response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value()); + } catch (IOException e) { + logger.error("Exception caught when executing HTTP sendError in servlet", e); + } + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java b/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java new file mode 100644 index 000000000..a0109a688 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java @@ -0,0 +1,53 @@ +/*- + * ============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.clds; + +import org.apache.catalina.Context; +import org.apache.tomcat.util.descriptor.web.SecurityCollection; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; + +/** + * This class is a factory that redirects by default all HTTP to HTTPS + * connector. It is used by the Application.java class and defined in a Spring + * Bean. + * In order to do this, the method postProcessContext has been overridden to + * provide another behavior. + */ +public class TomcatEmbeddedServletContainerFactoryRedirection extends TomcatServletWebServerFactory { + + /** + * This method is there to force the automatic redirection of all calls done + * on the tomcat server to a Secure connection. + */ + @Override + protected void postProcessContext(Context context) { + SecurityConstraint securityConstraint = new SecurityConstraint(); + securityConstraint.setUserConstraint("CONFIDENTIAL"); + SecurityCollection collection = new SecurityCollection(); + collection.addPattern("/*"); + securityConstraint.addCollection(collection); + context.addConstraint(securityConstraint); + } +} 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 000000000..fd3b3539a --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/client/CdsServices.java @@ -0,0 +1,229 @@ +/*-
+ * ============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 static java.lang.Boolean.parseBoolean;
+
+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.exception.cds.CdsParametersException;
+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);
+
+ private static final String TYPE = "type";
+ private static final String PROPERTIES = "properties";
+ private static final String LIST = "list";
+
+ /**
+ * 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);
+ } else {
+ logger.error("CDS getBlueprintWorkflowList FAILED");
+ 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);
+ } else {
+ logger.error("CDS getWorkflowInputProperties FAILED");
+ return null;
+ }
+ }
+
+ protected 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, new JsonObject()));
+ return workFlowProperties;
+ }
+
+ private JsonObject getInputProperties(JsonObject inputs, JsonObject dataTypes,
+ JsonObject inputObject) {
+ if (inputs == null) {
+ return inputObject;
+ }
+
+ for (Map.Entry<String, JsonElement> 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 if (LIST.equalsIgnoreCase(type)) {
+ handleListType(key, inputProperty, dataTypes, inputObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(key, entry.getValue());
+ }
+ }
+ return inputObject;
+ }
+
+ private void handleListType(String propertyName,
+ JsonObject inputProperty,
+ JsonObject dataTypes,
+ JsonObject inputObject) {
+ if (inputProperty.get("entry_schema") == null) {
+ throw new CdsParametersException("Entry schema is null for " + propertyName);
+ }
+
+ String type = inputProperty.get("entry_schema").getAsJsonObject().get(
+ TYPE).getAsString();
+ if (dataTypes.get(type) != null) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, LIST);
+ jsonObject.add(PROPERTIES, getPropertiesObject(type, dataTypes));
+ inputObject.add(propertyName, jsonObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(propertyName, inputProperty);
+ }
+ }
+
+ private JsonObject handleComplexType(String key, JsonObject dataTypes) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, "object");
+ jsonObject.add(PROPERTIES, getPropertiesObject(key, dataTypes));
+ return jsonObject;
+ }
+
+ private JsonObject getPropertiesObject(String key, JsonObject dataTypes) {
+ JsonObject properties = dataTypes.get(key).getAsJsonObject().get(PROPERTIES).getAsJsonObject();
+ JsonObject object = new JsonObject();
+ getInputProperties(properties, dataTypes, object);
+ return object;
+ }
+
+ private boolean isComplexType(String type, JsonObject dataTypes) {
+ if (dataTypes == null) {
+ return false;
+ }
+ return dataTypes.get(type) != null;
+ }
+
+ private boolean isInputParam(JsonObject inputProperty) {
+ JsonElement inputParam = inputProperty.get("input-param");
+ if (inputParam == null) {
+ return false;
+ }
+ return parseBoolean(inputParam.getAsString());
+ }
+
+ /**
+ * 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/client/DcaeInventoryServices.java b/src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java new file mode 100644 index 000000000..b24bc99b2 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/client/DcaeInventoryServices.java @@ -0,0 +1,141 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 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============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.client;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse;
+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 DCAE for the service inventory.
+ */
+@Component
+public class DcaeInventoryServices {
+
+ @Autowired
+ CamelContext camelContext;
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeInventoryServices.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static final String DCAE_INVENTORY_URL = "dcae.inventory.url";
+ public static final String DCAE_INVENTORY_RETRY_INTERVAL = "dcae.intentory.retry.interval";
+ public static final String DCAE_INVENTORY_RETRY_LIMIT = "dcae.intentory.retry.limit";
+ private final ClampProperties refProp;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public DcaeInventoryServices(ClampProperties refProp) {
+ this.refProp = refProp;
+ }
+
+ private int getTotalCountFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ Long totalCount = (Long) jsonObj.get("totalCount");
+ return totalCount.intValue();
+ }
+
+ private DcaeInventoryResponse getItemsFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ JSONArray itemsArray = (JSONArray) jsonObj.get("items");
+ JSONObject dcaeServiceType0 = (JSONObject) itemsArray.get(0);
+ return JsonUtils.GSON.fromJson(dcaeServiceType0.toString(), DcaeInventoryResponse.class);
+ }
+
+ /**
+ * DO a query to DCAE to get some Information.
+ *
+ * @param artifactName The artifact Name
+ * @param serviceUuid The service UUID
+ * @param resourceUuid The resource UUID
+ * @return The DCAE inventory for the artifact in DcaeInventoryResponse
+ * @throws IOException In case of issues with the stream
+ * @throws ParseException In case of issues with the Json parsing
+ */
+ public DcaeInventoryResponse getDcaeInformation(String artifactName, String serviceUuid, String resourceUuid)
+ throws IOException, ParseException, InterruptedException {
+ LoggingUtils.setTargetContext("DCAE", "getDcaeInformation");
+
+ int retryInterval = 0;
+ int retryLimit = 1;
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT) != null) {
+ retryLimit = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT));
+ }
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL) != null) {
+ retryInterval = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL));
+ }
+ for (int i = 0; i < retryLimit; i++) {
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)
+ .withProperty("blueprintResourceId", resourceUuid).withProperty("blueprintServiceId", serviceUuid)
+ .withProperty("blueprintName", artifactName).build();
+ metricsLogger.info("Attempt n°" + i + " to contact DCAE inventory");
+
+ Exchange exchangeResponse = camelContext.createProducerTemplate()
+ .send("direct:get-dcae-blueprint-inventory", myCamelExchange);
+
+ if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {
+ String dcaeResponse = (String) exchangeResponse.getIn().getBody();
+ int totalCount = getTotalCountFromDcaeInventoryResponse(dcaeResponse);
+ metricsLogger.info("getDcaeInformation complete: totalCount returned=" + totalCount);
+ if (totalCount > 0) {
+ logger.info("getDcaeInformation, answer from DCAE inventory:" + dcaeResponse);
+ LoggingUtils.setResponseContext("0", "Get Dcae Information success", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return getItemsFromDcaeInventoryResponse(dcaeResponse);
+ } else {
+ logger.info("Dcae inventory totalCount returned is 0, so waiting " + retryInterval
+ + "ms before retrying ...");
+ // wait for a while and try to connect to DCAE again
+ Thread.sleep(retryInterval);
+ }
+ }
+ }
+ logger.warn("Dcae inventory totalCount returned is still 0, after " + retryLimit + " attempts, returning NULL");
+ return null;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java b/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java new file mode 100644 index 000000000..c75d733a8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/client/PolicyEngineServices.java @@ -0,0 +1,227 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.client; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +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.config.ClampProperties; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintMicroService; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsService; +import org.onap.clamp.policy.pdpgroup.PdpGroup; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + + +/** + * The class implements the communication with the Policy Engine to retrieve + * policy models (tosca). It mainly delegates the physical calls to Camel + * engine. + */ +@Component +public class PolicyEngineServices { + private final CamelContext camelContext; + + private final PolicyModelsService policyModelsService; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineServices.class); + private static int retryInterval = 0; + private static int retryLimit = 1; + + public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval"; + public static final String POLICY_RETRY_LIMIT = "policy.retry.limit"; + + /** + * Default constructor. + * + * @param camelContext Camel context bean + * @param clampProperties ClampProperties bean + * @param policyModelsService policyModel service + */ + @Autowired + public PolicyEngineServices(CamelContext camelContext, ClampProperties clampProperties, + PolicyModelsService policyModelsService) { + this.camelContext = camelContext; + this.policyModelsService = policyModelsService; + if (clampProperties.getStringValue(POLICY_RETRY_LIMIT) != null) { + retryLimit = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_LIMIT)); + } + if (clampProperties.getStringValue(POLICY_RETRY_INTERVAL) != null) { + retryInterval = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_INTERVAL)); + } + } + + /** + * This method query Policy engine and create a PolicyModel object with type and version. + * If the policy already exist in the db it returns the existing one. + * + * @param policyType The policyType id + * @param policyVersion The policy version of that type + * @return A PolicyModel created from policyEngine data or null if nothing is found on policyEngine + */ + public PolicyModel createPolicyModelFromPolicyEngine(String policyType, String policyVersion) { + PolicyModel policyModelFound = policyModelsService.getPolicyModel(policyType, policyVersion); + if (policyModelFound == null) { + String policyTosca = this.downloadOnePolicy(policyType, policyVersion); + if (policyTosca != null && !policyTosca.isEmpty()) { + return policyModelsService.savePolicyModelInNewTransaction( + new PolicyModel(policyType, policyTosca, policyVersion)); + } else { + logger.error("Policy not found in the Policy Engine, returning null: " + policyType + + "/" + policyVersion); + return null; + } + } else { + logger.info("Skipping policy model download as it exists already in the database " + policyType + + "/" + policyVersion); + return policyModelFound; + } + } + + /** + * This method query Policy engine and create a PolicyModel object with type and version. + * + * @param microService microservice object instance + * @return A PolicyModel created from policyEngine data + */ + public PolicyModel createPolicyModelFromPolicyEngine(BlueprintMicroService microService) { + return createPolicyModelFromPolicyEngine(microService.getModelType(), microService.getModelVersion()); + } + + /** + * This method synchronize the clamp database and the policy engine. + * So it creates the required PolicyModel. + */ + public void synchronizeAllPolicies() { + LinkedHashMap<String, Object> loadedYaml; + loadedYaml = new Yaml().load(downloadAllPolicies()); + if (loadedYaml == null || loadedYaml.isEmpty()) { + logger.warn("getAllPolicyType yaml returned by policy engine could not be decoded, as it's null or empty"); + return; + } + + LinkedHashMap<String, Object> policyTypesMap = (LinkedHashMap<String, Object>) loadedYaml + .get("policy_types"); + policyTypesMap.forEach((key, value) -> + this.createPolicyModelFromPolicyEngine(key, + ((String) ((LinkedHashMap<String, Object>) value).get("version")))); + } + + /** + * This method can be used to download all policy types + data types defined in + * policy engine. + * + * @return A yaml containing all policy Types and all data types + */ + public String downloadAllPolicies() { + return callCamelRoute(ExchangeBuilder.anExchange(camelContext).build(), "direct:get-all-policy-models", + "Get all policies"); + } + + /** + * This method can be used to download a policy tosca model on the engine. + * + * @param policyType The policy type (id) + * @param policyVersion The policy version + * @return A string with the whole policy tosca model + */ + public String downloadOnePolicy(String policyType, String policyVersion) { + logger.info("Downloading the policy model " + policyType + "/" + policyVersion); + DumperOptions options = new DumperOptions(); + options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN); + options.setIndent(4); + options.setPrettyFlow(true); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + Yaml yamlParser = new Yaml(options); + String responseBody = callCamelRoute( + ExchangeBuilder.anExchange(camelContext).withProperty("policyModelName", policyType) + .withProperty("policyModelVersion", policyVersion).build(), "direct:get-policy-model", + "Get one policy"); + + if (responseBody == null || responseBody.isEmpty()) { + logger.warn("getPolicyModel returned by policy engine could not be decoded, as it's null or empty"); + return null; + } + + return yamlParser.dump((Map<String, Object>) yamlParser.load(responseBody)); + } + + /** + * This method can be used to download all Pdp Groups data from policy engine. + */ + public void downloadPdpGroups() { + String responseBody = + callCamelRoute(ExchangeBuilder.anExchange(camelContext).build(), "direct:get-all-pdp-groups", + "Get Pdp Groups"); + + if (responseBody == null || responseBody.isEmpty()) { + logger.warn("getPdpGroups returned by policy engine could not be decoded, as it's null or empty"); + return; + } + + JsonObject jsonObj = JsonUtils.GSON.fromJson(responseBody, JsonObject.class); + + List<PdpGroup> pdpGroupList = new LinkedList<>(); + JsonArray itemsArray = (JsonArray) jsonObj.get("groups"); + + for (com.google.gson.JsonElement jsonElement : itemsArray) { + JsonObject item = (JsonObject) jsonElement; + PdpGroup pdpGroup = JsonUtils.GSON.fromJson(item.toString(), PdpGroup.class); + pdpGroupList.add(pdpGroup); + } + + policyModelsService.updatePdpGroupInfo(pdpGroupList); + } + + private String callCamelRoute(Exchange exchange, String camelFlow, String logMsg) { + for (int i = 0; i < retryLimit; i++) { + Exchange exchangeResponse = camelContext.createProducerTemplate().send(camelFlow, exchange); + if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) { + return (String) exchangeResponse.getIn().getBody(); + } else { + logger.info(logMsg + " query " + retryInterval + "ms before retrying ..."); + // wait for a while and try to connect to DCAE again + try { + Thread.sleep(retryInterval); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + return ""; + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java b/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java new file mode 100644 index 000000000..d9178cb9a --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/AafConfiguration.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.config; + +import javax.servlet.Filter; + +import org.onap.clamp.clds.filter.ClampCadiFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("clamp-aaf-authentication") +public class AafConfiguration { + + /** + * Method to return clamp cadi filter. + * + * @return Filter + */ + @Bean(name = "cadiFilter") + public Filter cadiFilter() { + return new ClampCadiFilter(); + } + + /** + * Method to register cadi filter. + * + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean cadiFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(cadiFilter()); + registration.addUrlPatterns("/restservices/clds/v1/user/*"); + registration.addUrlPatterns("/restservices/clds/v2/dictionary/*"); + registration.addUrlPatterns("/restservices/clds/v2/templates/*"); + registration.addUrlPatterns("/restservices/clds/v2/clampInformation/*"); + registration.addUrlPatterns("/restservices/clds/v2/policyToscaModels/*"); + registration.addUrlPatterns("/restservices/clds/v2/loop/*"); + registration.setName("cadiFilter"); + registration.setOrder(0); + return registration; + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java b/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java new file mode 100644 index 000000000..36e11f64f --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/CamelConfiguration.java @@ -0,0 +1,134 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.config; + +import java.io.IOException; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.http4.HttpClientConfigurer; +import org.apache.camel.component.http4.HttpComponent; +import org.apache.camel.model.rest.RestBindingMode; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.onap.clamp.clds.util.ClampVersioning; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.util.PassDecoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +@Component +public class CamelConfiguration extends RouteBuilder { + + @Autowired + CamelContext camelContext; + + @Autowired + private Environment env; + + private void configureDefaultSslProperties() throws IOException { + if (env.getProperty("server.ssl.trust-store") != null) { + URL storeResource = Thread.currentThread().getContextClassLoader() + .getResource(env.getProperty("server.ssl.trust-store").replaceFirst("classpath:", "")); + System.setProperty("javax.net.ssl.trustStore", storeResource.getPath()); + String keyFile = env.getProperty("clamp.config.keyFile"); + String trustStorePass = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"), + keyFile); + System.setProperty("javax.net.ssl.trustStorePassword", trustStorePass); + System.setProperty("javax.net.ssl.trustStoreType", "jks"); + System.setProperty("ssl.TrustManagerFactory.algorithm", "PKIX"); + storeResource = Thread.currentThread().getContextClassLoader() + .getResource(env.getProperty("server.ssl.key-store").replaceFirst("classpath:", "")); + System.setProperty("javax.net.ssl.keyStore", storeResource.getPath()); + + String keyStorePass = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"), + keyFile); + System.setProperty("javax.net.ssl.keyStorePassword", keyStorePass); + System.setProperty("javax.net.ssl.keyStoreType", env.getProperty("server.ssl.key-store-type")); + } + } + + private void registerTrustStore() + throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException, IOException { + if (env.getProperty("server.ssl.trust-store") != null) { + KeyStore truststore = KeyStore.getInstance("JKS"); + String keyFile = env.getProperty("clamp.config.keyFile"); + String password = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"), keyFile); + truststore.load( + ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.trust-store")), + password.toCharArray()); + + TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("PKIX"); + trustFactory.init(truststore); + SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(null, trustFactory.getTrustManagers(), null); + SSLSocketFactory factory = new SSLSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + SchemeRegistry registry = new SchemeRegistry(); + final Scheme scheme = new Scheme("https4", 443, factory); + registry.register(scheme); + ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); + HttpComponent http4 = camelContext.getComponent("https4", HttpComponent.class); + http4.setHttpClientConfigurer(new HttpClientConfigurer() { + + @Override + public void configureHttpClient(HttpClientBuilder builder) { + builder.setSSLSocketFactory(factory); + Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() + .register("https", factory).register("http", plainsf).build(); + builder.setConnectionManager(new BasicHttpClientConnectionManager(registry)); + } + }); + } + } + + @Override + public void configure() + throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + restConfiguration().component("servlet").bindingMode(RestBindingMode.json).jsonDataFormat("clamp-gson") + .dataFormatProperty("prettyPrint", "true")// .enableCORS(true) + // turn on swagger api-doc + .apiContextPath("api-doc").apiVendorExtension(true).apiProperty("api.title", "Clamp Rest API") + .apiProperty("api.version", ClampVersioning.getCldsVersionFromProps()) + .apiProperty("base.path", "/restservices/clds/"); + + // camelContext.setTracing(true); + + configureDefaultSslProperties(); + registerTrustStore(); + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/ClampProperties.java b/src/main/java/org/onap/clamp/clds/config/ClampProperties.java new file mode 100644 index 000000000..0b5c951bf --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/ClampProperties.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.config; + +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +/** + * Holds Clamp properties and add some functionalities. + */ +@Component +public class ClampProperties { + + @Autowired + private ApplicationContext appContext; + @Autowired + private Environment env; + public static final String CONFIG_PREFIX = "clamp.config."; + + /** + * get property value. + * + * @param key The first key + * @return The string with the value + */ + public String getStringValue(String key) { + return env.getProperty(CONFIG_PREFIX + key); + } + + /** + * get property value for a combo key (key1 + "." + key2). If not found just use + * key1. + * + * @param key1 The first key + * @param key2 The second key after a dot + * @return The string with the value + */ + public String getStringValue(String key1, String key2) { + String value = getStringValue(key1 + "." + key2); + if (value == null || value.length() == 0) { + value = getStringValue(key1); + } + return value; + } + + /** + * Return the file content. The value obtained from the clds-reference file will + * be used as a filename. + * + * @param key The key that will be used to access the clds-reference file + * @return File content in String + * @throws IOException In case of issues with the JSON parser + */ + public String getFileContent(String key) throws IOException { + String fileReference = getStringValue(key); + return (fileReference != null) ? getFileContentFromPath(fileReference) : null; + } + + /** + * Return the file content. First try with combo key (key1 + "." + key2), + * otherwise default to just key1. The value obtained from the clds-reference + * file will be used as a filename. + * + * @param key1 The first key + * @param key2 The second key after a dot + * @return File content in String + * @throws IOException In case of issues with the JSON parser + */ + public String getFileContent(String key1, String key2) throws IOException { + String fileReference = getStringValue(key1, key2); + return (fileReference != null) ? getFileContentFromPath(fileReference) : null; + } + + private String getFileContentFromPath(String filepath) throws IOException { + URL url = appContext.getResource(filepath).getURL(); + return IOUtils.toString(url, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java new file mode 100644 index 000000000..a7ef10738 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/CldsUserJsonDecoder.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.config; + +import com.google.gson.JsonParseException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; +import org.onap.clamp.authorization.CldsUser; +import org.onap.clamp.clds.exception.CldsUsersException; +import org.onap.clamp.clds.util.JsonUtils; + +public class CldsUserJsonDecoder { + + private CldsUserJsonDecoder() { + } + + /** + * This method decodes the JSON file provided to a CldsUser Array. The stream is + * closed after this call, this is not possible to reuse it. + * + * @param cldsUsersFile + * The inputStream containing the users json file + * @return CldsUser[] Array containing a list of the user defined in the JSON + * file + */ + public static CldsUser[] decodeJson(InputStream cldsUsersFile) { + try { + return decodeJson(IOUtils.toString(cldsUsersFile, StandardCharsets.UTF_8.name())); + } catch (IOException e) { + throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e); + } + } + + /** + * This method decodes the JSON string to a CldsUser Array. + * + * @param cldsUsersString JSON string + * @return CldsUser[] Array containing a list of the user defined in the JSON + */ + public static CldsUser[] decodeJson(String cldsUsersString) { + try { + // the ObjectMapper readValue method closes the stream no need to do + // it + return JsonUtils.GSON.fromJson(cldsUsersString, CldsUser[].class); + } catch (JsonParseException e) { + throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e); + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java b/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java new file mode 100644 index 000000000..1c52e4100 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/DefaultDictionaryElements.java @@ -0,0 +1,167 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.config; + +import javax.annotation.PostConstruct; +import org.onap.clamp.tosca.Dictionary; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("default-dictionary-elements") +public class DefaultDictionaryElements { + + @Autowired + private DictionaryService dictionaryService; + + /** + * Init method. + */ + @PostConstruct + public void init() { + preProvisionDefaultActors(); + preProvisionDefaultOperations(); + } + + private void preProvisionDefaultActors() { + // Set up dictionary elements + Dictionary actorDictionary = new Dictionary(); + actorDictionary.setName("DefaultActors"); + actorDictionary.setSecondLevelDictionary(0); + actorDictionary.setSubDictionaryType(""); + + DictionaryElement elementSo = new DictionaryElement(); + elementSo.setName("SO"); + elementSo.setShortName("SO"); + elementSo.setType("string"); + elementSo.setDescription("SO component"); + actorDictionary.addDictionaryElements(elementSo); + + DictionaryElement elementSdnc = new DictionaryElement(); + elementSdnc.setName("SDNC"); + elementSdnc.setShortName("SDNC"); + elementSdnc.setType("string"); + elementSdnc.setDescription("SDNC component"); + actorDictionary.addDictionaryElements(elementSdnc); + + DictionaryElement elementAppc = new DictionaryElement(); + elementAppc.setName("APPC"); + elementAppc.setShortName("APPC"); + elementAppc.setType("string"); + elementAppc.setDescription("APPC component"); + actorDictionary.addDictionaryElements(elementAppc); + + DictionaryElement elementVfc = new DictionaryElement(); + elementVfc.setName("VFC"); + elementVfc.setShortName("VFC"); + elementVfc.setType("string"); + elementVfc.setDescription("VFC component"); + actorDictionary.addDictionaryElements(elementVfc); + + DictionaryElement elementSdnr = new DictionaryElement(); + elementSdnr.setName("SDNR"); + elementSdnr.setShortName("SDNR"); + elementSdnr.setType("string"); + elementSdnr.setDescription("SDNR component"); + actorDictionary.addDictionaryElements(elementSdnr); + + dictionaryService.saveOrUpdateDictionary(actorDictionary); + } + + private void preProvisionDefaultOperations() { + // Set up dictionary elements + Dictionary operationDictionary = new Dictionary(); + operationDictionary.setName("DefaultOperations"); + operationDictionary.setSecondLevelDictionary(0); + operationDictionary.setSubDictionaryType(""); + + DictionaryElement elementRestart = new DictionaryElement(); + elementRestart.setName("Restart"); + elementRestart.setShortName("Restart (APPC operation)"); + elementRestart.setType("string"); + elementRestart.setDescription("APPC operation"); + operationDictionary.addDictionaryElements(elementRestart); + + DictionaryElement elementRebuild = new DictionaryElement(); + elementRebuild.setName("Rebuild"); + elementRebuild.setShortName("Rebuild (APPC operation)"); + elementRebuild.setType("string"); + elementRebuild.setDescription("APPC operation"); + operationDictionary.addDictionaryElements(elementRebuild); + + DictionaryElement elementMigrate = new DictionaryElement(); + elementMigrate.setName("Migrate"); + elementMigrate.setShortName("Migrate (APPC operation)"); + elementMigrate.setType("string"); + elementMigrate.setDescription("APPC operation"); + operationDictionary.addDictionaryElements(elementMigrate); + + DictionaryElement elementHealthCheck = new DictionaryElement(); + elementHealthCheck.setName("Health-Check"); + elementHealthCheck.setShortName("Health-Check (APPC operation)"); + elementHealthCheck.setType("string"); + elementHealthCheck.setDescription("APPC operation"); + operationDictionary.addDictionaryElements(elementHealthCheck); + + DictionaryElement elementModifyConfig = new DictionaryElement(); + elementModifyConfig.setName("ModifyConfig"); + elementModifyConfig.setShortName("ModifyConfig (APPC/VFC operation)"); + elementModifyConfig.setType("string"); + elementModifyConfig.setDescription("APPC/VFC operation"); + operationDictionary.addDictionaryElements(elementModifyConfig); + + DictionaryElement elementVfModuleCreate = new DictionaryElement(); + elementVfModuleCreate.setName("VF Module Create"); + elementVfModuleCreate.setShortName("VF Module Create (SO operation)"); + elementVfModuleCreate.setType("string"); + elementVfModuleCreate.setDescription("SO operation"); + operationDictionary.addDictionaryElements(elementVfModuleCreate); + + DictionaryElement elementVfModuleDelete = new DictionaryElement(); + elementVfModuleDelete.setName("VF Module Delete"); + elementVfModuleDelete.setShortName("VF Module Delete (SO operation)"); + elementVfModuleDelete.setType("string"); + elementVfModuleDelete.setDescription("SO operation"); + operationDictionary.addDictionaryElements(elementVfModuleDelete); + + DictionaryElement elementReroute = new DictionaryElement(); + elementReroute.setName("Reroute"); + elementReroute.setShortName("Reroute (SDNC operation)"); + elementReroute.setType("string"); + elementReroute.setDescription("SDNC operation"); + operationDictionary.addDictionaryElements(elementReroute); + + DictionaryElement elementBandwidthOnDemand = new DictionaryElement(); + elementBandwidthOnDemand.setName("BandwidthOnDemand"); + elementBandwidthOnDemand.setShortName("BandwidthOnDemand (SDNC operation)"); + elementBandwidthOnDemand.setType("string"); + elementBandwidthOnDemand.setDescription("SDNC operation"); + operationDictionary.addDictionaryElements(elementBandwidthOnDemand); + + dictionaryService.saveOrUpdateDictionary(operationDictionary); + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java new file mode 100644 index 000000000..cfd5f990f --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/DefaultUserConfiguration.java @@ -0,0 +1,138 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.config; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.IOException; +import org.onap.clamp.authorization.CldsUser; +import org.onap.clamp.clds.exception.CldsConfigException; +import org.onap.clamp.clds.exception.CldsUsersException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * This class is used to enable the HTTP authentication to login. It requires a + * specific JSON file containing the user definition + * (classpath:clds/clds-users.json). + */ +@Configuration +@EnableWebSecurity +@Profile("clamp-default-user") +public class DefaultUserConfiguration extends WebSecurityConfigurerAdapter { + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DefaultUserConfiguration.class); + + private static final String SETUP_WEB_USERS_EXCEPTION_MSG = "Exception occurred during the " + + " setup of the Web users in memory"; + @Autowired + private ClampProperties refProp; + @Value("${clamp.config.security.permission.type.cl:permission-type-cl}") + private String cldsPersmissionTypeCl; + @Value("${CLDS_PERMISSION_INSTANCE:dev}") + private String cldsPermissionInstance; + @Value("${clamp.config.security.encoder:bcrypt}") + private String cldsEncoderMethod; + @Value("${clamp.config.security.encoder.bcrypt.strength:10}") + private Integer cldsBcryptEncoderStrength; + + /** + * This method configures on which URL the authorization will be enabled. + */ + @Override + protected void configure(HttpSecurity http) { + try { + http.csrf().disable().httpBasic().and().authorizeRequests().antMatchers("/restservices/clds/v1/user/**") + .authenticated().anyRequest().permitAll().and().sessionManagement() + .maximumSessions(1); + + } catch (Exception e) { + logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e); + throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e); + } + } + + /** + * This method is called by the framework and is used to load all the users + * defined in cldsUsersFile variable (this file path can be configured in the + * application.properties). + * + * @param auth authentication manager builder + */ + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) { + // configure algorithm used for password hashing + final PasswordEncoder passwordEncoder = getPasswordEncoder(); + + try { + CldsUser[] usersList = loadUsers(); + // no users defined + if (null == usersList) { + logger.warn("No users defined. Users should be defined under clds-users.json"); + return; + } + for (CldsUser user : usersList) { + auth.inMemoryAuthentication().withUser(user.getUser()).password(user.getPassword()) + .authorities(user.getPermissionsString()).and().passwordEncoder(passwordEncoder); + } + } catch (Exception e) { + logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e); + throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e); + } + } + + /** + * This method loads physically the JSON file and convert it to an Array of + * CldsUser. + * + * @return The array of CldsUser + * @throws IOException In case of the file is not found + */ + private CldsUser[] loadUsers() throws IOException { + logger.info("Load from clds-users.properties"); + return CldsUserJsonDecoder.decodeJson(refProp.getFileContent("files.cldsUsers")); + } + + /** + * This methods returns the chosen encoder for password hashing. + */ + private PasswordEncoder getPasswordEncoder() { + if ("bcrypt".equals(cldsEncoderMethod)) { + return new BCryptPasswordEncoder(cldsBcryptEncoderStrength); + } else { + throw new CldsConfigException( + "Invalid clamp.config.security.encoder value. 'bcrypt' is the only option at this time."); + } + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/config/SslConfig.java b/src/main/java/org/onap/clamp/clds/config/SslConfig.java new file mode 100644 index 000000000..6345f4b56 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/SslConfig.java @@ -0,0 +1,93 @@ +/*- + * ============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.clds.config; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.util.PassDecoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.SslStoreProvider; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; + +@Configuration +@Profile("clamp-ssl-config") +public class SslConfig { + @Autowired + private Environment env; + + @Bean + WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer(ServerProperties serverProperties, + ResourceLoader resourceLoader) { + return (tomcat) -> tomcat.setSslStoreProvider(new SslStoreProvider() { + @Override + public KeyStore getKeyStore() throws KeyStoreException, + NoSuchAlgorithmException, CertificateException, IOException { + KeyStore keystore = KeyStore.getInstance(env.getProperty("server.ssl.key-store-type")); + String password = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"), + env.getProperty("clamp.config.keyFile")); + keystore.load(ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.key-store")), + password.toCharArray()); + return keystore; + } + + @Override + public KeyStore getTrustStore() throws KeyStoreException, + NoSuchAlgorithmException, CertificateException, IOException { + KeyStore truststore = KeyStore.getInstance("JKS"); + String password = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"), + env.getProperty("clamp.config.keyFile")); + truststore.load( + ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.trust-store")), + password.toCharArray()); + return truststore; + } + }); + } + + @Bean + WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatSslCustomizer(ServerProperties serverProperties, + ResourceLoader resourceLoader) { + return (tomcat) -> tomcat.setSsl(new Ssl() { + @Override + public String getKeyPassword() { + String password = PassDecoder.decode(env.getProperty("server.ssl.key-password"), + env.getProperty("clamp.config.keyFile")); + return password; + } + }); + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java b/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java new file mode 100644 index 000000000..7480beb8d --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/SystemPropertiesLoader.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.config; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.util.Properties; + +import javax.annotation.Resource; + +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + +@Component +public class SystemPropertiesLoader implements ApplicationListener<ContextRefreshedEvent> { + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(SystemPropertiesLoader.class); + + @Resource(name = "mapper") + private Properties myTranslator; + + @Override + public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { + logger.info("Loading additional JVM properties:" + myTranslator.toString()); + System.getProperties().putAll(myTranslator); + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java new file mode 100644 index 000000000..ad2751bb8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.config.sdc; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.PostConstruct; + +import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException; +import org.onap.clamp.clds.util.JsonUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.Resource; + +/** + * This class maps the SDC config JSON file. This JSON can have multiple + * sdc-controller config. So the json is loaded in a static way and the instance + * must specify the controller name that it represents. + */ +public class SdcControllersConfiguration { + + private static final String CONTROLLER_SUBTREE_KEY = "sdc-connections"; + @Autowired + protected ApplicationContext appContext; + /** + * The file name that will be loaded by Spring. + */ + @Value("${clamp.config.files.sdcController:'classpath:/clds/sdc-controllers-config.json'}") + protected String sdcControllerFile; + /** + * The root of the JSON. + */ + private JsonObject jsonRootNode; + + /** + * Loads configuration from SDC controller config file. + * + * @throws IOException IO Exception + */ + @PostConstruct + public void loadConfiguration() throws IOException { + Resource resource = appContext.getResource(sdcControllerFile); + // Try to load json tree + jsonRootNode = JsonUtils.GSON.fromJson(new InputStreamReader( + resource.getInputStream(), StandardCharsets.UTF_8), + JsonObject.class); + } + + public SdcSingleControllerConfiguration getSdcSingleControllerConfiguration(String controllerName) { + return getAllDefinedControllers().get(controllerName); + } + + /** + * This method reads all Controllers configurations and returns them. + * + * @return A list of controller Names defined in the config + */ + public Map<String, SdcSingleControllerConfiguration> getAllDefinedControllers() { + Map<String, SdcSingleControllerConfiguration> result = new HashMap<>(); + if (jsonRootNode.get(CONTROLLER_SUBTREE_KEY) != null) { + jsonRootNode.get(CONTROLLER_SUBTREE_KEY).getAsJsonObject().entrySet().forEach( + entry -> result.put(entry.getKey(), + new SdcSingleControllerConfiguration(entry.getValue().getAsJsonObject(), entry.getKey()))); + } else { + throw new SdcParametersException( + CONTROLLER_SUBTREE_KEY + " key not found in the file: " + sdcControllerFile); + } + return result; + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java new file mode 100644 index 000000000..da90e6060 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java @@ -0,0 +1,290 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.config.sdc; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apache.commons.codec.DecoderException; +import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException; +import org.onap.clamp.clds.util.CryptoUtils; +import org.onap.sdc.api.consumer.IConfiguration; + +/** + * This class maps the SDC config JSON for one controller. + */ +public class SdcSingleControllerConfiguration implements IConfiguration { + + private static final EELFLogger logger = EELFManager.getInstance() + .getLogger(SdcSingleControllerConfiguration.class); + /** + * The sdc Controller name corresponding. + */ + private String sdcControllerName; + /** + * The root of the JSON. + */ + private JsonObject jsonRootNode; + // All keys that can be present in the JSON + public static final String CONSUMER_GROUP_ATTRIBUTE_NAME = "consumerGroup"; + public static final String CONSUMER_ID_ATTRIBUTE_NAME = "consumerId"; + public static final String ENVIRONMENT_NAME_ATTRIBUTE_NAME = "environmentName"; + public static final String SDC_KEY_ATTRIBUTE_NAME = "password"; + public static final String POLLING_INTERVAL_ATTRIBUTE_NAME = "pollingInterval"; + public static final String RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME = "relevantArtifactTypes"; + public static final String USER_ATTRIBUTE_NAME = "user"; + public static final String SDC_ADDRESS_ATTRIBUTE_NAME = "sdcAddress"; + public static final String POLLING_TIMEOUT_ATTRIBUTE_NAME = "pollingTimeout"; + public static final String ACTIVATE_SERVER_TLS_AUTH = "activateServerTLSAuth"; + public static final String KEY_STORE_KEY = "keyStorePassword"; + public static final String KEY_STORE_PATH = "keyStorePath"; + public static final String MESSAGE_BUS_ADDRESSES = "messageBusAddresses"; + private String errorMessageKeyNotFound; + /** + * Supported artifact types. + */ + public static final String HEAT = "HEAT"; + public static final String HEAT_ARTIFACT = "HEAT_ARTIFACT"; + public static final String HEAT_ENV = "HEAT_ENV"; + public static final String HEAT_NESTED = "HEAT_NESTED"; + public static final String HEAT_NET = "HEAT_NET"; + public static final String HEAT_VOL = "HEAT_VOL"; + public static final String OTHER = "OTHER"; + public static final String TOSCA_CSAR = "TOSCA_CSAR"; + public static final String VF_MODULES_METADATA = "VF_MODULES_METADATA"; + private static final String[] SUPPORTED_ARTIFACT_TYPES = { + TOSCA_CSAR, VF_MODULES_METADATA + }; + public static final List<String> SUPPORTED_ARTIFACT_TYPES_LIST = Collections + .unmodifiableList(Arrays.asList(SUPPORTED_ARTIFACT_TYPES)); + + /** + * This constructor builds a SdcSingleControllerConfiguration from the + * corresponding json. + * + * @param jsonNode + * The JSON node + * @param controllerName + * The controller name that must appear in the JSON + */ + public SdcSingleControllerConfiguration(JsonObject jsonNode, String controllerName) { + jsonRootNode = jsonNode; + setSdcControllerName(controllerName); + testAllRequiredParameters(); + } + + public String getSdcControllerName() { + return sdcControllerName; + } + + /** + * Sets SDC controller name. + * + * @param controllerName SDC controller name + */ + public void setSdcControllerName(String controllerName) { + this.sdcControllerName = controllerName; + errorMessageKeyNotFound = " parameter cannot be found in config file for controller name" + sdcControllerName; + testAllRequiredParameters(); + } + + private String getStringConfig(String key) { + if (jsonRootNode != null && jsonRootNode.get(key) != null) { + String config = jsonRootNode.get(key).getAsString(); + return config.isEmpty() ? null : config; + } + return null; + } + + private Integer getIntConfig(String key) { + if (jsonRootNode != null && jsonRootNode.get(key) != null) { + return jsonRootNode.get(key).getAsInt(); + } else { + return 0; + } + } + + private String getEncryptedStringConfig(String key) throws GeneralSecurityException, DecoderException { + if (jsonRootNode != null && jsonRootNode.get(key) != null) { + return jsonRootNode.get(key).getAsString().isEmpty() ? null + : CryptoUtils.decrypt(jsonRootNode.get(key).getAsString()); + } + return null; + } + + @Override + public java.lang.Boolean isUseHttpsWithDmaap() { + return false; + } + + @Override + public String getConsumerGroup() { + if (jsonRootNode != null && jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) != null) { + String config = jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString(); + return "NULL".equals(config) || config.isEmpty() ? null : config; + } + return null; + } + + @Override + public String getConsumerID() { + return getStringConfig(CONSUMER_ID_ATTRIBUTE_NAME); + } + + @Override + public String getEnvironmentName() { + return getStringConfig(ENVIRONMENT_NAME_ATTRIBUTE_NAME); + } + + @Override + public String getPassword() { + try { + return getEncryptedStringConfig(SDC_KEY_ATTRIBUTE_NAME); + } catch (GeneralSecurityException | DecoderException e) { + logger.error("Unable to decrypt the SDC password", e); + return null; + } + } + + @Override + public int getPollingInterval() { + return getIntConfig(POLLING_INTERVAL_ATTRIBUTE_NAME); + } + + @Override + public List<String> getRelevantArtifactTypes() { + // DO not return the Static List SUPPORTED_ARTIFACT_TYPES_LIST because + // the ASDC Client could try to modify it !!! + return Arrays.asList(SUPPORTED_ARTIFACT_TYPES); + } + + @Override + public String getUser() { + return getStringConfig(USER_ATTRIBUTE_NAME); + } + + @Override + public String getAsdcAddress() { + return getStringConfig(SDC_ADDRESS_ATTRIBUTE_NAME); + } + + @Override + public int getPollingTimeout() { + return getIntConfig(POLLING_TIMEOUT_ATTRIBUTE_NAME); + } + + @Override + public boolean activateServerTLSAuth() { + if (jsonRootNode != null && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH) != null + && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).isJsonPrimitive()) { + return jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).getAsBoolean(); + } else { + return false; + } + } + + @Override + public String getKeyStorePassword() { + try { + return getEncryptedStringConfig(KEY_STORE_KEY); + } catch (GeneralSecurityException | DecoderException e) { + logger.error("Unable to decrypt the SDC password", e); + return null; + } + } + + @Override + public String getKeyStorePath() { + return getStringConfig(KEY_STORE_PATH); + } + + /** + * This method can be used to validate all required parameters are well + * there. + */ + public void testAllRequiredParameters() { + // Special case for this attribute that can be null from + // getConsumerGroup + if (jsonRootNode == null) { + throw new SdcParametersException("Json is null for controller " + this.getSdcControllerName()); + } + if (this.getConsumerGroup() == null && (jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) == null + || !"NULL".equals(jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString()))) { + throw new SdcParametersException(CONSUMER_GROUP_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getConsumerID() == null || this.getConsumerID().isEmpty()) { + throw new SdcParametersException(CONSUMER_ID_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getEnvironmentName() == null || this.getEnvironmentName().isEmpty()) { + throw new SdcParametersException(ENVIRONMENT_NAME_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getAsdcAddress() == null || this.getAsdcAddress().isEmpty()) { + throw new SdcParametersException(SDC_ADDRESS_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getMsgBusAddress() == null || this.getMsgBusAddress().isEmpty()) { + throw new SdcParametersException(MESSAGE_BUS_ADDRESSES + errorMessageKeyNotFound); + } + if (this.getPassword() == null || this.getPassword().isEmpty()) { + throw new SdcParametersException(SDC_KEY_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getPollingInterval() == 0) { + throw new SdcParametersException(POLLING_INTERVAL_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getPollingTimeout() == 0) { + throw new SdcParametersException(POLLING_TIMEOUT_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getRelevantArtifactTypes() == null || this.getRelevantArtifactTypes().isEmpty()) { + throw new SdcParametersException(RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + if (this.getUser() == null || this.getUser().isEmpty()) { + throw new SdcParametersException(USER_ATTRIBUTE_NAME + errorMessageKeyNotFound); + } + } + + /** + * The flag allows the client to receive metadata for all resources of the + * service regardless of the artifacts associated to them. Setting the flag + * to false will preserve legacy behavior. + */ + @Override + public boolean isFilterInEmptyResources() { + return false; + } + + @Override + public List<String> getMsgBusAddress() { + List<String> addressesList = new ArrayList<>(); + if (jsonRootNode != null && jsonRootNode.get(MESSAGE_BUS_ADDRESSES) != null) { + jsonRootNode.get(MESSAGE_BUS_ADDRESSES).getAsJsonArray().forEach(k -> addressesList.add(k.getAsString())); + return addressesList; + } else { + return addressesList; + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java b/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java new file mode 100644 index 000000000..14c08c800 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/spring/CldsConfiguration.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.config.spring; + +import org.onap.clamp.clds.config.ClampProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.PropertiesFactoryBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("clamp-default") +public class CldsConfiguration { + + @Autowired + private ApplicationContext appContext; + @Autowired + private ClampProperties refProp; + + + /** + * This loads the file system.properties. + * + * @return The PropertiesFactoryBean + */ + @Bean(name = "mapper") + public PropertiesFactoryBean mapper() { + PropertiesFactoryBean bean = new PropertiesFactoryBean(); + bean.setLocation(appContext.getResource(refProp.getStringValue("files.systemProperties"))); + return bean; + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java b/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java new file mode 100644 index 000000000..eca45d66f --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/config/spring/SdcControllerConfiguration.java @@ -0,0 +1,113 @@ +/*- + * ============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.clds.config.spring; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.config.sdc.SdcControllersConfiguration; +import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException; +import org.onap.clamp.clds.sdc.controller.SdcSingleController; +import org.onap.clamp.clds.sdc.controller.SdcSingleControllerStatus; +import org.onap.clamp.loop.CsarInstaller; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +@Profile("clamp-sdc-controller") +public class SdcControllerConfiguration { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcControllerConfiguration.class); + private List<SdcSingleController> sdcControllersList = new ArrayList<>(); + private final ClampProperties clampProp; + private final CsarInstaller csarInstaller; + + @Autowired + public SdcControllerConfiguration(ClampProperties clampProp, + @Qualifier("csarInstaller") CsarInstaller csarInstaller) { + this.clampProp = clampProp; + this.csarInstaller = csarInstaller; + } + + /** + * Loads SDC controller configuration. + */ + @PostConstruct + public void loadSdcControllers() { + SdcControllersConfiguration sdcControllersConfig = getSdcControllersConfiguration(); + sdcControllersConfig.getAllDefinedControllers().forEach((key, value) -> { + logger.info("Creating controller instance:" + key); + SdcSingleController sdcController = new SdcSingleController(clampProp, csarInstaller, value, null); + sdcControllersList.add(sdcController); + }); + } + + /** + * Checks whether all SDC controllers defined are up and running. + */ + @Scheduled(fixedRate = 120000) + public void checkAllSdcControllers() { + logger.info("Checking that all SDC Controllers defined are up and running"); + for (SdcSingleController controller : sdcControllersList) { + try { + if (SdcSingleControllerStatus.STOPPED.equals(controller.getControllerStatus())) { + controller.initSdc(); + } + } catch (SdcControllerException e) { + logger.error("Exception caught when booting sdc controller", e); + } + } + logger.info("SDC Controllers check completed"); + } + + /** + * Closes all SDC Controller and the SDC Client. + */ + @PreDestroy + public void killSdcControllers() { + sdcControllersList.forEach(e -> { + try { + e.closeSdc(); + } catch (SdcControllerException e1) { + logger.error("Exception caught when stopping sdc controller", e1); + } + }); + } + + @Bean(name = "sdcControllersConfiguration") + public SdcControllersConfiguration getSdcControllersConfiguration() { + return new SdcControllersConfiguration(); + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java b/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.java new file mode 100644 index 000000000..93d98151a --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/CldsConfigException.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.clds.exception; + +/** + * New exception to CldsUser errors. + * + */ +public class CldsConfigException extends RuntimeException { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 5958873136187918505L; + + /** + * This constructor can be used to create a new CldsConfigException. + * + * @param message + * A string message detailing the problem + * @param ex + * The exception sent by the code + */ + public CldsConfigException(String message, Throwable ex) { + super(message, ex); + } + + /** + * This constructor can be used to create a new CldsConfigException. 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 CldsConfigException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java b/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.java new file mode 100644 index 000000000..270bfa1e2 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/CldsUsersException.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.clds.exception; + +/** + * New exception to CldsUser errors. + * + */ +public class CldsUsersException extends RuntimeException { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 933535057227505342L; + + /** + * This constructor can be used to create a new CldsUsersException. + * + * @param message + * A string message detailing the problem + * @param ex + * The exception sent by the code + */ + public CldsUsersException(String message, Throwable ex) { + super(message, ex); + } + + /** + * 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 CldsUsersException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java b/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java new file mode 100644 index 000000000..1bdf18e7e --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/NotAuthorizedException.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception; + +/** + * New exception to request errors. + * + */ +public class NotAuthorizedException extends RuntimeException { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = -5738167530541646123L; + + /** + * This constructor can be used to create a new CldsConfigException. + * + * @param message + * A string message detailing the problem + * @param ex + * The exception sent by the code + */ + public NotAuthorizedException(String message, Throwable ex) { + super(message, ex); + } + + /** + * This constructor can be used to create a new CldsConfigException. 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 NotAuthorizedException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java b/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java new file mode 100644 index 000000000..73ce31f89 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/cds/CdsParametersException.java @@ -0,0 +1,53 @@ +/*- + * ============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.exception.cds; + +/** + * Exception while parsing CDS response. + */ +public class CdsParametersException extends RuntimeException { + + /** + * serialization id. + */ + private static final long serialVersionUID = 8425657297510362736L; + + /** + * This constructor can be used to create a new CdsParametersException. + * + * @param message The message to dump + */ + public CdsParametersException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new CdsParametersException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public CdsParametersException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java b/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.java new file mode 100644 index 000000000..e733da53d --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/dcae/DcaeDeploymentException.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.clds.exception.dcae; + +/** + * New exception to capture DCAE communication errors. + * + */ +public class DcaeDeploymentException extends RuntimeException { + + /** + * Generated ID. + */ + private static final long serialVersionUID = 8452294782552680243L; + + /** + * This constructor can be used to create a new DcaeDeploymentException. + * + * @param message + * A string message detailing the problem + * @param ex + * The exception sent by the code + */ + public DcaeDeploymentException(String message, Throwable ex) { + super(message, ex); + } + + /** + * This constructor can be used to create a new DcaeDeploymentException. 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 DcaeDeploymentException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java new file mode 100644 index 000000000..7257fd8a0 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/BlueprintParserException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.exception.sdc.controller; + +/** + * Exception during blueprint parsing. + */ +public class BlueprintParserException extends Exception { + + /** + * Serial ID. + */ + private static final long serialVersionUID = -3044162346353623199L; + + /** + * This constructor can be used to create a new SdcDownloadException. + * + * @param message The message to dump + */ + public BlueprintParserException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new SdcDownloadException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public BlueprintParserException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java new file mode 100644 index 000000000..c3ebde1f8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception.sdc.controller; + +/** + * Exception during Csar operations. + */ +public class CsarHandlerException extends Exception { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = -7628640776124409155L; + + /** + * This constructor can be used to create a new CsarHandlerException. + * + * @param message The message to dump + */ + public CsarHandlerException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new CsarHandlerException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public CsarHandlerException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java new file mode 100644 index 000000000..523766af1 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception.sdc.controller; + +/** + * Exception during SDC artifact installation. + */ +public class SdcArtifactInstallerException extends Exception { + + /** + * serialization id. + */ + private static final long serialVersionUID = 4095937499475915021L; + + /** + * This constructor can be used to create a new SdcArtifactInstallerException. + * + * @param message The message to dump + */ + public SdcArtifactInstallerException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new SdcArtifactInstallerException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public SdcArtifactInstallerException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java new file mode 100644 index 000000000..d73001d78 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcControllerException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception.sdc.controller; + +/** + * Exception of the SDC controller. + */ +public class SdcControllerException extends Exception { + + /** + * serialization id. + */ + private static final long serialVersionUID = -4236006447255525130L; + + /** + * This constructor can be used to create a new SdcControllerException. + * + * @param message The message to dump + */ + public SdcControllerException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new SdcControllerException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public SdcControllerException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java new file mode 100644 index 000000000..6cd3fb88d --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcDownloadException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception.sdc.controller; + +/** + * Exception during download from SDC. + */ +public class SdcDownloadException extends Exception { + + /** + * serialization id. + */ + private static final long serialVersionUID = -5276848693231134901L; + + /** + * This constructor can be used to create a new SdcDownloadException. + * + * @param message The message to dump + */ + public SdcDownloadException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new SdcDownloadException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public SdcDownloadException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java new file mode 100644 index 000000000..bfe63cbfb --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/SdcParametersException.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.exception.sdc.controller; + +/** + * Exception of the SDC controller. + */ +public class SdcParametersException extends RuntimeException { + + /** + * serialization id. + */ + private static final long serialVersionUID = 8425657297510362736L; + + /** + * This constructor can be used to create a new SdcParametersException. + * + * @param message The message to dump + */ + public SdcParametersException(final String message) { + super(message); + } + + /** + * This constructor can be used to create a new SdcParametersException. + * + * @param message The message to dump + * @param cause The Throwable cause object + */ + public SdcParametersException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java b/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java new file mode 100644 index 000000000..c673f544a --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/filter/ClampCadiFilter.java @@ -0,0 +1,190 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.filter; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.StandardCopyOption; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; + +public class ClampCadiFilter extends CadiFilter { + private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampCadiFilter.class); + + @Autowired + private ApplicationContext appContext; + + @Value("${server.ssl.key-store:#{null}}") + private String keyStore; + + @Value("${server.ssl.key-store-password:#{null}}") + private String keyStorePass; + + @Value("${server.ssl.trust-store:#{null}}") + private String trustStore; + + @Value("${server.ssl.trust-store-password:#{null}}") + private String trustStorePass; + + @Value("${server.ssl.key-alias:clamp@clamp.onap.org}") + private String alias; + + @Value("${clamp.config.keyFile:#{null}}") + private String keyFile; + + @Value("${clamp.config.cadi.cadiLoglevel:#{null}}") + private String cadiLoglevel; + + @Value("${clamp.config.cadi.cadiLatitude:#{null}}") + private String cadiLatitude; + + @Value("${clamp.config.cadi.cadiLongitude:#{null}}") + private String cadiLongitude; + + @Value("${clamp.config.cadi.aafLocateUrl:#{null}}") + private String aafLocateUrl; + + @Value("${clamp.config.cadi.oauthTokenUrl:#{null}}") + private String oauthTokenUrl; + + @Value("${clamp.config.cadi.oauthIntrospectUrl:#{null}}") + private String oauthIntrospectUrl; + + @Value("${clamp.config.cadi.aafEnv:#{null}}") + private String aafEnv; + + @Value("${clamp.config.cadi.aafUrl:#{null}}") + private String aafUrl; + + @Value("${clamp.config.cadi.cadiX509Issuers:#{null}}") + private String cadiX509Issuers; + + @Value("${clamp.config.caCerts:#{null}}") + private String caCertsPath; + + private void checkIfNullProperty(String key, String value) { + /* + * When value is null, so not defined in application.properties set nothing in + * System properties + */ + if (value != null) { + /* + * Ensure that any properties already defined in System.prop by JVM params won't + * be overwritten by Spring application.properties values + */ + System.setProperty(key, System.getProperty(key, value)); + } + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // set some properties in System so that Cadi filter will find its config + // The JVM values set will always overwrite the Spring ones. + checkIfNullProperty(Config.CADI_KEYFILE, convertSpringToPath(keyFile)); + checkIfNullProperty(Config.CADI_LOGLEVEL, cadiLoglevel); + checkIfNullProperty(Config.CADI_LATITUDE, cadiLatitude); + checkIfNullProperty(Config.CADI_LONGITUDE, cadiLongitude); + + checkIfNullProperty(Config.AAF_LOCATE_URL, aafLocateUrl); + checkIfNullProperty(Config.AAF_OAUTH2_TOKEN_URL, oauthTokenUrl); + checkIfNullProperty(Config.AAF_OAUTH2_INTROSPECT_URL, oauthIntrospectUrl); + + checkIfNullProperty(Config.AAF_ENV, aafEnv); + checkIfNullProperty(Config.AAF_URL, aafUrl); + checkIfNullProperty(Config.CADI_X509_ISSUERS, cadiX509Issuers); + checkIfNullProperty(Config.CADI_KEYSTORE, convertSpringToPath(keyStore)); + checkIfNullProperty(Config.CADI_TRUSTSTORE, convertSpringToPath(trustStore)); + checkIfNullProperty(Config.CADI_ALIAS, alias); + checkIfNullProperty(Config.CADI_KEYSTORE_PASSWORD, keyStorePass); + checkIfNullProperty(Config.CADI_TRUSTSTORE_PASSWORD, trustStorePass); + + super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + try { + String certHeader = ((HttpServletRequest) request).getHeader("X-SSL-Cert"); + if (certHeader != null) { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate) certificateFactory + .generateCertificate(new ByteArrayInputStream( + URLDecoder.decode(certHeader, StandardCharsets.UTF_8.toString()).getBytes())); + X509Certificate caCert = (X509Certificate) certificateFactory + .generateCertificate(new ByteArrayInputStream( + ResourceFileUtils.getResourceAsString(this.caCertsPath).getBytes())); + + X509Certificate[] certifArray = ((X509Certificate[]) request + .getAttribute("javax.servlet.request.X509Certificate")); + if (certifArray == null) { + certifArray = new X509Certificate[] { cert, caCert }; + request.setAttribute("javax.servlet.request.X509Certificate", certifArray); + } else { + certifArray[0] = cert; + certifArray[1] = caCert; + } + } + + } catch (CertificateException e) { + logger.error("Unable to inject the X.509 certificate", e); + } + super.doFilter(request, response, chain); + } + + private String convertSpringToPath(String fileName) { + try (InputStream ioFile = appContext.getResource(fileName).getInputStream()) { + if (!fileName.contains("file:")) { + File targetFile = new File(appContext.getResource(fileName).getFilename()); + java.nio.file.Files.copy(ioFile, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + return targetFile.getPath(); + } else { + return appContext.getResource(fileName).getFile().getPath(); + } + } catch (IOException e) { + logger.error("Unable to open and copy the file: " + fileName, e); + return null; + } + + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/ClampInformation.java b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java new file mode 100644 index 000000000..d73e94204 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/ClampInformation.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2020 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.clds.model; + +import com.google.gson.annotations.Expose; +import java.util.ArrayList; +import java.util.List; +import org.onap.clamp.clds.util.ClampVersioning; + +public class ClampInformation { + @Expose + private String userName; + @Expose + private String cldsVersion = ClampVersioning.getCldsVersionFromProps(); + @Expose + List<String> allPermissions = new ArrayList<>(); + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getCldsVersion() { + return cldsVersion; + } + + public void setCldsVersion(String cldsVersion) { + this.cldsVersion = cldsVersion; + } + + public List<String> getAllPermissions() { + return allPermissions; + } + + public void setAllPermissions(List<String> allPermissions) { + this.allPermissions = allPermissions; + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java b/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java new file mode 100644 index 000000000..651997cd3 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/CldsHealthCheck.java @@ -0,0 +1,60 @@ +/*- + * ============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.clds.model; + +import com.google.gson.annotations.Expose; + +public class CldsHealthCheck { + @Expose + private String healthCheckComponent; + @Expose + private String healthCheckStatus; + @Expose + private String description; + + public String getHealthCheckComponent() { + return healthCheckComponent; + } + + public void setHealthCheckComponent(String healthCheckComponent) { + this.healthCheckComponent = healthCheckComponent; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getHealthCheckStatus() { + return healthCheckStatus; + } + + public void setHealthCheckStatus(String healthCheckStatus) { + this.healthCheckStatus = healthCheckStatus; + } + +} 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 000000000..66025c479 --- /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<String> workflows = new LinkedList<String>(); + + 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<String> getWorkflows() { + return workflows; + } + + public void setWorkflows(List<String> workflows) { + this.workflows = workflows; + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java new file mode 100644 index 000000000..fc2ca5caa --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryCache.java @@ -0,0 +1,62 @@ +/*- + * ============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.clds.model.dcae; + +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class stores the multiple DcaeInventoryResponse coming back from DCAE. + * The structure is a map of list indexed by asdcServiceId. The list is sorted + * by asdcResourceId. Therefore it's possible to retrieve all the loops defined + * in the DCAE inventory and created by DCAE Mod. + */ +public class DcaeInventoryCache { + + private static Map<String, Set<DcaeInventoryResponse>> blueprintsMap = new ConcurrentHashMap<>(); + + /** + * Add Dcae inventory response. + * + * @param inventoryResponse the Dcae inventory response + */ + public void addDcaeInventoryResponse(DcaeInventoryResponse inventoryResponse) { + Set<DcaeInventoryResponse> responsesSet = blueprintsMap.get(inventoryResponse.getAsdcServiceId()); + if (responsesSet == null) { + responsesSet = new TreeSet<>(); + blueprintsMap.put(inventoryResponse.getAsdcServiceId(), responsesSet); + } + responsesSet.add(inventoryResponse); + } + + public Set<String> getAllLoopIds() { + return this.blueprintsMap.keySet(); + } + + public Set<DcaeInventoryResponse> getAllBlueprintsPerLoopId(String loopId) { + return blueprintsMap.getOrDefault(loopId, new TreeSet<>()); + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java new file mode 100644 index 000000000..67bd026d0 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponse.java @@ -0,0 +1,102 @@ + +/*- + * ============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.clds.model.dcae; + +import com.google.gson.annotations.Expose; + +/** + * This class maps the DCAE inventory answer to a nice pojo. + */ +public class DcaeInventoryResponse implements Comparable<DcaeInventoryResponse> { + + @Expose + private String typeName; + + @Expose + private String typeId; + + @Expose + private String blueprintTemplate; + + /** + * This field will be used to know all blueprints associated a loop. + */ + @Expose + private String asdcServiceId; + + /** + * This field will be used to know to order of each blueprint microservice in a + * loop. + */ + @Expose + private String asdcResourceId; + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public String getTypeId() { + return typeId; + } + + public void setTypeId(String typeId) { + this.typeId = typeId; + } + + public String getBlueprintTemplate() { + return blueprintTemplate; + } + + public void setBlueprintTemplate(String blueprintTemplate) { + this.blueprintTemplate = blueprintTemplate; + } + + public String getAsdcServiceId() { + return asdcServiceId; + } + + public void setAsdcServiceId(String asdcServiceId) { + this.asdcServiceId = asdcServiceId; + } + + public String getAsdcResourceId() { + return asdcResourceId; + } + + public void setAsdcResourceId(String asdcResourceId) { + this.asdcResourceId = asdcResourceId; + } + + @Override + public int compareTo(DcaeInventoryResponse otherResponse) { + int thisResourceId = Integer.parseInt(this.asdcResourceId); + int otherResourceId = Integer.parseInt(otherResponse.getAsdcResourceId()); + return (thisResourceId < otherResourceId ? -1 : (thisResourceId > otherResourceId ? 1 : 0)); + } +} diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java new file mode 100644 index 000000000..368e1b8e6 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeLinks.java @@ -0,0 +1,60 @@ +/*- + * ============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.clds.model.dcae; + +import com.google.gson.annotations.Expose; + +public class DcaeLinks { + @Expose + private String self; + @Expose + private String status; + @Expose + private String uninstall; + + public String getSelf() { + return self; + } + + public void setSelf(String self) { + this.self = self; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getUninstall() { + return uninstall; + } + + public void setUninstall(String uninstall) { + this.uninstall = uninstall; + } + +} diff --git a/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java new file mode 100644 index 000000000..aee7d0613 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/model/dcae/DcaeOperationStatusResponse.java @@ -0,0 +1,88 @@ +/*- + * ============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.clds.model.dcae; + +import com.google.gson.annotations.Expose; + +/** + * This class maps the DCAE deployment handler response to a nice pojo. + */ +public class DcaeOperationStatusResponse { + + @Expose + private String operationType; + + @Expose + private String status; + + @Expose + private String requestId; + + @Expose + private String error; + + @Expose + private DcaeLinks links; + + public String getOperationType() { + return operationType; + } + + public void setOperationType(String operationType) { + this.operationType = operationType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public DcaeLinks getLinks() { + return links; + } + + public void setLinks(DcaeLinks links) { + this.links = links; + } + +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java b/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java new file mode 100644 index 000000000..c80441fa6 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/DistributionStatusMessage.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.sdc.controller; + +import org.onap.sdc.api.consumer.IDistributionStatusMessage; +import org.onap.sdc.utils.DistributionStatusEnum; + +public class DistributionStatusMessage implements IDistributionStatusMessage { + + private String artifactUrl; + private String consumerId; + private String distributionId; + private DistributionStatusEnum distributionStatus; + private long timestamp; + + /** + * Distribution status message constructor. + * + * @param artifactUrl + * Url of specific SDC artifact(resource) + * @param consumerId + * Unique ID of SDC component instance + * @param distributionId + * Distribution ID published in the distribution notification. + * @param distributionStatusEnum + * Status to send in the message + * @param timestamp + * Timestamp of the message + */ + public DistributionStatusMessage(final String artifactUrl, final String consumerId, final String distributionId, + final DistributionStatusEnum distributionStatusEnum, final long timestamp) { + this.artifactUrl = artifactUrl; + this.consumerId = consumerId; + this.distributionId = distributionId; + this.distributionStatus = distributionStatusEnum; + this.timestamp = timestamp; + } + + @Override + public String getArtifactURL() { + return artifactUrl; + } + + @Override + public String getConsumerID() { + return consumerId; + } + + @Override + public String getDistributionID() { + return distributionId; + } + + @Override + public DistributionStatusEnum getStatus() { + return distributionStatus; + } + + @Override + public long getTimestamp() { + return timestamp; + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java new file mode 100644 index 000000000..f9b43abb7 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java @@ -0,0 +1,435 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018-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============================================ + * Modifications copyright (c) 2018 Nokia + * =================================================================== + * + */ + +package org.onap.clamp.clds.sdc.controller; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.util.Date; +import java.util.Map.Entry; +import java.util.concurrent.ThreadLocalRandom; + +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration; +import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException; +import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.loop.CsarInstaller; +import org.onap.sdc.api.IDistributionClient; +import org.onap.sdc.api.consumer.IComponentDoneStatusMessage; +import org.onap.sdc.api.consumer.IDistributionStatusMessage; +import org.onap.sdc.api.consumer.INotificationCallback; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.results.IDistributionClientDownloadResult; +import org.onap.sdc.api.results.IDistributionClientResult; +import org.onap.sdc.impl.DistributionClientFactory; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.sdc.utils.DistributionActionResultEnum; +import org.onap.sdc.utils.DistributionStatusEnum; + +/** + * This class handles one sdc controller defined in the config. + */ +public class SdcSingleController { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class); + private boolean isSdcClientAutoManaged = false; + private CsarInstaller csarInstaller; + private ClampProperties refProp; + /** + * The constant CONFIG_SDC_FOLDER. + */ + public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder"; + private int nbOfNotificationsOngoing = 0; + private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED; + private SdcSingleControllerConfiguration sdcConfig; + private IDistributionClient distributionClient; + + /** + * Inner class for Notification callback. + */ + private final class SdcNotificationCallBack implements INotificationCallback { + + private SdcSingleController sdcController; + + /** + * Instantiates a new Sdc notification call back. + * + * @param controller the controller + */ + SdcNotificationCallBack(SdcSingleController controller) { + sdcController = controller; + } + + /** + * This method can be called multiple times at the same moment. The controller + * must be thread safe ! + */ + @Override + public void activateCallback(INotificationData notificationData) { + Date startTime = new Date(); + logger.info("Receive a callback notification in SDC, nb of resources: " + + notificationData.getResources().size()); + sdcController.treatNotification(notificationData); + LoggingUtils.setTimeContext(startTime, new Date()); + LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully", + this.getClass().getName()); + } + } + + /** + * Gets nb of notifications ongoing. + * + * @return the nb of notifications ongoing + */ + public int getNbOfNotificationsOngoing() { + return nbOfNotificationsOngoing; + } + + private void changeControllerStatusIdle() { + if (this.nbOfNotificationsOngoing > 1) { + --this.nbOfNotificationsOngoing; + } else { + this.nbOfNotificationsOngoing = 0; + this.controllerStatus = SdcSingleControllerStatus.IDLE; + } + } + + /** + * Change controller status. + * + * @param newControllerStatus the new controller status + */ + protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) { + switch (newControllerStatus) { + case BUSY: + ++this.nbOfNotificationsOngoing; + this.controllerStatus = newControllerStatus; + break; + case IDLE: + this.changeControllerStatusIdle(); + break; + default: + this.controllerStatus = newControllerStatus; + break; + } + } + + /** + * Gets controller status. + * + * @return the controller status + */ + public final synchronized SdcSingleControllerStatus getControllerStatus() { + return this.controllerStatus; + } + + /** + * Instantiates a new Sdc single controller. + * + * @param clampProp the clamp prop + * @param csarInstaller the csar installer + * @param sdcSingleConfig the sdc single config + * @param distributionClient the distribution client + */ + public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller, + SdcSingleControllerConfiguration sdcSingleConfig, + IDistributionClient distributionClient) { + this.distributionClient = distributionClient; + isSdcClientAutoManaged = (distributionClient == null); + this.sdcConfig = sdcSingleConfig; + this.refProp = clampProp; + this.csarInstaller = csarInstaller; + } + + /** + * This method initializes the SDC Controller and the SDC Client. + * + * @throws SdcControllerException It throws an exception if the SDC Client + * cannot be instantiated or if an init attempt + * is done when already initialized + */ + public void initSdc() throws SdcControllerException { + logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName()); + if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) { + throw new SdcControllerException("The controller is already initialized, call the closeSDC method first"); + } + if (distributionClient == null) { + distributionClient = DistributionClientFactory.createDistributionClient(); + } + IDistributionClientResult result = distributionClient.init(sdcConfig, new SdcNotificationCallBack(this)); + if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { + logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult()); + this.changeControllerStatus(SdcSingleControllerStatus.STOPPED); + throw new SdcControllerException("Initialization of the SDC Controller failed with reason: " + + result.getDistributionMessageResult()); + } + logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName()); + logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName()); + result = this.distributionClient.start(); + if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) { + logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult()); + this.changeControllerStatus(SdcSingleControllerStatus.STOPPED); + throw new SdcControllerException( + "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult()); + } + logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName()); + this.changeControllerStatus(SdcSingleControllerStatus.IDLE); + } + + /** + * This method closes the SDC Controller and the SDC Client. + * + * @throws SdcControllerException It throws an exception if the SDC Client + * cannot be closed because it's currently BUSY + * in processing notifications. + */ + public void closeSdc() throws SdcControllerException { + if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) { + throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state"); + } + if (this.distributionClient != null) { + this.distributionClient.stop(); + // If auto managed we can set it to Null, SdcController controls it. + // In the other case the client of this class has specified it, so + // we can't reset it + if (isSdcClientAutoManaged) { + // Next init will initialize it with a new SDC Client + this.distributionClient = null; + } + } + this.changeControllerStatus(SdcSingleControllerStatus.STOPPED); + } + + private void sendAllNotificationForCsarHandler(INotificationData notificationData, CsarHandler csar, + NotificationType notificationType, + DistributionStatusEnum distributionStatus, String errorMessage) { + if (csar != null) { + // Notify for the CSAR + this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(), + sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, errorMessage, + System.currentTimeMillis()); + // Notify for all VF resources found + for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) { + // Normally always 1 artifact in resource for Clamp as we + // specified + // only VF_METADATA type + this.sendSdcNotification(notificationType, + blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(), + sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, + errorMessage, System.currentTimeMillis()); + } + } else { + this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(), + notificationData.getDistributionID(), distributionStatus, errorMessage, System.currentTimeMillis()); + } + } + + /** + * This method processes the notification received from Sdc. + * + * @param notificationData The INotificationData + */ + public void treatNotification(INotificationData notificationData) { + CsarHandler csar = null; + try { + // wait for a random time, so that 2 running Clamp will not treat + // the same Notification at the same time + Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10) * 1000L); + logger.info("Notification received for service UUID:" + notificationData.getServiceUUID()); + this.changeControllerStatus(SdcSingleControllerStatus.BUSY); + csar = new CsarHandler(notificationData, this.sdcConfig.getSdcControllerName(), + refProp.getStringValue(CONFIG_SDC_FOLDER)); + csar.save(downloadTheArtifact(csar.getArtifactElement())); + if (csarInstaller.isCsarAlreadyDeployed(csar)) { + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD, + DistributionStatusEnum.ALREADY_DOWNLOADED, null); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.ALREADY_DEPLOYED, null); + } else { + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD, + DistributionStatusEnum.DOWNLOAD_OK, null); + csarInstaller.installTheCsar(csar); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.DEPLOY_OK, null); + } + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_OK, null); + } catch (SdcArtifactInstallerException | SdcToscaParserException e) { + logger.error("SdcArtifactInstallerException exception caught during the notification processing", e); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.DEPLOY_ERROR, e.getMessage()); + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage()); + } catch (SdcDownloadException | CsarHandlerException e) { + logger.error("SdcDownloadException exception caught during the notification processing", e); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD, + DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage()); + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage()); + } catch (InterruptedException e) { + logger.error("Interrupt exception caught during the notification processing", e); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.DEPLOY_ERROR, e.getMessage()); + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage()); + Thread.currentThread().interrupt(); + } catch (BlueprintParserException e) { + logger.error("BlueprintParser exception caught during the notification processing", e); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.DEPLOY_ERROR, e.getMessage()); + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage()); + } catch (RuntimeException e) { + logger.error("Unexpected exception caught during the notification processing", e); + sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY, + DistributionStatusEnum.DEPLOY_ERROR, e.getMessage()); + this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage()); + } finally { + this.changeControllerStatus(SdcSingleControllerStatus.IDLE); + } + } + + private enum NotificationType { + /** + * Download notification type. + */ + DOWNLOAD, + /** + * Deploy notification type. + */ + DEPLOY + } + + private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException { + logger.info("Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: " + + artifact.getArtifactUUID()); + IDistributionClientDownloadResult downloadResult; + try { + downloadResult = distributionClient.download(artifact); + if (null == downloadResult) { + logger.info("downloadResult is Null for: " + artifact.getArtifactUUID()); + return null; + } + } catch (RuntimeException e) { + throw new SdcDownloadException("Exception caught when downloading the artifact", e); + } + if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) { + logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID " + + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length); + } else { + throw new SdcDownloadException("Artifact " + artifact.getArtifactName() + + " could not be downloaded from SDC URL " + artifact.getArtifactURL() + " UUID " + + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is " + + downloadResult.getDistributionMessageResult() + System.lineSeparator()); + } + return downloadResult; + } + + private void sendSdcNotification(NotificationType notificationType, String artifactUrl, String consumerId, + String distributionId, DistributionStatusEnum status, String errorReason, + long timestamp) { + String event = "Sending " + notificationType.name() + "(" + status.name() + ")" + + " notification to SDC for artifact:" + artifactUrl; + if (errorReason != null) { + event = event + "(" + errorReason + ")"; + } + logger.info(event); + String action = ""; + try { + IDistributionStatusMessage message = new DistributionStatusMessage(artifactUrl, consumerId, distributionId, + status, timestamp); + switch (notificationType) { + case DOWNLOAD: + this.sendDownloadStatus(message, errorReason); + action = "sendDownloadStatus"; + break; + case DEPLOY: + this.sendDeploymentStatus(message, errorReason); + action = "sendDeploymentdStatus"; + break; + default: + break; + } + } catch (RuntimeException e) { + logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e); + } + logger.info("SDC Notification sent successfully(" + action + ")"); + } + + private void sendComponentStatus(INotificationData notificationData, DistributionStatusEnum status, + String errorReason) { + try { + IComponentDoneStatusMessage message = new IComponentDoneStatusMessage() { + + @Override public String getDistributionID() { + return notificationData.getDistributionID(); + } + + @Override public String getConsumerID() { + return sdcConfig.getConsumerID(); + } + + @Override public long getTimestamp() { + return System.currentTimeMillis(); + } + + @Override public DistributionStatusEnum getStatus() { + return status; + } + + @Override public String getComponentName() { + return sdcConfig.getUser(); + } + }; + + if (errorReason != null) { + this.distributionClient.sendComponentDoneStatus(message, errorReason); + } else { + this.distributionClient.sendComponentDoneStatus(message); + } + } catch (RuntimeException e) { + logger.warn("Unable to send the SDC Notification (" + status.name() + ") due to an exception", e); + } + logger.info("SDC Notification sent successfully(" + status.name() + ")"); + } + + private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) { + if (errorReason != null) { + this.distributionClient.sendDownloadStatus(message, errorReason); + } else { + this.distributionClient.sendDownloadStatus(message); + } + } + + private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) { + if (errorReason != null) { + this.distributionClient.sendDeploymentStatus(message, errorReason); + } else { + this.distributionClient.sendDeploymentStatus(message); + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java new file mode 100644 index 000000000..a50e340e3 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleControllerStatus.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.sdc.controller; + +public enum SdcSingleControllerStatus { + STOPPED, IDLE, BUSY +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java new file mode 100644 index 000000000..35bc909dc --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintArtifact.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.sdc.controller.installer; + +import org.onap.sdc.api.notification.IResourceInstance; + +/** + * This class is useful to store the information concerning + * blueprint artifact extracted from SDC CSAR. + */ +public class BlueprintArtifact { + + private String dcaeBlueprint; + private String blueprintArtifactName; + private String blueprintInvariantServiceUuid; + private IResourceInstance resourceAttached; + + public String getDcaeBlueprint() { + return dcaeBlueprint; + } + + public void setDcaeBlueprint(String dcaeBlueprint) { + this.dcaeBlueprint = dcaeBlueprint; + } + + public String getBlueprintArtifactName() { + return blueprintArtifactName; + } + + public void setBlueprintArtifactName(String blueprintArtifactName) { + this.blueprintArtifactName = blueprintArtifactName; + } + + public String getBlueprintInvariantServiceUuid() { + return blueprintInvariantServiceUuid; + } + + public void setBlueprintInvariantServiceUuid(String blueprintInvariantServiceUuid) { + this.blueprintInvariantServiceUuid = blueprintInvariantServiceUuid; + } + + public IResourceInstance getResourceAttached() { + return resourceAttached; + } + + public void setResourceAttached(IResourceInstance resourceAttached) { + this.resourceAttached = resourceAttached; + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java new file mode 100644 index 000000000..e00ce9430 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintMicroService.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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============================================ + * Modifications copyright (c) 2019-2020 AT&T + * =================================================================== + * + */ + +package org.onap.clamp.clds.sdc.controller.installer; + +import java.util.Objects; + +public class BlueprintMicroService { + private final String name; + private final String modelType; + private final String inputFrom; + private final String modelVersion; + + /** + * The Micro service constructor. + * + * @param name The name in String + * @param modelType The model type + * @param inputFrom Comes from (single chained) + */ + public BlueprintMicroService(String name, String modelType, String inputFrom, String modelVersion) { + this.name = name; + this.inputFrom = inputFrom; + this.modelType = modelType; + this.modelVersion = modelVersion; + } + + public String getName() { + return name; + } + + public String getModelType() { + return modelType; + } + + public String getInputFrom() { + return inputFrom; + } + + /** + * modelVerrsion getter. + * + * @return the modelVersion + */ + public String getModelVersion() { + return modelVersion; + } + + @Override + public String toString() { + return "MicroService {" + "name='" + name + '\'' + ", modelType='" + modelType + '\'' + ", inputFrom='" + + inputFrom + '\'' + ", modelVersion='" + modelVersion + '\'' + '}'; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + BlueprintMicroService that = (BlueprintMicroService) obj; + return name.equals(that.name) && modelType.equals(that.modelType) && inputFrom.equals(that.inputFrom) + && modelVersion.equals(that.modelVersion); + } + + @Override + public int hashCode() { + return Objects.hash(name, modelType, inputFrom, modelVersion); + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java new file mode 100644 index 000000000..5d5027d29 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParser.java @@ -0,0 +1,222 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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============================================ + * Modifications copyright (c) 2019 AT&T + * =================================================================== + * + */ + +package org.onap.clamp.clds.sdc.controller.installer; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.json.JSONObject; +import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException; +import org.yaml.snakeyaml.Yaml; + +public class BlueprintParser { + + static final String TCA = "TCA"; + private static final String NODE_TEMPLATES = "node_templates"; + private static final String DCAE_NODES = "dcae.nodes."; + private static final String DCAE_NODES_POLICY = ".nodes.policy"; + private static final String TYPE = "type"; + private static final String PROPERTIES = "properties"; + private static final String NAME = "name"; + private static final String INPUT = "inputs"; + private static final String GET_INPUT = "get_input"; + private static final String POLICY_MODEL_ID = "policy_model_id"; + private static final String POLICY_MODEL_VERSION = "policy_model_version"; + private static final String RELATIONSHIPS = "relationships"; + private static final String CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM = "clamp_node.relationships.gets_input_from"; + private static final String TARGET = "target"; + public static final String DEFAULT_VERSION = "1.0.0"; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(BlueprintParser.class); + + private BlueprintParser() { + + } + + /** + * Get all micro services from blueprint. + * + * @param blueprintString the blueprint in a String + * @return A set of MircoService + * @throws BlueprintParserException In case of issues with the parsing + */ + public static Set<BlueprintMicroService> getMicroServices(String blueprintString) throws BlueprintParserException { + Set<BlueprintMicroService> microServices = new HashSet<>(); + JsonObject blueprintJson = BlueprintParser.convertToJson(blueprintString); + JsonObject nodeTemplateList = blueprintJson.get(NODE_TEMPLATES).getAsJsonObject(); + JsonObject inputList = blueprintJson.get(INPUT).getAsJsonObject(); + + for (Entry<String, JsonElement> entry : nodeTemplateList.entrySet()) { + JsonObject nodeTemplate = entry.getValue().getAsJsonObject(); + if (!nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES_POLICY) + && nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES)) { + BlueprintMicroService microService = getNodeRepresentation(entry, nodeTemplateList, inputList); + if (!microService.getModelType().isBlank()) { + microServices.add(microService); + } else { + logger.warn("Microservice " + microService.getName() + + " will NOT be used by CLAMP as the model type is not defined or has not been found"); + } + } + } + logger.debug("Those microservices have been found in the blueprint:" + microServices); + return microServices; + } + + /** + * Does a fallback to TCA. + * + * @return The list of microservices + */ + public static List<BlueprintMicroService> fallbackToOneMicroService() { + return Collections.singletonList( + new BlueprintMicroService(TCA, "onap.policies.monitoring.cdap.tca.hi.lo.app", "", DEFAULT_VERSION)); + } + + static String getName(Entry<String, JsonElement> entry) { + String microServiceYamlName = entry.getKey(); + JsonObject ob = entry.getValue().getAsJsonObject(); + if (ob.has(PROPERTIES)) { + JsonObject properties = ob.get(PROPERTIES).getAsJsonObject(); + if (properties.has(NAME)) { + return properties.get(NAME).getAsString(); + } + } + return microServiceYamlName; + } + + static String getInput(Entry<String, JsonElement> entry) { + JsonObject ob = entry.getValue().getAsJsonObject(); + if (ob.has(RELATIONSHIPS)) { + JsonArray relationships = ob.getAsJsonArray(RELATIONSHIPS); + for (JsonElement element : relationships) { + String target = getTarget(element.getAsJsonObject()); + if (!target.isEmpty()) { + return target; + } + } + } + return ""; + } + + static String findPropertyInRelationshipsArray(String propertyName, JsonArray relationshipsArray, + JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException { + for (JsonElement elem : relationshipsArray) { + if (blueprintNodeTemplateList.get(elem.getAsJsonObject().get(TARGET).getAsString()) == null) { + throw new BlueprintParserException( + "The Target mentioned in the blueprint is not a known entry in the blueprint: " + + elem.getAsJsonObject().get(TARGET).getAsString()); + } else { + String property = getPropertyValue(propertyName, + new AbstractMap.SimpleEntry<String, JsonElement>( + elem.getAsJsonObject().get(TARGET).getAsString(), blueprintNodeTemplateList + .get(elem.getAsJsonObject().get(TARGET).getAsString()).getAsJsonObject()), + blueprintNodeTemplateList, blueprintInputList); + if (!property.isEmpty()) { + return property; + } + } + } + return ""; + } + + static String getDirectOrInputPropertyValue(String propertyName, JsonObject blueprintInputList, + JsonObject nodeTemplateContent) { + JsonObject properties = nodeTemplateContent.get(PROPERTIES).getAsJsonObject(); + if (properties.has(propertyName)) { + if (properties.get(propertyName).isJsonObject()) { + // it's a blueprint parameter + return blueprintInputList + .get(properties.get(propertyName).getAsJsonObject().get(GET_INPUT).getAsString()) + .getAsJsonObject().get("default").getAsString(); + } else { + // It's a direct value + return properties.get(propertyName).getAsString(); + } + } + return ""; + } + + static String getPropertyValue(String propertyName, Entry<String, JsonElement> nodeTemplateEntry, + JsonObject blueprintNodeTemplateList, JsonObject blueprintIputList) throws BlueprintParserException { + JsonObject nodeTemplateContent = nodeTemplateEntry.getValue().getAsJsonObject(); + // Search first in this node template + if (nodeTemplateContent.has(PROPERTIES)) { + String propValue = getDirectOrInputPropertyValue(propertyName, blueprintIputList, nodeTemplateContent); + if (!propValue.isBlank()) { + return propValue; + } + } + // Or it's may be defined in a relationship + if (nodeTemplateContent.has(RELATIONSHIPS)) { + return findPropertyInRelationshipsArray(propertyName, + nodeTemplateContent.get(RELATIONSHIPS).getAsJsonArray(), blueprintNodeTemplateList, + blueprintIputList); + } + return ""; + } + + static BlueprintMicroService getNodeRepresentation(Entry<String, JsonElement> nodeTemplateEntry, + JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException { + String modelIdFound = getPropertyValue(POLICY_MODEL_ID, nodeTemplateEntry, blueprintNodeTemplateList, + blueprintInputList); + String versionFound = getPropertyValue(POLICY_MODEL_VERSION, nodeTemplateEntry, blueprintNodeTemplateList, + blueprintInputList); + if (modelIdFound.isBlank()) { + logger.warn("policy_model_id is not defined for the node template:" + nodeTemplateEntry.getKey()); + } + if (versionFound.isBlank()) { + logger.warn("policy_model_version is not defined (setting it to a default value) for the node template:" + + nodeTemplateEntry.getKey()); + } + return new BlueprintMicroService(getName(nodeTemplateEntry), modelIdFound, getInput(nodeTemplateEntry), + !versionFound.isBlank() ? versionFound : DEFAULT_VERSION); + } + + private static String getTarget(JsonObject elementObject) { + if (elementObject.has(TYPE) && elementObject.has(TARGET) + && elementObject.get(TYPE).getAsString().equals(CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM)) { + return elementObject.get(TARGET).getAsString(); + } + return ""; + } + + private static JsonObject convertToJson(String yamlString) { + Map<String, Object> map = new Yaml().load(yamlString); + return new Gson().fromJson(new JSONObject(map).toString(), JsonObject.class); + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java new file mode 100644 index 000000000..2bd259c2b --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/ChainGenerator.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.clds.sdc.controller.installer; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +@Component +public class ChainGenerator { + + ChainGenerator() { + } + + /** + * Get list of microservices chain. + * + * @param input A set of microservices + * @return The list of microservice chained + */ + public List<BlueprintMicroService> getChainOfMicroServices(Set<BlueprintMicroService> input) { + LinkedList<BlueprintMicroService> returnList = new LinkedList<>(); + if (preValidate(input)) { + LinkedList<BlueprintMicroService> theList = new LinkedList<>(); + for (BlueprintMicroService ms : input) { + insertNodeTemplateIntoChain(ms, theList); + } + if (postValidate(theList)) { + returnList = theList; + } + } + return returnList; + } + + private boolean preValidate(Set<BlueprintMicroService> input) { + List<BlueprintMicroService> noInputs = input.stream().filter(ms -> "".equals(ms.getInputFrom())) + .collect(Collectors.toList()); + return noInputs.size() == 1; + } + + private boolean postValidate(LinkedList<BlueprintMicroService> microServices) { + for (int i = 1; i < microServices.size() - 1; i++) { + BlueprintMicroService prev = microServices.get(i - 1); + BlueprintMicroService current = microServices.get(i); + if (!current.getInputFrom().equals(prev.getName())) { + return false; + } + } + return true; + } + + private void insertNodeTemplateIntoChain(BlueprintMicroService microServicetoInsert, + LinkedList<BlueprintMicroService> chainOfMicroServices) { + int insertIndex = 0; + for (int i = 0; i < chainOfMicroServices.size(); i++) { + BlueprintMicroService current = chainOfMicroServices.get(i); + if (microServicetoInsert.getName().equals(current.getInputFrom())) { + insertIndex = i; + break; + } else if (current.getName().equals(microServicetoInsert.getInputFrom())) { + insertIndex = i + 1; + break; + } + } + chainOfMicroServices.add(insertIndex, microServicetoInsert); + } +} diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java new file mode 100644 index 000000000..471415a37 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java @@ -0,0 +1,221 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.sdc.controller.installer; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.commons.io.IOUtils; +import org.codehaus.plexus.util.StringUtils; +import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.notification.IResourceInstance; +import org.onap.sdc.api.results.IDistributionClientDownloadResult; +import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; + +/** + * CsarDescriptor that will be used to deploy file in CLAMP file system. Some + * methods can also be used to get some data from it. + */ +public class CsarHandler { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarHandler.class); + private IArtifactInfo artifactElement; + private String csarFilePath; + private String controllerName; + private SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance(); + private ISdcCsarHelper sdcCsarHelper; + private Map<String, BlueprintArtifact> mapOfBlueprints = new HashMap<>(); + public static final String CSAR_TYPE = "TOSCA_CSAR"; + public static final String BLUEPRINT_TYPE = "DCAE_INVENTORY_BLUEPRINT"; + private INotificationData sdcNotification; + public static final String RESOURCE_INSTANCE_NAME_PREFIX = "/Artifacts/Resources/"; + public static final String RESOURCE_INSTANCE_NAME_SUFFIX = "/Deployment/"; + public static final String POLICY_DEFINITION_NAME_SUFFIX = "Definitions/policies.yml"; + public static final String DATA_DEFINITION_NAME_SUFFIX = "Definitions/data.yml"; + public static final String DATA_DEFINITION_KEY = "data_types:"; + + /** + * Constructor for CsarHandler taking sdc notification in input. + */ + public CsarHandler(INotificationData data, String controller, String clampCsarPath) throws CsarHandlerException { + this.sdcNotification = data; + this.controllerName = controller; + this.artifactElement = searchForUniqueCsar(data); + this.csarFilePath = buildFilePathForCsar(artifactElement, clampCsarPath); + } + + private String buildFilePathForCsar(IArtifactInfo artifactElement, String clampCsarPath) { + return clampCsarPath + "/" + controllerName + "/" + artifactElement.getArtifactName(); + } + + private IArtifactInfo searchForUniqueCsar(INotificationData notificationData) throws CsarHandlerException { + List<IArtifactInfo> serviceArtifacts = notificationData.getServiceArtifacts(); + for (IArtifactInfo artifact : serviceArtifacts) { + if (artifact.getArtifactType().equals(CSAR_TYPE)) { + return artifact; + } + } + throw new CsarHandlerException("Unable to find a CSAR in the Sdc Notification"); + } + + /** + * This saves the notification to disk and database. + * + * @param resultArtifact The artifact to install + * @throws SdcArtifactInstallerException In case of issues with the installation + * @throws SdcToscaParserException In case of issues with the parsing of + * the CSAR + */ + public synchronized void save(IDistributionClientDownloadResult resultArtifact) + throws SdcArtifactInstallerException, SdcToscaParserException { + try { + logger.info("Writing CSAR file to: " + csarFilePath + " UUID " + artifactElement.getArtifactUUID() + ")"); + Path path = Paths.get(csarFilePath); + Files.createDirectories(path.getParent()); + // Create or replace the file + try (OutputStream out = Files.newOutputStream(path)) { + out.write(resultArtifact.getArtifactPayload(), 0, resultArtifact.getArtifactPayload().length); + } + sdcCsarHelper = factory.getSdcCsarHelper(csarFilePath); + this.loadDcaeBlueprint(); + } catch (IOException e) { + throw new SdcArtifactInstallerException( + "Exception caught when trying to write the CSAR on the file system to " + csarFilePath, e); + } + } + + private IResourceInstance searchForResourceByInstanceName(String blueprintResourceInstanceName) + throws SdcArtifactInstallerException { + for (IResourceInstance resource : this.sdcNotification.getResources()) { + String filteredString = resource.getResourceInstanceName().replaceAll("-", ""); + filteredString = filteredString.replaceAll(" ", ""); + if (filteredString.equalsIgnoreCase(blueprintResourceInstanceName)) { + return resource; + } + } + throw new SdcArtifactInstallerException("Error when searching for " + blueprintResourceInstanceName + + " as ResourceInstanceName in Sdc notification and did not find it"); + } + + private void loadDcaeBlueprint() throws IOException, SdcArtifactInstallerException { + try (ZipFile zipFile = new ZipFile(csarFilePath)) { + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (!entry.isDirectory() && entry.getName().contains(BLUEPRINT_TYPE)) { + BlueprintArtifact blueprintArtifact = new BlueprintArtifact(); + blueprintArtifact.setBlueprintArtifactName( + entry.getName().substring(entry.getName().lastIndexOf('/') + 1, entry.getName().length())); + blueprintArtifact + .setBlueprintInvariantServiceUuid(this.getSdcNotification().getServiceInvariantUUID()); + try (InputStream stream = zipFile.getInputStream(entry)) { + blueprintArtifact.setDcaeBlueprint(IOUtils.toString(stream, StandardCharsets.UTF_8)); + } + blueprintArtifact.setResourceAttached(searchForResourceByInstanceName(entry.getName().substring( + entry.getName().indexOf(RESOURCE_INSTANCE_NAME_PREFIX) + + RESOURCE_INSTANCE_NAME_PREFIX.length(), + entry.getName().indexOf(RESOURCE_INSTANCE_NAME_SUFFIX)))); + this.mapOfBlueprints.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact); + logger.info("Found a blueprint entry in the CSAR " + blueprintArtifact.getBlueprintArtifactName() + + " for resource instance Name " + + blueprintArtifact.getResourceAttached().getResourceInstanceName()); + } + } + logger.info(this.mapOfBlueprints.size() + " blueprint(s) will be converted to closed loop"); + } + } + + public IArtifactInfo getArtifactElement() { + return artifactElement; + } + + public String getFilePath() { + return csarFilePath; + } + + public String setFilePath(String newPath) { + return csarFilePath = newPath; + } + + public synchronized ISdcCsarHelper getSdcCsarHelper() { + return sdcCsarHelper; + } + + public INotificationData getSdcNotification() { + return sdcNotification; + } + + public Map<String, BlueprintArtifact> getMapOfBlueprints() { + return mapOfBlueprints; + } + + /** + * Get the whole policy model Yaml. It combines the content of policies.yaml and + * data.yaml. + * + * @return The whole policy model yaml + * @throws IOException The IO Exception + */ + public Optional<String> getPolicyModelYaml() throws IOException { + String result = null; + try (ZipFile zipFile = new ZipFile(csarFilePath)) { + ZipEntry entry = zipFile.getEntry(POLICY_DEFINITION_NAME_SUFFIX); + if (entry != null) { + ZipEntry data = zipFile.getEntry(DATA_DEFINITION_NAME_SUFFIX); + if (data != null) { + String dataStr = IOUtils.toString(zipFile.getInputStream(data), StandardCharsets.UTF_8); + String dataStrWithoutHeader = dataStr.substring(dataStr.indexOf(DATA_DEFINITION_KEY)); + String policyStr = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8); + StringUtils.chomp(policyStr); + result = policyStr.concat(dataStrWithoutHeader); + } else { + result = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8); + } + } else { + logger.info("Policy model not found inside the CSAR file: " + csarFilePath); + } + return Optional.ofNullable(result); + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java b/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java new file mode 100644 index 000000000..3fceace55 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/service/CldsHealthcheckService.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.service; + +import java.util.Date; +import org.onap.clamp.clds.model.CldsHealthCheck; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.clds.util.OnapLogConstants; +import org.onap.clamp.loop.LoopController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +/** + * Service to retrieve the Health Check of the clds application. + * + */ +@Component +public class CldsHealthcheckService { + + @Autowired + private LoopController loopController; + + protected static final Logger logger = LoggerFactory.getLogger(CldsHealthcheckService.class); + + /** + * REST service that retrieves clds healthcheck information. + * + * @return CldsHealthCheck class containing healthcheck info + */ + public CldsHealthCheck gethealthcheck() { + CldsHealthCheck cldsHealthCheck = new CldsHealthCheck(); + Date startTime = new Date(); + LoggingUtils util = new LoggingUtils(logger); + LoggingUtils.setRequestContext("CldsService: GET healthcheck", "Clamp-Health-Check"); + LoggingUtils.setTimeContext(startTime, new Date()); + try { + loopController.getLoopNames(); + cldsHealthCheck.setHealthCheckComponent("CLDS-APP"); + cldsHealthCheck.setHealthCheckStatus("UP"); + cldsHealthCheck.setDescription("OK"); + LoggingUtils.setResponseContext("0", "Get healthcheck success", + this.getClass().getName()); + util.exiting(HttpStatus.OK.value(), "Healthcheck success", Level.INFO, + OnapLogConstants.ResponseStatus.COMPLETE); + } catch (Exception e) { + logger.error("CLAMP application Heath check failed", e); + LoggingUtils.setResponseContext("999", "Get healthcheck failed", + this.getClass().getName()); + cldsHealthCheck.setHealthCheckComponent("CLDS-APP"); + cldsHealthCheck.setHealthCheckStatus("DOWN"); + cldsHealthCheck.setDescription("NOT-OK"); + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Healthcheck failed", Level.INFO, + OnapLogConstants.ResponseStatus.ERROR); + } + return cldsHealthCheck; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java b/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java new file mode 100644 index 000000000..e3c661698 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018-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.clds.tosca; + +public class JsonEditorSchemaConstants { + + //Data types in JSON Schema + public static final String TYPE_OBJECT = "object"; + public static final String TYPE_ARRAY = "array"; + public static final String TYPE_MAP = "map"; + public static final String TYPE_STRING = "string"; + public static final String TYPE_INTEGER = "integer"; + public static final String TYPE_DATE_TIME = "datetime"; + + //Key elements in JSON Schema + public static final String TYPE = "type"; + public static final String TITLE = "title"; + public static final String REQUIRED = "required"; + public static final String DEFAULT = "default"; + public static final String ENUM = "enum"; + public static final String ENUM_TITLES = "enum_titles"; + public static final String OPTIONS = "options"; + public static final String FORMAT = "format"; + public static final String ITEMS = "items"; + public static final String PROPERTIES = "properties"; + public static final String PROPERTY_ORDER = "propertyOrder"; + public static final String VALUES = "values"; + public static final String HEADER_TEMPLATE = "headerTemplate"; + public static final String HEADER_TEMPLATE_VALUE = "{{self.name}}"; + + public static final String MINIMUM = "minimum"; + public static final String MAXIMUM = "maximum"; + public static final String MIN_LENGTH = "minLength"; + public static final String MAX_LENGTH = "maxLength"; + public static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum"; + public static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum"; + public static final String MINITEMS = "minItems"; + public static final String MAXITEMS = "maxItems"; + + public static final String CUSTOM_KEY_FORMAT = "format"; + public static final String CUSTOM_KEY_FORMAT_TABS_TOP = "tabs-top"; + public static final String CUSTOM_KEY_FORMAT_TABS = "tabs"; + public static final String CUSTOM_KEY_FORMAT_INPUT = "input"; + public static final String FORMAT_SELECT = "select"; + public static final String UNIQUE_ITEMS = "uniqueItems"; + public static final String TRUE = "true"; + public static final String QSSCHEMA = "qschema"; + public static final String TYPE_QBLDR = "qbldr"; + + public static final String ID = "id"; + public static final String LABEL = "label"; + public static final String OPERATORS = "operators"; + public static final String FILTERS = "filters"; + + public static final String SCHEMA = "schema"; + public static final String CURRENT_VALUES = "currentValues"; + + public static final String PLUGIN = "plugin"; + public static final String DATE_TIME_PICKER = "datetimepicker"; + public static final String VALIDATION = "validation"; + public static final String DATE_TIME_FORMAT = "YYYY/MM/DD HH:mm:ss"; + public static final String INPUT_EVENT = "input_event"; + public static final String DP_CHANGE = "dp.change"; + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java b/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java new file mode 100644 index 000000000..d00c431c8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/ToscaSchemaConstants.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.tosca; + +public class ToscaSchemaConstants { + + // Data types in TOSCA Schema + public static final String TYPE_LIST = "list"; + public static final String TYPE_MAP = "map"; + public static final String TYPE_STRING = "string"; + public static final String TYPE_INTEGER = "integer"; + public static final String TYPE_NUMBER = "number"; + public static final String TYPE_DATE_TIME = "datetime"; + public static final String TYPE_FLOAT = "float"; + public static final String TYPE_BOOLEAN = "boolean"; + public static final String TYPE_USER_DEFINED = "userDefined"; + + // Key elements in Tosca + public static final String NODE_TYPES = "policy_types"; + public static final String DATA_TYPES = "data_types"; + public static final String TYPE = "type"; + public static final String DESCRIPTION = "description"; + public static final String DEFAULT = "default"; + public static final String PROPERTIES = "properties"; + public static final String REQUIRED = "required"; + public static final String ENTRY_SCHEMA = "entry_schema"; + + public static final String METADATA = "metadata"; + public static final String METADATA_POLICY_MODEL_TYPE = "policy_model_type"; + public static final String METADATA_ACRONYM = "acronym"; + public static final String METADATA_ELEMENT_NAME = "element_name"; + public static final String METADATA_HEADER_TEMPLATE = "header_template"; + public static final String METADATA_CLAMP_POSSIBLE_VALUES = "clamp_possible_values"; + + // Constraints + public static final String CONSTRAINTS = "constraints"; + public static final String VALID_VALUES = "valid_values"; + public static final String EQUAL = "equal"; + public static final String GREATER_THAN = "greater_than"; + public static final String GREATER_OR_EQUAL = "greater_or_equal"; + public static final String LESS_THAN = "less_than"; + public static final String LESS_OR_EQUAL = "less_or_equal"; + public static final String IN_RANGE = "in_range"; + public static final String LENGTH = "length"; + public static final String MIN_LENGTH = "min_length"; + public static final String MAX_LENGTH = "max_length"; + public static final String PATTERN = "pattern"; + + // Prefix for policy nodes + public static final String POLICY_NODE = "onap.policies."; + + // Prefix for data nodes + public static final String POLICY_DATA = "onap.datatypes."; + + // Prefix for dictionary elements + public static final String DICTIONARY = "Dictionary:"; + + // Custom Elements that must exist in the Tosca models + public static final String NAME = "name"; + public static final String CONTEXT = "context"; + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java b/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java new file mode 100644 index 000000000..45bb87ed8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java @@ -0,0 +1,780 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.tosca; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.stream.Collectors; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.tosca.Dictionary; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +/** + * Tosca Model Yaml parser and convertor to JSON Schema consumable for JSON + * Editor. + * + */ +@Component +public class ToscaYamlToJsonConvertor { + + @Autowired + private DictionaryService dictionaryService; + + @Autowired + private ClampProperties refProp; + + private int simpleTypeOrder = 1000; + private int complexTypeOrder = 10000; + private int complexSimpleTypeOrder = 1; + + private int incrementSimpleTypeOrder() { + return simpleTypeOrder++; + } + + private int incrementComplexTypeOrder() { + return complexTypeOrder = complexTypeOrder + 10000; + } + + private int incrementComplexSimpleTypeOrder() { + complexSimpleTypeOrder++; + return complexTypeOrder + complexSimpleTypeOrder; + } + + /** + * Parses Tosca YAML string and Converts to JsonObject. + * + * @param yamlString YAML string + * @return JsonObject + */ + public JsonObject validateAndConvertToJson(String yamlString) { + + Yaml yaml = new Yaml(); + LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString); + if (loadedYaml == null) { + return null; + } + + JSONObject jsonObject = new JSONObject(loadedYaml); + return new Gson().fromJson(jsonObject.toString(), JsonObject.class); + } + + /** + * return the values by looking up the key in the Toscsa JSON object. + * + * @param obj Tosca Json Object + * @param key the parameter key to look up + * @return the value for the provided key + */ + public String getValueFromMetadata(JsonObject obj, String key) { + JsonElement jsonElement = obj.get(ToscaSchemaConstants.NODE_TYPES); + if (jsonElement.isJsonObject()) { + Iterator<Entry<String, JsonElement>> itr = + jsonElement.getAsJsonObject().entrySet().iterator(); + while (itr.hasNext()) { + Entry<String, JsonElement> entry = itr.next(); + if (entry.getValue() != null && entry.getValue().isJsonObject() + && entry.getValue().getAsJsonObject().has(ToscaSchemaConstants.METADATA)) { + JsonObject metadatas = entry.getValue().getAsJsonObject() + .get(ToscaSchemaConstants.METADATA).getAsJsonObject(); + if (metadatas.has(key)) { + return metadatas.get(key).getAsString(); + } + } + } + } + return null; + } + + /** + * Parses Tosca YAML string. + * + * @param yamlString YAML string + * @param modelTypeToUse The model type that must be used to obtain the Json + * Schema + * @return JSON string + */ + public String parseToscaYaml(String yamlString, String modelTypeToUse) { + + Yaml yaml = new Yaml(); + LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString); + if (loadedYaml == null) { + return ""; + } + LinkedHashMap<String, Object> nodeTypes = new LinkedHashMap<>(); + LinkedHashMap<String, Object> dataNodes = new LinkedHashMap<>(); + JSONObject jsonParentObject = new JSONObject(); + JSONObject jsonTempObject = new JSONObject(); + parseNodeAndDataType(loadedYaml, nodeTypes, dataNodes); + populateJsonEditorObject(loadedYaml, nodeTypes, dataNodes, jsonParentObject, jsonTempObject, + modelTypeToUse); + + String headerTemplate = getValueFromMetadata(validateAndConvertToJson(yamlString), + ToscaSchemaConstants.METADATA_HEADER_TEMPLATE); + if (headerTemplate != null) { + jsonParentObject.put(JsonEditorSchemaConstants.HEADER_TEMPLATE, + JsonEditorSchemaConstants.HEADER_TEMPLATE_VALUE); + } + if (jsonTempObject.length() > 0) { + jsonParentObject = jsonTempObject; + } + JSONObject jsonEditorObject = new JSONObject(); + jsonEditorObject.put(JsonEditorSchemaConstants.SCHEMA, jsonParentObject); + return jsonEditorObject.toString(); + } + + // Parse node_type and data_type + @SuppressWarnings("unchecked") + private void parseNodeAndDataType(LinkedHashMap<String, Object> map, + LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes) { + map.entrySet().stream().forEach(n -> { + if (n.getKey().contains(ToscaSchemaConstants.NODE_TYPES) + && n.getValue() instanceof Map) { + parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes, + dataNodes); + } else if (n.getKey().contains(ToscaSchemaConstants.DATA_TYPES) + && n.getValue() instanceof Map) { + parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes, + dataNodes); + } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_NODE)) { + nodeTypes.put(n.getKey(), n.getValue()); + } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_DATA)) { + dataNodes.put(n.getKey(), n.getValue()); + } + }); + } + + @SuppressWarnings("unchecked") + private void populateJsonEditorObject(LinkedHashMap<String, Object> map, + LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes, + JSONObject jsonParentObject, JSONObject jsonTempObject, String modelTypeToUse) { + + Map<String, JSONObject> jsonEntrySchema = new HashMap<>(); + jsonParentObject.put(JsonEditorSchemaConstants.TYPE, JsonEditorSchemaConstants.TYPE_OBJECT); + if (nodeTypes.get(modelTypeToUse) instanceof Map) { + ((LinkedHashMap<String, Object>) nodeTypes.get(modelTypeToUse)).entrySet() + .forEach(ntElement -> { + if (ntElement.getKey().equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) { + JSONArray rootNodeArray = new JSONArray(); + if (ntElement.getValue() instanceof Map) { + ((LinkedHashMap<String, Object>) ntElement.getValue()).entrySet() + .forEach((ntPropertiesElement) -> { + boolean isListNode = false; + parseDescription( + (LinkedHashMap<String, Object>) ntPropertiesElement + .getValue(), + jsonParentObject); + LinkedHashMap<String, Object> parentPropertiesMap = + (LinkedHashMap<String, Object>) ntPropertiesElement + .getValue(); + if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE) + && ((String) parentPropertiesMap + .get(ToscaSchemaConstants.TYPE)) + .contains(ToscaSchemaConstants.TYPE_MAP) + && parentPropertiesMap + .containsKey(ToscaSchemaConstants.ENTRY_SCHEMA)) { + parentPropertiesMap = + (LinkedHashMap<String, Object>) parentPropertiesMap + .get(ToscaSchemaConstants.ENTRY_SCHEMA); + isListNode = true; + } + if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE) + && ((String) parentPropertiesMap + .get(ToscaSchemaConstants.TYPE)) + .contains(ToscaSchemaConstants.POLICY_DATA)) { + ((LinkedHashMap<String, Object>) dataNodes.get( + parentPropertiesMap.get(ToscaSchemaConstants.TYPE))) + .entrySet().stream().forEach(pmap -> { + if (pmap.getKey().equalsIgnoreCase( + ToscaSchemaConstants.PROPERTIES)) { + parseToscaProperties( + ToscaSchemaConstants.POLICY_NODE, + (LinkedHashMap<String, Object>) pmap + .getValue(), + jsonParentObject, rootNodeArray, + jsonEntrySchema, dataNodes, + incrementSimpleTypeOrder()); + } + }); + } + if (isListNode) { + jsonTempObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_ARRAY); + parseDescription( + (LinkedHashMap<String, Object>) ntPropertiesElement + .getValue(), + jsonTempObject); + jsonTempObject.put(JsonEditorSchemaConstants.ITEMS, + jsonParentObject); + jsonTempObject.put(JsonEditorSchemaConstants.FORMAT, + JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS); + jsonTempObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS, + JsonEditorSchemaConstants.TRUE); + } + }); + } + } + }); + } + } + + @SuppressWarnings("unchecked") + private void parseToscaProperties(String parentKey, LinkedHashMap<String, Object> propertiesMap, + JSONObject jsonDataNode, JSONArray array, Map<String, JSONObject> jsonEntrySchema, + LinkedHashMap<String, Object> dataNodes, final int order) { + JSONObject jsonPropertyNode = new JSONObject(); + propertiesMap.entrySet().stream().forEach(p -> { + // Populate JSON Array for "required" key + + if (p.getValue() instanceof Map) { + LinkedHashMap<String, Object> nodeMap = + (LinkedHashMap<String, Object>) p.getValue(); + if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED) + && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) { + array.put(p.getKey()); + } + // if(nodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS)) + parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema, + dataNodes, array, incrementSimpleTypeOrder()); + } + }); + jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array); + jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode); + } + + @SuppressWarnings("unchecked") + private void parseToscaPropertiesForType(String parentKey, + LinkedHashMap<String, Object> propertiesMap, JSONObject jsonDataNode, JSONArray array, + Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes, + boolean isType, int order) { + JSONObject jsonPropertyNode = new JSONObject(); + + propertiesMap.entrySet().stream().forEach(p -> { + // array.put(p.getKey()); + boolean overWriteArray = false; + if (p.getValue() instanceof Map) { + LinkedHashMap<String, Object> nodeMap = + (LinkedHashMap<String, Object>) p.getValue(); + if (!(parentKey.contains(ToscaSchemaConstants.ENTRY_SCHEMA) + || parentKey.contains(ToscaSchemaConstants.POLICY_NODE)) + && nodeMap.containsKey(ToscaSchemaConstants.TYPE) + && (((String) nodeMap.get(ToscaSchemaConstants.TYPE)) + .contains(ToscaSchemaConstants.POLICY_DATA))) { + overWriteArray = true; + } + if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED) + && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) { + array.put(p.getKey()); + } + parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema, + dataNodes, array, order); + } + }); + jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array); + jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode); + } + + private void parseToscaChildNodeMap(String childObjectKey, + LinkedHashMap<String, Object> childNodeMap, JSONObject jsonPropertyNode, + Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes, + JSONArray array, int order) { + JSONObject childObject = new JSONObject(); + // JSONArray childArray = new JSONArray(); + parseDescription(childNodeMap, childObject); + parseTypes(childObjectKey, childNodeMap, childObject, jsonEntrySchema, dataNodes, array, + order); + parseConstraints(childNodeMap, childObject); + parseMetadataPossibleValues(childNodeMap, childObject); + parseEntrySchema(childNodeMap, childObject, jsonPropertyNode, jsonEntrySchema, dataNodes); + + jsonPropertyNode.put(childObjectKey, childObject); + order++; + + } + + private void parseEntrySchema(LinkedHashMap<String, Object> childNodeMap, + JSONObject childObject, JSONObject jsonPropertyNode, + Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes) { + if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) != null) { + if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) instanceof Map) { + LinkedHashMap<String, Object> entrySchemaMap = + (LinkedHashMap<String, Object>) childNodeMap + .get(ToscaSchemaConstants.ENTRY_SCHEMA); + entrySchemaMap.entrySet().stream().forEach(entry -> { + if (entry.getKey().equalsIgnoreCase(ToscaSchemaConstants.TYPE) + && entry.getValue() != null) { + String entrySchemaType = (String) entry.getValue(); + if (entrySchemaType.contains(ToscaSchemaConstants.POLICY_DATA)) { + JSONArray array = new JSONArray(); + if (jsonEntrySchema.get(entrySchemaType) != null) { + // Already traversed + JSONObject entrySchemaObject = jsonEntrySchema.get(entrySchemaType); + attachEntrySchemaJsonObject(childObject, entrySchemaObject, + JsonEditorSchemaConstants.TYPE_OBJECT); + } else if (dataNodes.containsKey(entrySchemaType)) { + + JSONObject entrySchemaObject = new JSONObject(); + // Need to traverse + ((LinkedHashMap<String, Object>) dataNodes.get(entrySchemaType)) + .entrySet().stream().forEach(pmap -> { + if (pmap.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) { + parseToscaProperties(ToscaSchemaConstants.ENTRY_SCHEMA, + (LinkedHashMap<String, Object>) pmap.getValue(), + entrySchemaObject, array, jsonEntrySchema, + dataNodes, incrementComplexTypeOrder()); + jsonEntrySchema.put(entrySchemaType, entrySchemaObject); + dataNodes.remove(entrySchemaType); + attachEntrySchemaJsonObject(childObject, + entrySchemaObject, + JsonEditorSchemaConstants.TYPE_OBJECT); + } + + }); + } + } else if (entrySchemaType + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING) + || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER) + || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) { + JSONObject entrySchemaObject = new JSONObject(); + parseConstraints(entrySchemaMap, entrySchemaObject); + parseMetadataPossibleValues(entrySchemaMap, entrySchemaObject); + String jsontype = JsonEditorSchemaConstants.TYPE_STRING; + if (entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER) + || entrySchemaType + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) { + jsontype = JsonEditorSchemaConstants.TYPE_INTEGER; + } + if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) { + // Only known value of type is String for now + if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) { + String typeValue = + (String) childNodeMap.get(ToscaSchemaConstants.TYPE); + if (typeValue + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) { + // Custom key for JSON Editor and UI rendering + childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT, + JsonEditorSchemaConstants.FORMAT_SELECT); + // childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS, + // JsonEditorSchemaConstants.TRUE); + } + } + } + attachEntrySchemaJsonObject(childObject, entrySchemaObject, jsontype); + } + } + }); + } + } + } + + private void attachEntrySchemaJsonObject(JSONObject childObject, JSONObject entrySchemaObject, + String dataType) { + + entrySchemaObject.put(JsonEditorSchemaConstants.TYPE, dataType); + childObject.put(JsonEditorSchemaConstants.ITEMS, entrySchemaObject); + } + + @SuppressWarnings("unchecked") + private void attachTypeJsonObject(JSONObject childObject, JSONObject typeObject) { + Iterator<String> keys = typeObject.keys(); + while (keys.hasNext()) { + String key = keys.next(); + childObject.put(key, typeObject.get(key)); + } + } + + /* + * private String parseKey(String toscaKey, String lookupString) { return + * toscaKey.substring(toscaKey.indexOf(lookupString) + lookupString.length(), + * toscaKey.length()); } + */ + + private void parseDescription(LinkedHashMap<String, Object> childNodeMap, + JSONObject childObject) { + if (childNodeMap.get(ToscaSchemaConstants.DESCRIPTION) != null) { + childObject.put(JsonEditorSchemaConstants.TITLE, + childNodeMap.get(ToscaSchemaConstants.DESCRIPTION)); + } + } + + private void parseTypes(String childObjectKey, LinkedHashMap<String, Object> childNodeMap, + JSONObject childObject, Map<String, JSONObject> jsonEntrySchema, + LinkedHashMap<String, Object> dataNodes, JSONArray array, int order) { + if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) { + // Only known value of type is String for now + if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) { + childObject.put(JsonEditorSchemaConstants.PROPERTY_ORDER, order); + String typeValue = (String) childNodeMap.get(ToscaSchemaConstants.TYPE); + if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) { + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_INTEGER); + + } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) { + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_INTEGER); + } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) { + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_ARRAY); + // Custom key for JSON Editor and UI rendering + childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT, + JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS_TOP); + childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS, + JsonEditorSchemaConstants.TRUE); + } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) { + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_OBJECT); + } else if (typeValue.contains(ToscaSchemaConstants.POLICY_DATA)) { + JSONArray childArray = new JSONArray(); + + if (jsonEntrySchema.get(typeValue) != null) { + // Already traversed + JSONObject entrySchemaObject = jsonEntrySchema.get(typeValue); + attachTypeJsonObject(childObject, entrySchemaObject); + } else if (dataNodes.containsKey(typeValue)) { + JSONObject entrySchemaObject = new JSONObject(); + // Need to traverse + JSONArray jsonArray = new JSONArray(); + ((LinkedHashMap<String, Object>) dataNodes.get(typeValue)).entrySet() + .stream().forEach(pmap -> { + if (pmap.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) { + parseToscaPropertiesForType(childObjectKey, + (LinkedHashMap<String, Object>) pmap.getValue(), + entrySchemaObject, childArray, jsonEntrySchema, dataNodes, + true, incrementComplexSimpleTypeOrder()); + jsonEntrySchema.put(typeValue, entrySchemaObject); + dataNodes.remove(typeValue); + attachTypeJsonObject(childObject, entrySchemaObject); + } + }); + } + } else { + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_STRING); + } + } + if (childNodeMap.get(ToscaSchemaConstants.DEFAULT) != null) { + childObject.put(JsonEditorSchemaConstants.DEFAULT, + childNodeMap.get(ToscaSchemaConstants.DEFAULT)); + } + } + } + + private void parseConstraints(LinkedHashMap<String, Object> childNodeMap, + JSONObject childObject) { + if (childNodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS) + && childNodeMap.get(ToscaSchemaConstants.CONSTRAINTS) != null) { + List<LinkedHashMap<String, Object>> constraintsList = + (List<LinkedHashMap<String, Object>>) childNodeMap + .get(ToscaSchemaConstants.CONSTRAINTS); + constraintsList.stream().forEach(c -> { + if (c instanceof Map) { + c.entrySet().stream().forEach(constraint -> { + if (constraint.getKey().equalsIgnoreCase(ToscaSchemaConstants.MIN_LENGTH) + || constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.GREATER_OR_EQUAL)) { + // For String min_lenghth is minimum length whereas for number, it will + // be + // minimum or greater than to the defined value + if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE) + && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) + && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE)) + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) { + childObject.put(JsonEditorSchemaConstants.MIN_LENGTH, + constraint.getValue()); + } else { + childObject.put(JsonEditorSchemaConstants.MINIMUM, + constraint.getValue()); + } + } else if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.MAX_LENGTH) + || constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.LESS_OR_EQUAL)) { + // For String max_lenghth is maximum length whereas for number, it will + // be + // maximum or less than the defined value + if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE) + && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) + && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE)) + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) { + childObject.put(JsonEditorSchemaConstants.MAX_LENGTH, + constraint.getValue()); + } else { + childObject.put(JsonEditorSchemaConstants.MAXIMUM, + constraint.getValue()); + } + } else if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.LESS_THAN)) { + childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MAXIMUM, + constraint.getValue()); + } else if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.GREATER_THAN)) { + childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MINIMUM, + constraint.getValue()); + } else if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.IN_RANGE)) { + if (constraint.getValue() instanceof ArrayList<?>) { + if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE) + && (childNodeMap + .get(ToscaSchemaConstants.TYPE) instanceof String) + && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE)) + .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) { + childObject.put(JsonEditorSchemaConstants.MIN_LENGTH, + ((ArrayList) constraint.getValue()).get(0)); + childObject.put(JsonEditorSchemaConstants.MAX_LENGTH, + ((ArrayList) constraint.getValue()).get(1)); + } else { + childObject.put(JsonEditorSchemaConstants.MINIMUM, + ((ArrayList) constraint.getValue()).get(0)); + childObject.put(JsonEditorSchemaConstants.MAXIMUM, + ((ArrayList) constraint.getValue()).get(1)); + } + + } + } else if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.VALID_VALUES)) { + JSONArray validValuesArray = new JSONArray(); + + if (constraint.getValue() instanceof ArrayList<?>) { + boolean processDictionary = + ((ArrayList<?>) constraint.getValue()).stream().anyMatch( + value -> (value instanceof String && ((String) value) + .contains(ToscaSchemaConstants.DICTIONARY))); + if (!processDictionary) { + ((ArrayList<?>) constraint.getValue()).stream() + .forEach(value -> { + validValuesArray.put(value); + }); + childObject.put(JsonEditorSchemaConstants.ENUM, + validValuesArray); + } else { + ((ArrayList<?>) constraint.getValue()).stream() + .forEach(value -> { + if ((value instanceof String && ((String) value) + .contains(ToscaSchemaConstants.DICTIONARY))) { + processDictionaryElements(childObject, + (String) value); + } + + }); + + } + } + + } + }); + } + }); + } + } + + private void parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap, + JSONObject childObject) { + if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA) + && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) { + LinkedHashMap<String, Object> metadataMap = + (LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA); + if (metadataMap instanceof Map) { + metadataMap.entrySet().stream().forEach(constraint -> { + if (constraint.getKey() + .equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) { + JSONArray validValuesArray = new JSONArray(); + + if (constraint.getValue() instanceof ArrayList<?>) { + boolean processDictionary = ((ArrayList<?>) constraint.getValue()) + .stream().anyMatch(value -> (value instanceof String + && ((String) value).contains(ToscaSchemaConstants.DICTIONARY))); + if (processDictionary) { + ((ArrayList<?>) constraint.getValue()).stream().forEach(value -> { + if ((value instanceof String && ((String) value) + .contains(ToscaSchemaConstants.DICTIONARY))) { + processDictionaryElements(childObject, (String) value); + } + + }); + + } + } + + } + }); + } + } + } + + private void processDictionaryElements(JSONObject childObject, String dictionaryReference) { + if (dictionaryReference.contains("#")) { + String[] dictionaryKeyArray = dictionaryReference + .substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11, + dictionaryReference.length()) + .split("#"); + // We support only one # as of now. + List<DictionaryElement> cldsDictionaryElements = null; + List<DictionaryElement> subDictionaryElements = null; + if (dictionaryKeyArray != null && dictionaryKeyArray.length == 2) { + cldsDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[0]) + .getDictionaryElements().stream().collect(Collectors.toList()); + subDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[1]) + .getDictionaryElements().stream().collect(Collectors.toList()); + + if (cldsDictionaryElements != null) { + List<String> subCldsDictionaryNames = subDictionaryElements.stream() + .map(DictionaryElement::getShortName).collect(Collectors.toList()); + JSONArray jsonArray = new JSONArray(); + + Optional.ofNullable(cldsDictionaryElements).get().stream().forEach(c -> { + JSONObject jsonObject = new JSONObject(); + if (c.getSubDictionary() != null) { + Dictionary subDictionary = + dictionaryService.getDictionary(c.getSubDictionary()); + if (subDictionary != null + && !subDictionary.getDictionaryElements().isEmpty()) { + + jsonObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_INPUT, + JsonEditorSchemaConstants.FORMAT_SELECT); + + List<String> shortNames = new ArrayList<>(); + subDictionary.getDictionaryElements().stream().forEach(c1 -> { + shortNames.add(c1.getShortName()); + }); + jsonObject.put(JsonEditorSchemaConstants.VALUES, shortNames); + } + } + jsonObject.put(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType())); + + if (c.getType() != null + && (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING) + || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME) + || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP))) { + jsonObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1); + + if (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) { + jsonObject.put(JsonEditorSchemaConstants.PLUGIN, + JsonEditorSchemaConstants.DATE_TIME_PICKER); + jsonObject.put(JsonEditorSchemaConstants.INPUT_EVENT, + JsonEditorSchemaConstants.DP_CHANGE); + JSONObject formatJsonObject = new JSONObject(); + formatJsonObject.put(JsonEditorSchemaConstants.FORMAT, + JsonEditorSchemaConstants.DATE_TIME_FORMAT); + jsonObject.put(JsonEditorSchemaConstants.VALIDATION, + formatJsonObject); + } + } + + jsonObject.put(JsonEditorSchemaConstants.ID, c.getName()); + jsonObject.put(JsonEditorSchemaConstants.LABEL, c.getShortName()); + jsonObject.put(JsonEditorSchemaConstants.OPERATORS, subCldsDictionaryNames); + jsonArray.put(jsonObject); + });; + JSONObject filterObject = new JSONObject(); + filterObject.put(JsonEditorSchemaConstants.FILTERS, jsonArray); + + childObject.put(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_QBLDR); + // TO invoke validation on such parameters + childObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1); + childObject.put(JsonEditorSchemaConstants.QSSCHEMA, filterObject); + + } + } + } else { + String dictionaryKey = dictionaryReference.substring( + dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11, + dictionaryReference.length()); + + if (dictionaryKey != null) { + if (dictionaryKey.contains(ToscaSchemaConstants.TYPE_USER_DEFINED)) { + childObject.put(JsonEditorSchemaConstants.ENUM, new ArrayList<>()); + // Add Enum titles for generated translated values during + // JSON instance generation + JSONObject enumTitles = new JSONObject(); + enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES, new ArrayList<>()); + childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles); + } else { + List<DictionaryElement> cldsDictionaryElements = + dictionaryService.getDictionary(dictionaryKey).getDictionaryElements() + .stream().collect(Collectors.toList()); + if (cldsDictionaryElements != null) { + List<String> cldsDictionaryNames = new ArrayList<>(); + List<String> cldsDictionaryFullNames = new ArrayList<>(); + cldsDictionaryElements.stream().forEach(c -> { + // Json type will be translated before Policy creation + if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) { + cldsDictionaryFullNames.add(c.getName()); + } + cldsDictionaryNames.add(c.getShortName()); + }); + + if (!cldsDictionaryFullNames.isEmpty()) { + childObject.put(JsonEditorSchemaConstants.ENUM, + cldsDictionaryFullNames); + // Add Enum titles for generated translated values during JSON instance + // generation + JSONObject enumTitles = new JSONObject(); + enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES, + cldsDictionaryNames); + childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles); + } else { + childObject.put(JsonEditorSchemaConstants.ENUM, cldsDictionaryNames); + } + + } + } + } + } + } + + private String getJsonType(String toscaType) { + String jsonType = null; + if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER) + || toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_NUMBER)) { + jsonType = JsonEditorSchemaConstants.TYPE_INTEGER; + } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) { + jsonType = JsonEditorSchemaConstants.TYPE_DATE_TIME; + } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) { + jsonType = JsonEditorSchemaConstants.TYPE_ARRAY; + } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) { + jsonType = JsonEditorSchemaConstants.TYPE_MAP; + } else { + jsonType = JsonEditorSchemaConstants.TYPE_STRING; + } + return jsonType; + } + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java b/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java new file mode 100644 index 000000000..5832986a1 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import java.io.IOException; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser; +import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParserWithDictionarySupport; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.service.Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ToscaConverterWithDictionarySupport { + + private static final EELFLogger logger = + EELFManager.getInstance().getLogger(ToscaConverterWithDictionarySupport.class); + + private ClampProperties clampProperties; + private ToscaMetadataParser metadataParser; + + /** + * Constructor with Spring support. + * + * @param clampProperties Clamp Spring properties + * @param metadataParser Metadata parser + */ + @Autowired + public ToscaConverterWithDictionarySupport(ClampProperties clampProperties, + ToscaMetadataParserWithDictionarySupport metadataParser) { + this.clampProperties = clampProperties; + this.metadataParser = metadataParser; + } + + /** + * This method converts a tosca file to a json schema. + * It uses some parameters specified in the application.properties. + * + * @param toscaFile The tosca file as String + * @param policyTypeToDecode The policy type to decode + * @param serviceModel The service model associated so that the clamp enrichment could be done if required by + * the tosca model + * @return A json object being a json schema + */ + public JsonObject convertToscaToJsonSchemaObject(String toscaFile, String policyTypeToDecode, + Service serviceModel) { + try { + return new JsonTemplateManager(toscaFile, + clampProperties.getFileContent("tosca.converter.default.datatypes"), + clampProperties.getFileContent("tosca.converter.json.schema.templates")) + .getJsonSchemaForPolicyType(policyTypeToDecode, Boolean.parseBoolean(clampProperties.getStringValue( + "tosca.converter.dictionary.support.enabled")) ? metadataParser : null, serviceModel); + } catch (IOException | UnknownComponentException e) { + logger.error("Unable to convert the tosca properly, exception caught during the decoding", + e); + return new JsonObject(); + } + } + + /** + * This method converts a tosca file to a json schema. + * It uses some parameters specified in the application.properties. + * + * @param toscaFile The tosca file as String + * @param policyTypeToDecode The policy type to decode + * @param serviceModel The service Model so that clamp enrichment could be done if required by tosca model + * @return A String containing the json schema + */ + public String convertToscaToJsonSchemaString(String toscaFile, String policyTypeToDecode, Service serviceModel) { + return JsonUtils.GSON.toJson(this.convertToscaToJsonSchemaObject(toscaFile, policyTypeToDecode, serviceModel)); + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java b/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java new file mode 100644 index 000000000..e30f9158b --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/UnknownComponentException.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +public class UnknownComponentException extends Exception { + public UnknownComponentException(String nameEntry) { + this.getWrongName(nameEntry); + } + + public String getWrongName(String nameEntry) { + return "Unknown Component: " + nameEntry; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java new file mode 100644 index 000000000..83f792f3f --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ArrayField.java @@ -0,0 +1,72 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import java.util.ArrayList;
+
+public class ArrayField {
+
+ private ArrayList<Object> complexFields;
+
+ /**
+ * Constructor from arraryList.
+ *
+ * @param arrayProperties the array properties
+ */
+ public ArrayField(ArrayList<Object> arrayProperties) {
+ this.complexFields = arrayProperties;
+ }
+
+ /**
+ * Each LinkedHashMap is parsed to extract the Array and each of its value. They are casted for the JsonObject.
+ *
+ * @return JsonArray
+ */
+ public JsonArray deploy() {
+
+ JsonArray subPropertyValuesArray = new JsonArray();
+ for (Object arrayElement : complexFields) {
+ //Cast for each Primitive Type
+ String typeValue = arrayElement.getClass().getSimpleName();
+ switch (typeValue) {
+ case "String":
+ subPropertyValuesArray.add((String) arrayElement);
+ break;
+ case "Boolean":
+ subPropertyValuesArray.add((Boolean) arrayElement);
+ break;
+ case "Double":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ case "Integer":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ default:
+ break;
+ }
+ }
+ return subPropertyValuesArray;
+ }
+}
diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java new file mode 100644 index 000000000..d6bd355e3 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/Constraint.java @@ -0,0 +1,222 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplate;
+
+public class Constraint {
+
+ private LinkedHashMap<String, Object> constraints;
+ private JsonTemplate jsonTemplate;
+
+ public Constraint(LinkedHashMap<String, Object> constraints, JsonTemplate jsonTemplate) {
+ this.jsonTemplate = jsonTemplate;
+ this.constraints = constraints;
+ }
+
+ /**
+ * Deploy the linkedhashmap which contains the constraints, to extract them one to one.
+ *
+ * @param jsonSchema The json Schema
+ * @param typeProperty The ype property
+ * @return the json object
+ */
+ public JsonObject deployConstraints(JsonObject jsonSchema, String typeProperty) {
+ for (Entry<String, Object> constraint : constraints.entrySet()) {
+ this.parseConstraint(jsonSchema, constraint.getKey(), constraint.getValue(), typeProperty);
+ }
+ return jsonSchema;
+ }
+
+ /**
+ * Each case of Tosca constraints below parse specifically the field in the JsonObject.
+ *
+ * @param jsonSchema Json Schema
+ * @param nameConstraint Name constraint
+ * @param valueConstraint value constraint
+ * @param typeProperty Type Property
+ */
+ @SuppressWarnings("unchecked")
+ public void parseConstraint(JsonObject jsonSchema, String nameConstraint, Object valueConstraint,
+ String typeProperty) {
+ switch (nameConstraint) {
+ case "equal":
+ checkTemplateField("const", jsonSchema, valueConstraint);
+ break;
+ case "greater_than":
+ checkTemplateField("exclusiveMinimum", jsonSchema, valueConstraint);
+ break;
+ case "greater_or_equal":
+ checkTemplateField("minimum", jsonSchema, valueConstraint);
+ break;
+ case "less_than":
+ checkTemplateField("exclusiveMaximum", jsonSchema, valueConstraint);
+ break;
+ case "less_or_equal":
+ checkTemplateField("maximum", jsonSchema, valueConstraint);
+ break;
+ case "in_range":
+ ArrayList<Integer> limitValues = (ArrayList<Integer>) valueConstraint;
+ checkTemplateField("minimum", jsonSchema, limitValues.get(0));
+ checkTemplateField("maximum", jsonSchema, limitValues.get(1));
+ break;
+ case "pattern":
+ jsonSchema.addProperty(nameConstraint, (String) valueConstraint);
+ break;
+ case "length":
+ this.getSpecificLength(jsonSchema, valueConstraint, typeProperty);
+ break;
+ case "min_length":
+ String[] prefixValues = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, prefixValues[0]);
+ break;
+ case "max_length":
+ String[] maxtab = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, maxtab[0]);
+ break;
+ default://valid_value
+ this.getValueArray(jsonSchema, valueConstraint, typeProperty);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty For the complex components, get a specific number of items/properties
+ */
+ public void getSpecificLength(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ switch (typeProperty.toLowerCase()) {
+ case "string":
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ break;
+ case "array":
+ if (fieldValue.equals(1) && jsonTemplate.hasFields("uniqueItems")) {
+ jsonSchema.addProperty("uniqueItems", true);
+ } else {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Map && List
+ checkTemplateField("minProperties", jsonSchema, fieldValue);
+ checkTemplateField("maxProperties", jsonSchema, fieldValue);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty type property
+ * @param side Get the limits fieldValue for the properties : depend of the type of the component
+ */
+ public void getLimitValue(JsonObject jsonSchema, Object fieldValue, String typeProperty, String side) {
+ switch (typeProperty) {
+ case "string":
+ if (side.equals("min")) {
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Array
+ if (side.equals("min")) {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema Json schema
+ * @param fieldValue field value
+ * @param typeProperty Get as Enum the valid values for the property
+ */
+ public void getValueArray(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ if (jsonTemplate.hasFields("enum")) {
+ JsonArray enumeration = new JsonArray();
+ if (typeProperty.equals("string") || typeProperty.equals("String")) {
+ ArrayList<String> arrayValues = (ArrayList<String>) fieldValue;
+ for (String arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ } else {
+ ArrayList<Number> arrayValues = (ArrayList<Number>) fieldValue;
+ for (Number arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ }
+ }
+ }
+
+ /**
+ * To be done.
+ *
+ * @param field Field
+ * @param jsonSchema Json schema
+ * @param fieldValue Simple way to avoid code duplication
+ */
+ public void checkTemplateField(String field, JsonObject jsonSchema, Object fieldValue) {
+ if (jsonTemplate.hasFields(field)) {
+ String typeField = fieldValue.getClass().getSimpleName();
+ switch (typeField) {
+ case "String":
+ jsonSchema.addProperty(field, (String) fieldValue);
+ break;
+ case "Integer":
+ jsonSchema.addProperty(field, (Integer) fieldValue);
+ break;
+ case "Number":
+ jsonSchema.addProperty(field, (Number) fieldValue);
+ break;
+ case "Boolean":
+ jsonSchema.addProperty(field, (Boolean) fieldValue);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java new file mode 100644 index 000000000..9035a5806 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElement.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.elements; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +public class ToscaElement { + + /** + * name parameter is used as "key", in the LinkedHashMap of Components. + */ + private String name; + private String derivedFrom; + private String version; + private String typeVersion; + private String description; + private LinkedHashMap<String, ToscaElementProperty> properties; + + public ToscaElement() { + } + + /** + * Constructor. + * + * @param name name + * @param derivedFrom derivedFrom + * @param description description + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public ToscaElement(String name, String derivedFrom, String description) { + super(); + this.name = name; + this.derivedFrom = derivedFrom; + this.description = description; + this.properties = new LinkedHashMap(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDerivedFrom() { + return derivedFrom; + } + + public void setDerivedFrom(String derivedFrom) { + this.derivedFrom = derivedFrom; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTypeVersion() { + return typeVersion; + } + + public void setTypeVersion(String typeVersion) { + this.typeVersion = typeVersion; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public LinkedHashMap<String, ToscaElementProperty> getProperties() { + return properties; + } + + public void setProperties(LinkedHashMap<String, ToscaElementProperty> properties) { + this.properties = properties; + } + + public void addProperties(ToscaElementProperty toscaElementProperty) { + this.properties.put(toscaElementProperty.getName(), toscaElementProperty); + } + + public ArrayList<String> propertiesNames() { + return new ArrayList<>(properties.keySet()); + } + + @Override + public String toString() { + return name + ": " + description + ", version: " + version + ", nb de properties: " + properties.size() + + System.getProperty("line.separator") + propertiesNames(); + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java new file mode 100644 index 000000000..c5ab5a18e --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/elements/ToscaElementProperty.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.elements; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; + +public class ToscaElementProperty { + + /** + * name parameter is used as "key", in the LinkedHashMap of Components. + */ + private String name; + private LinkedHashMap<String, Object> items; + + /** + * Constructor. + * + * @param name the name + * @param items the items + */ + public ToscaElementProperty(String name, LinkedHashMap<String, Object> items) { + super(); + this.name = name; + this.items = items; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LinkedHashMap<String, Object> getItems() { + return items; + } + + public void setItems(LinkedHashMap<String, Object> items) { + this.items = items; + } + + /** + * For each primitive value, requires to get each field Value and cast it and add it in a Json. + * + * @param fieldsContent field + * @param fieldName field + * @param value value + */ + public void addFieldToJson(JsonObject fieldsContent, String fieldName, Object value) { + if (value != null) { + String typeValue = value.getClass().getSimpleName(); + switch (typeValue) { + case "String": + fieldsContent.addProperty(fieldName, (String) value); + break; + case "Boolean": + fieldsContent.addProperty(fieldName, (Boolean) value); + break; + case "Double": + fieldsContent.addProperty(fieldName, (Number) value); + break; + case "Integer": + fieldsContent.addProperty(fieldName, (Integer) value); + break; + default: + fieldsContent.add(fieldName, parseArray((ArrayList) value)); + break; + } + } + } + + /** + * If a field value is an Array, create an Instance of ArrayField to insert if in the JsonObject. + * + * @param arrayProperties array pro + * @return a json array + */ + public JsonArray parseArray(ArrayList<Object> arrayProperties) { + JsonArray arrayContent = new JsonArray(); + ArrayList<Object> arrayComponent = new ArrayList<>(); + for (Object itemArray : arrayProperties) { + arrayComponent.add(itemArray); + } + ArrayField af = new ArrayField(arrayComponent); + arrayContent = af.deploy(); + return arrayContent; + } + + /** + * Create an instance of Constraint, to extract the values and add it to the Json (according to the type + * * of the current property). + * + * @param json a json + * @param constraints constraints + * @param jsonTemplate template + */ + @SuppressWarnings("unchecked") + public void addConstraintsAsJson(JsonObject json, ArrayList<Object> constraints, JsonTemplate jsonTemplate) { + for (Object constraint : constraints) { + if (constraint instanceof LinkedHashMap) { + LinkedHashMap<String, Object> valueConstraint = (LinkedHashMap<String, Object>) constraint; + Constraint constraintParser = new Constraint(valueConstraint, jsonTemplate); + constraintParser.deployConstraints(json, (String) getItems().get("type")); + } + } + + } + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java new file mode 100644 index 000000000..885e755bd --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java @@ -0,0 +1,76 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.execution; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.PostConstruct; +import org.onap.clamp.clds.tosca.update.execution.cds.ToscaMetadataCdsProcess; +import org.onap.clamp.clds.tosca.update.execution.target.ToscaMetadataTargetProcess; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.tosca.DictionaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * This class is used to execute a code based on a key found in the metadata section. + */ +@Component +public class ToscaMetadataExecutor { + + private static final EELFLogger logger = + EELFManager.getInstance().getLogger(ToscaMetadataExecutor.class); + + @Autowired + private DictionaryService dictionaryService; + + private Map<String, ToscaMetadataProcess> mapOfProcesses = new HashMap<>(); + + /** + * This method executes the required process specified in processInfo. + * + * @param processInfo A String containing the process to execute, like "cds/param1:value1/param2:value2" + * @param childObject The jsonObject + * @param serviceModel The service model associated to do clamp enrichment + */ + public void executeTheProcess(String processInfo, JsonObject childObject, Service serviceModel) { + String[] processParameters = (processInfo + "/ ").split("/"); + logger.info("Executing the Tosca clamp process " + processParameters[0] + " with parameters " + + processParameters[1].trim()); + mapOfProcesses.get(processParameters[0].trim()) + .executeProcess(processParameters[1].trim(), childObject, serviceModel); + } + + /** + * Init method. + */ + @PostConstruct + public void init() { + mapOfProcesses.put("CDS", new ToscaMetadataCdsProcess()); + mapOfProcesses.put("CSAR_RESOURCES", new ToscaMetadataTargetProcess()); + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java new file mode 100644 index 000000000..214eadb03 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.execution; + +import com.google.gson.JsonObject; +import org.onap.clamp.loop.service.Service; + +/** + * This code is the interface that must be implemented to have a tosca process. + */ +public abstract class ToscaMetadataProcess { + + /** + * This method add some elements to the JsonObject childObject passed in argument. + * The process can take multiple parameters in arguments. + * + * @param parameters The parameters required by the process + * @param childObject The Json Object modified by the current process + * @param serviceModel The service model associated to do clamp enrichment + */ + public abstract void executeProcess(String parameters, JsonObject childObject, Service serviceModel); +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java new file mode 100644 index 000000000..39fa25a2b --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java @@ -0,0 +1,220 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.execution.cds; + +import static org.onap.clamp.clds.tosca.ToscaSchemaConstants.TYPE; +import static org.onap.clamp.clds.tosca.ToscaSchemaConstants.TYPE_LIST; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.util.Map; +import java.util.Set; +import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataProcess; +import org.onap.clamp.loop.service.Service; + +/** + * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model. + */ +public class ToscaMetadataCdsProcess extends ToscaMetadataProcess { + + @Override + public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) { + switch (parameters) { + case "actor": + JsonArray jsonArray = new JsonArray(); + jsonArray.add("CDS"); + addToJsonArray(childObject, "enum", jsonArray); + break; + case "payload": + generatePayload(childObject, serviceModel); + break; + case "operation": + generateOperation(childObject, serviceModel); + break; + default: + } + } + + private static void generatePayload(JsonObject childObject, Service serviceModel) { + JsonArray schemaAnyOf = new JsonArray(); + schemaAnyOf.addAll(createBlankEntry()); + schemaAnyOf.addAll(generatePayloadPerResource("VF", serviceModel)); + schemaAnyOf.addAll(generatePayloadPerResource("PNF", serviceModel)); + addToJsonArray(childObject, "anyOf", schemaAnyOf); + } + + private static void generateOperation(JsonObject childObject, Service serviceModel) { + generateOperationPerResource(childObject, "VF", serviceModel); + generateOperationPerResource(childObject, "PNF", serviceModel); + } + + private static void generateOperationPerResource(JsonObject childObject, String resourceName, + Service serviceModel) { + JsonArray schemaEnum = new JsonArray(); + JsonArray schemaTitle = new JsonArray(); + for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName) + .entrySet()) { + JsonObject controllerProperties = entry.getValue().getAsJsonObject() + .getAsJsonObject("controllerProperties"); + if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) { + for (String workflowsEntry : controllerProperties.getAsJsonObject("workflows").keySet()) { + schemaEnum.add(workflowsEntry); + schemaTitle.add(workflowsEntry + " (CDS operation)"); + } + } + } + addToJsonArray(childObject, "enum", schemaEnum); + if (childObject.get("options") == null) { + JsonObject optionsSection = new JsonObject(); + childObject.add("options", optionsSection); + } + addToJsonArray(childObject.getAsJsonObject("options"), "enum_titles", schemaTitle); + + } + + private static JsonArray generatePayloadPerResource(String resourceName, + Service serviceModel) { + JsonArray schemaAnyOf = new JsonArray(); + + for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName) + .entrySet()) { + JsonObject controllerProperties = entry.getValue().getAsJsonObject() + .getAsJsonObject("controllerProperties"); + if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) { + for (Map.Entry<String, JsonElement> workflowsEntry : controllerProperties.getAsJsonObject("workflows") + .entrySet()) { + JsonObject obj = new JsonObject(); + obj.addProperty("title", workflowsEntry.getKey()); + obj.add("properties", + createInputPropertiesForPayload(workflowsEntry.getValue().getAsJsonObject(), + controllerProperties, + workflowsEntry.getKey())); + schemaAnyOf.add(obj); + } + } + } + return schemaAnyOf; + } + + private static JsonArray createBlankEntry() { + JsonArray result = new JsonArray(); + JsonObject blankObject = new JsonObject(); + blankObject.addProperty("title", "User defined"); + blankObject.add("properties", new JsonObject()); + result.add(blankObject); + return result; + } + + private static JsonObject createAnyOfJsonProperty(String name, + String defaultValue, + boolean readOnlyFlag) { + JsonObject result = new JsonObject(); + result.addProperty("title", name); + result.addProperty("type", "string"); + result.addProperty("default", defaultValue); + result.addProperty("readOnly", readOnlyFlag); + return result; + } + + private static void addToJsonArray(JsonObject childObject, String section, JsonArray value) { + if (childObject.getAsJsonArray(section) != null) { + childObject.getAsJsonArray(section).addAll(value); + } else { + childObject.add(section, value); + } + } + + /** + * Returns the properties of payload based on the cds work flows. + * + * @param workFlow cds work flows to update payload + * @param controllerProperties cds properties to get blueprint name and + * version + * @param workFlowName work flow name + * @return returns the properties of payload + */ + public static JsonObject createInputPropertiesForPayload(JsonObject workFlow, + JsonObject controllerProperties, + String workFlowName) { + String artifactName = controllerProperties.get("sdnc_model_name").getAsString(); + String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString(); + JsonObject inputs = workFlow.getAsJsonObject("inputs"); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("artifact_name", createAnyOfJsonProperty( + "artifact name", artifactName, true)); + jsonObject.add("artifact_version", createAnyOfJsonProperty( + "artifact version", artifactVersion, true)); + jsonObject.add("mode", createAnyOfJsonProperty( + "mode", "async", false)); + jsonObject.add("data", createDataProperty(inputs, workFlowName)); + return jsonObject; + } + + private static JsonObject createDataProperty(JsonObject inputs, String workFlowName) { + JsonObject data = new JsonObject(); + data.addProperty("title", "data"); + data.addProperty("type", "string"); + data.addProperty("format", "textarea"); + JsonObject defaultValue = new JsonObject(); + addDefaultValueForData(inputs, defaultValue, workFlowName); + data.addProperty("default", defaultValue.toString()); + return data; + } + + private static void addDefaultValueForData(JsonObject inputs, + JsonObject defaultValue, + String workFlowName) { + Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet(); + for (Map.Entry<String, JsonElement> entry : entrySet) { + String key = entry.getKey(); + JsonObject inputProperty = inputs.getAsJsonObject(key); + if (key.equalsIgnoreCase(workFlowName + "-properties")) { + addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties") + .getAsJsonObject(), defaultValue, workFlowName); + } else if ("object".equalsIgnoreCase(inputProperty.get(TYPE).getAsString())) { + JsonObject object = new JsonObject(); + addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties") + .getAsJsonObject(), object, workFlowName); + defaultValue.add(entry.getKey(), object); + } else if (TYPE_LIST.equalsIgnoreCase(inputProperty.get(TYPE).getAsString())) { + defaultValue.add(entry.getKey(), handleListType(entry.getValue().getAsJsonObject(), workFlowName)); + } else { + defaultValue.addProperty(entry.getKey(), ""); + } + } + } + + private static JsonArray handleListType(JsonObject inputs, + String workFlowName) { + + JsonObject object = new JsonObject(); + if (inputs.get("properties") != null) { + addDefaultValueForData(inputs.get("properties").getAsJsonObject(), object, workFlowName); + } + JsonArray arr = new JsonArray(); + arr.add(object); + return arr; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java b/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java new file mode 100644 index 000000000..8b8fa1784 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/execution/target/ToscaMetadataTargetProcess.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.execution.target; + +import com.google.gson.JsonObject; +import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataProcess; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.policy.operational.OperationalPolicyRepresentationBuilder; + +/** + * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model. + */ +public class ToscaMetadataTargetProcess extends ToscaMetadataProcess { + + @Override + public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) { + childObject.add("anyOf", OperationalPolicyRepresentationBuilder.createAnyOfArray(serviceModel, false)); + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java new file mode 100644 index 000000000..9721e33d9 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java @@ -0,0 +1,346 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.parser; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map.Entry; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; +import org.onap.clamp.loop.service.Service; + +public class ToscaConverterToJsonSchema { + private LinkedHashMap<String, ToscaElement> components; + private LinkedHashMap<String, JsonTemplate> templates; + + private ToscaMetadataParser metadataParser; + + private Service serviceModel; + + /** + * Constructor. + * + * @param toscaElementsMap All the tosca elements found (policy type + data types + native tosca datatypes) + * @param jsonSchemaTemplates All Json schema templates to use + * @param metadataParser The metadata parser to use for metadata section + * @param serviceModel The service model for clamp enrichment + */ + public ToscaConverterToJsonSchema(LinkedHashMap<String, ToscaElement> toscaElementsMap, + LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates, + ToscaMetadataParser metadataParser, Service serviceModel) { + this.components = toscaElementsMap; + this.templates = jsonSchemaTemplates; + this.metadataParser = metadataParser; + this.serviceModel = serviceModel; + } + + /** + * For a given component, launch process to parse it in Json. + * + * @param toscaElementKey name components + * @return return + */ + public JsonObject getJsonSchemaOfToscaElement(String toscaElementKey) { + return this.getFieldAsObject(getToscaElement(toscaElementKey)); + } + + /** + * Return the classical/general fields of the component, & launch the properties deployment. + * + * @param toscaElement the compo + * @return a json object + */ + public JsonObject getFieldAsObject(ToscaElement toscaElement) { + + JsonObject globalFields = new JsonObject(); + if (templates.get("object").hasFields("title")) { + globalFields.addProperty("title", toscaElement.getName()); + } + if (templates.get("object").hasFields("type")) { + globalFields.addProperty("type", "object"); + } + if (templates.get("object").hasFields("description")) { + if (toscaElement.getDescription() != null) { + globalFields.addProperty("description", toscaElement.getDescription()); + } + } + if (templates.get("object").hasFields("required")) { + globalFields.add("required", this.getRequirements(toscaElement.getName())); + } + if (templates.get("object").hasFields("properties")) { + globalFields.add("properties", this.deploy(toscaElement.getName())); + } + return globalFields; + } + + /** + * Get the required properties of the Component, including the parents properties requirements. + * + * @param nameComponent name component + * @return a json array + */ + public JsonArray getRequirements(String nameComponent) { + JsonArray requirements = new JsonArray(); + ToscaElement toParse = components.get(nameComponent); + //Check for a father component, and launch the same process + if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root") + && !toParse.getDerivedFrom().equals("tosca.policies.Root")) { + requirements.addAll(getRequirements(toParse.getDerivedFrom())); + } + //Each property is checked, and add to the requirement array if it's required + Collection<ToscaElementProperty> properties = toParse.getProperties().values(); + for (ToscaElementProperty toscaElementProperty : properties) { + if (toscaElementProperty.getItems().containsKey("required") + && toscaElementProperty.getItems().get("required").equals(true)) { + requirements.add(toscaElementProperty.getName()); + } + } + return requirements; + } + + /** + * The beginning of the recursive process. Get the parents (or not) to launch the same process, and otherwise + * deploy and parse the properties. + * + * @param nameComponent name component + * @return a json object + */ + public JsonObject deploy(String nameComponent) { + JsonObject jsonSchema = new JsonObject(); + ToscaElement toParse = components.get(nameComponent); + //Check for a father component, and launch the same process + if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root") + && !toParse.getDerivedFrom().equals("tosca.policies.Root")) { + jsonSchema = this.getParent(toParse.getDerivedFrom()); + } + //For each component property, check if its a complex properties (a component) or not. In that case, + //launch the analyse of the property. + for (Entry<String, ToscaElementProperty> property : toParse.getProperties().entrySet()) { + if (getToscaElement((String) property.getValue().getItems().get("type")) != null) { + jsonSchema.add(property.getValue().getName(), + this.getJsonSchemaOfToscaElement((String) property.getValue().getItems().get("type"))); + } + else { + jsonSchema.add(property.getValue().getName(), this.complexParse(property.getValue())); + } + } + return jsonSchema; + } + + /** + * If a component has a parent, it is deploy in the same way. + * + * @param nameComponent name component + * @return a json object + */ + public JsonObject getParent(String nameComponent) { + return deploy(nameComponent); + } + + /** + * to be done. + * + * @param toscaElementProperty property + * @return a json object + */ + @SuppressWarnings("unchecked") + public JsonObject complexParse(ToscaElementProperty toscaElementProperty) { + JsonObject propertiesInJson = new JsonObject(); + JsonTemplate currentPropertyJsonTemplate; + String typeProperty = (String) toscaElementProperty.getItems().get("type"); + if (typeProperty.toLowerCase().equals("list") || typeProperty.toLowerCase().equals("map")) { + currentPropertyJsonTemplate = templates.get("object"); + } + else { + String propertyType = (String) toscaElementProperty.getItems().get("type"); + currentPropertyJsonTemplate = templates.get(propertyType.toLowerCase()); + } + //Each "special" field is analysed, and has a specific treatment + for (String propertyField : toscaElementProperty.getItems().keySet()) { + switch (propertyField) { + case "type": + if (currentPropertyJsonTemplate.hasFields(propertyField)) { + String fieldtype = (String) toscaElementProperty.getItems().get(propertyField); + switch (fieldtype.toLowerCase()) { + case "list": + propertiesInJson.addProperty("type", "array"); + break; + case "map": + propertiesInJson.addProperty("type", "object"); + break; + case "scalar-unit.time": + case "scalar-unit.frequency": + case "scalar-unit.size": + propertiesInJson.addProperty("type", "string"); + break; + case "timestamp": + propertiesInJson.addProperty("type", "string"); + propertiesInJson.addProperty("format", "date-time"); + break; + case "float": + propertiesInJson.addProperty("type", "number"); + break; + case "range": + propertiesInJson.addProperty("type", "integer"); + if (!checkConstraintPresence(toscaElementProperty, "greater_than") + && currentPropertyJsonTemplate.hasFields("exclusiveMinimum")) { + propertiesInJson.addProperty("exclusiveMinimum", false); + } + if (!checkConstraintPresence(toscaElementProperty, "less_than") + && currentPropertyJsonTemplate.hasFields("exclusiveMaximum")) { + propertiesInJson.addProperty("exclusiveMaximum", false); + } + break; + default: + propertiesInJson.addProperty("type", currentPropertyJsonTemplate.getName()); + break; + } + } + break; + case "metadata": + if (metadataParser != null) { + metadataParser.processAllMetadataElement(toscaElementProperty, serviceModel).entrySet() + .forEach((jsonEntry) -> { + propertiesInJson.add(jsonEntry.getKey(), + jsonEntry.getValue()); + + }); + } + break; + case "constraints": + toscaElementProperty.addConstraintsAsJson(propertiesInJson, + (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + currentPropertyJsonTemplate); + break; + case "entry_schema": + //Here, a way to check if entry is a component (datatype) or a simple string + if (getToscaElement(this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema")) + != null) { + String nameComponent = this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema"); + ToscaConverterToJsonSchema child = new ToscaConverterToJsonSchema(components, templates, + metadataParser, serviceModel); + JsonObject propertiesContainer = new JsonObject(); + + switch ((String) toscaElementProperty.getItems().get("type")) { + case "map": // Get it as an object + JsonObject componentAsProperty = child.getJsonSchemaOfToscaElement(nameComponent); + propertiesContainer.add(nameComponent, componentAsProperty); + if (currentPropertyJsonTemplate.hasFields("properties")) { + propertiesInJson.add("properties", propertiesContainer); + } + break; + default://list : get it as an Array + JsonObject componentAsItem = child.getJsonSchemaOfToscaElement(nameComponent); + if (currentPropertyJsonTemplate.hasFields("properties")) { + propertiesInJson.add("items", componentAsItem); + propertiesInJson.addProperty("format", "tabs-top"); + } + break; + } + + } + // Native cases + else if (toscaElementProperty.getItems().get("type").equals("list")) { + JsonObject itemContainer = new JsonObject(); + String valueInEntrySchema = + this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema"); + itemContainer.addProperty("type", valueInEntrySchema); + propertiesInJson.add("items", itemContainer); + propertiesInJson.addProperty("format", "tabs-top"); + } + // MAP Case, for now nothing + + break; + default: + //Each classical field : type, description, default.. + if (currentPropertyJsonTemplate.hasFields(propertyField) && !propertyField.equals("required")) { + toscaElementProperty.addFieldToJson(propertiesInJson, propertyField, + toscaElementProperty.getItems().get(propertyField)); + } + break; + } + } + return propertiesInJson; + } + + /** + * Look for a matching Component for the name parameter, in the components list. + * + * @param name the tosca element name to search for + * @return a tosca element + */ + public ToscaElement getToscaElement(String name) { + ToscaElement correspondingToscaElement = null; + if (components == null) { + return null; + } + for (ToscaElement toscaElement : components.values()) { + if (toscaElement.getName().equals(name)) { + correspondingToscaElement = toscaElement; + } + } + return correspondingToscaElement; + } + + /** + * Simple method to extract quickly a type field from particular property item. + * + * @param toscaElementProperty the property + * @param fieldName the fieldname + * @return a string + */ + @SuppressWarnings("unchecked") + public String extractSpecificFieldFromMap(ToscaElementProperty toscaElementProperty, String fieldName) { + LinkedHashMap<String, String> entrySchemaFields = + (LinkedHashMap<String, String>) toscaElementProperty.getItems().get(fieldName); + return entrySchemaFields.get("type"); + } + + /** + * Check if a constraint, for a specific property, is there. + * + * @param toscaElementProperty property + * @param nameConstraint name constraint + * @return a flag boolean + */ + public boolean checkConstraintPresence(ToscaElementProperty toscaElementProperty, String nameConstraint) { + boolean presentConstraint = false; + if (toscaElementProperty.getItems().containsKey("constraints")) { + ArrayList<Object> constraints = (ArrayList) toscaElementProperty.getItems().get("constraints"); + for (Object constraint : constraints) { + if (constraint instanceof LinkedHashMap) { + if (((LinkedHashMap) constraint).containsKey(nameConstraint)) { + presentConstraint = true; + } + } + } + } + return presentConstraint; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java new file mode 100644 index 000000000..090fcfcfa --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/ToscaElementParser.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.parser; + +import java.util.LinkedHashMap; +import java.util.Map.Entry; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.yaml.snakeyaml.Yaml; + +public class ToscaElementParser { + /** + * Constructor. + */ + private ToscaElementParser() { + } + + private static LinkedHashMap<String, Object> searchAllDataTypesAndPolicyTypes(String toscaYaml) { + LinkedHashMap<String, LinkedHashMap<String, Object>> file = + (LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaYaml); + LinkedHashMap<String, Object> allDataTypesFound = file.get("data_types"); + LinkedHashMap<String, Object> allPolicyTypesFound = file.get("policy_types"); + LinkedHashMap<String, Object> allItemsFound = new LinkedHashMap<>(); + // Put the policies and datatypes in the same collection + allItemsFound = (allDataTypesFound == null) ? (new LinkedHashMap<>()) : allDataTypesFound; + allItemsFound.putAll(allPolicyTypesFound == null ? new LinkedHashMap<>() : allPolicyTypesFound); + return allItemsFound; + } + + private static LinkedHashMap<String, Object> searchAllNativeToscaDataTypes(String toscaNativeYaml) { + return ((LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaNativeYaml)) + .get("data_types"); + } + + /** + * Yaml Parse gets raw policies and datatypes, in different sections : necessary to extract + * all entities and put them at the same level. + * + * @param toscaYaml the tosca model content + * @param nativeToscaYaml the tosca native datatype content + * @return a map of Tosca Element containing all tosca elements found (policy types and datatypes) + */ + public static LinkedHashMap<String, ToscaElement> searchAllToscaElements(String toscaYaml, + String nativeToscaYaml) { + LinkedHashMap<String, Object> allItemsFound = searchAllDataTypesAndPolicyTypes(toscaYaml); + allItemsFound.putAll(searchAllNativeToscaDataTypes(nativeToscaYaml)); + return parseAllItemsFound(allItemsFound); + } + + /** + * With all the component, get as Map, Components and Components properties are created. + * + * @param allMaps maps + */ + private static LinkedHashMap<String, ToscaElement> parseAllItemsFound(LinkedHashMap<String, Object> allMaps) { + LinkedHashMap<String, ToscaElement> allItemsFound = new LinkedHashMap<String, ToscaElement>(); + //Component creations, from the file maps + for (Entry<String, Object> itemToParse : allMaps.entrySet()) { + LinkedHashMap<String, Object> componentBody = (LinkedHashMap<String, Object>) itemToParse.getValue(); + ToscaElement toscaElement = + new ToscaElement(itemToParse.getKey(), (String) componentBody.get("derived_from"), + (String) componentBody.get("description")); + //If policy, version and type_version : + if (componentBody.get("type_version") != null) { + toscaElement.setVersion((String) componentBody.get("type_version")); + toscaElement.setTypeVersion((String) componentBody.get("type_version")); + } + //Properties creation, from the map + if (componentBody.get("properties") != null) { + LinkedHashMap<String, Object> properties = + (LinkedHashMap<String, Object>) componentBody.get("properties"); + for (Entry<String, Object> itemToProperty : properties.entrySet()) { + ToscaElementProperty toscaElementProperty = new ToscaElementProperty(itemToProperty.getKey(), + (LinkedHashMap<String, Object>) itemToProperty.getValue()); + toscaElement.addProperties(toscaElementProperty); + } + } + allItemsFound.put(toscaElement.getName(), toscaElement); + } + return allItemsFound; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java new file mode 100644 index 000000000..f4a48139e --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.parser.metadata; + +import com.google.gson.JsonObject; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.loop.service.Service; + +public interface ToscaMetadataParser { + JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel); +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java new file mode 100644 index 000000000..33e084279 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.parser.metadata; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Optional; +import org.onap.clamp.clds.tosca.JsonEditorSchemaConstants; +import org.onap.clamp.clds.tosca.ToscaSchemaConstants; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataExecutor; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ToscaMetadataParserWithDictionarySupport implements ToscaMetadataParser { + + @Autowired + private ToscaMetadataExecutor toscaMetadataExecutor; + + @Autowired + private DictionaryService dictionaryService; + + /** + * This method is used to start the processing of the metadata field. + * + * @param toscaElementProperty The property metadata as Json Object + * @return The jsonObject structure that must be added to the json schema + */ + public JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel) { + if (dictionaryService != null) { + return parseMetadataPossibleValues(toscaElementProperty.getItems(), dictionaryService, serviceModel, + toscaMetadataExecutor); + } + else { + return null; + } + } + + private static JsonObject parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap, + DictionaryService dictionaryService, Service serviceModel, + ToscaMetadataExecutor toscaMetadataExecutor) { + JsonObject childObject = new JsonObject(); + if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA) + && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) { + ((LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA)).forEach((key, + value) -> { + if (key.equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) { + String[] multipleValues = ((String) value).split(","); + for (String multipleValue : multipleValues) { + if (multipleValue.contains(ToscaSchemaConstants.DICTIONARY)) { + processDictionaryElements(multipleValue, childObject, dictionaryService); + } + if (multipleValue.contains("ClampExecution:")) { + executeClampProcess(multipleValue.replaceAll("ClampExecution:", ""), childObject, + serviceModel, toscaMetadataExecutor); + } + } + + } + }); + } + return childObject; + } + + private static void executeClampProcess(String processInfo, JsonObject childObject, Service serviceModel, + ToscaMetadataExecutor toscaMetadataExecutor) { + toscaMetadataExecutor.executeTheProcess(processInfo, childObject, serviceModel); + } + + /** + * For dictionary with multiple levels (defined by #). + * + * @param dictionaryKeyArray the array containing the different elements + * @param childObject the structure getting the new entries + * @param dictionaryService the dictionary service bean + */ + private static void processComplexDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject, + DictionaryService dictionaryService) { + // We support only one # as of now. + List<DictionaryElement> dictionaryElements = null; + if (dictionaryKeyArray.length == 2) { + dictionaryElements = new ArrayList<>(dictionaryService.getDictionary(dictionaryKeyArray[0]) + .getDictionaryElements()); + JsonArray subDictionaryNames = new JsonArray(); + new ArrayList<DictionaryElement>(dictionaryService.getDictionary(dictionaryKeyArray[1]) + .getDictionaryElements()).forEach(elem -> subDictionaryNames.add(elem.getShortName())); + + JsonArray jsonArray = new JsonArray(); + + Optional.of(dictionaryElements).get().forEach(c -> { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType())); + if (c.getType() != null + && c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) { + jsonObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1); + + } + jsonObject.addProperty(JsonEditorSchemaConstants.ID, c.getName()); + jsonObject.addProperty(JsonEditorSchemaConstants.LABEL, c.getShortName()); + jsonObject.add(JsonEditorSchemaConstants.OPERATORS, subDictionaryNames); + jsonArray.add(jsonObject); + }); + + JsonObject filterObject = new JsonObject(); + filterObject.add(JsonEditorSchemaConstants.FILTERS, jsonArray); + + childObject.addProperty(JsonEditorSchemaConstants.TYPE, + JsonEditorSchemaConstants.TYPE_QBLDR); + // TO invoke validation on such parameters + childObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1); + childObject.add(JsonEditorSchemaConstants.QSSCHEMA, filterObject); + + } + } + + /** + * For dictionary with single entry. + * + * @param dictionaryKeyArray the array containing the different elements + * @param childObject the structure getting the new entries + * @param dictionaryService the dictionary service bean + */ + private static void processSimpleDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject, + DictionaryService dictionaryService) { + JsonArray dictionaryNames = new JsonArray(); + JsonArray dictionaryFullNames = new JsonArray(); + dictionaryService.getDictionary(dictionaryKeyArray[0]).getDictionaryElements().forEach(c -> { + // Json type will be translated before Policy creation + if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) { + dictionaryFullNames.add(c.getName()); + } + dictionaryNames.add(c.getShortName()); + }); + + if (dictionaryFullNames.size() > 0) { + if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) { + childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryFullNames); + } + else { + childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryFullNames); + } + // Add Enum titles for generated translated values during JSON instance + // generation + JsonObject enumTitles = new JsonObject(); + enumTitles.add(JsonEditorSchemaConstants.ENUM_TITLES, dictionaryNames); + if (childObject.get(JsonEditorSchemaConstants.OPTIONS) != null) { + childObject.get(JsonEditorSchemaConstants.OPTIONS).getAsJsonArray().add(enumTitles); + } + else { + childObject.add(JsonEditorSchemaConstants.OPTIONS, enumTitles); + } + + } + else { + if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) { + childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryNames); + } + else { + childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryNames); + } + } + } + + private static void processDictionaryElements(String dictionaryReference, JsonObject childObject, + DictionaryService dictionaryService) { + String[] dictionaryKeyArray = + dictionaryReference.substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11, + dictionaryReference.length()).split("#"); + if (dictionaryKeyArray.length > 1) { + processComplexDictionaryElements(dictionaryKeyArray, childObject, dictionaryService); + } + else { + processSimpleDictionaryElements(dictionaryKeyArray, childObject, dictionaryService); + } + } + + private static String getJsonType(String toscaType) { + String jsonType = null; + if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) { + jsonType = JsonEditorSchemaConstants.TYPE_INTEGER; + } + else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) { + jsonType = JsonEditorSchemaConstants.TYPE_ARRAY; + } + else { + jsonType = JsonEditorSchemaConstants.TYPE_STRING; + } + return jsonType; + } + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java new file mode 100644 index 000000000..f64ba68cf --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplate.java @@ -0,0 +1,224 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.templates; + +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; + +public class JsonTemplate { + + /** + * name parameter is used as "key", in the LinkedHashMap of Templates. + */ + private String name; + private List<JsonTemplateField> jsonTemplateFields; + + public JsonTemplate(String name) { + this.name = name; + this.jsonTemplateFields = new ArrayList<>(); + } + + public JsonTemplate(String name, List<JsonTemplateField> jsonTemplateFields) { + this.name = name; + this.jsonTemplateFields = jsonTemplateFields; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<JsonTemplateField> getJsonTemplateFields() { + return jsonTemplateFields; + } + + public void setJsonTemplateFields(List<JsonTemplateField> jsonTemplateFields) { + this.jsonTemplateFields = jsonTemplateFields; + } + + /** + * Search in fields if fieldName exists. + * + * @param fieldName The field name + * @return Ture if it exists, false otherwise + */ + public boolean hasFields(String fieldName) { + for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) { + if (jsonTemplateField.getTitle().equals(fieldName)) { + return true; + } + } + return false; + } + + /** + * Get a specific Field. + * + * @param fieldName The field name + * @return THe Field found + */ + public JsonTemplateField getSpecificField(String fieldName) { + for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) { + if (jsonTemplateField.getTitle().equals(fieldName)) { + return jsonTemplateField; + } + } + return null; + } + + public void addField(JsonTemplateField jsonTemplateField) { + jsonTemplateFields.add(jsonTemplateField); + } + + public void removeField(JsonTemplateField jsonTemplateField) { + jsonTemplateFields.remove(jsonTemplateField); + } + + /** + * Enable or disable the visibility. + * + * @param nameField THe field name + * @param state True or false + */ + public void setVisibility(String nameField, boolean state) { + for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) { + if (jsonTemplateField.getTitle().equals(nameField)) { + jsonTemplateField.setVisible(state); + } + } + } + + /** + * This method defines if a field is static or not. + * + * @param nameField The name of the field + * @param state true or false + */ + public void setStatic(String nameField, boolean state) { + for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) { + if (jsonTemplateField.getTitle().equals(nameField)) { + jsonTemplateField.setStaticValue(state); + } + } + } + + /** + * This method updates the value of a specfic field. + * + * @param nameField The name of the field + * @param newValue The new value as Object + */ + public void updateValueField(String nameField, Object newValue) { + for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) { + if (jsonTemplateField.getTitle().equals(nameField)) { + jsonTemplateField.setValue(newValue); + } + } + } + + /** + * Compare two templates : size and their contents. + * + * @param jsonTemplate the template + * @return a boolean + */ + public boolean checkFields(JsonTemplate jsonTemplate) { + boolean duplicateFields = false; + if (jsonTemplate.getJsonTemplateFields().size() == this.getJsonTemplateFields().size()) { + int countMatchingFields = 0; + //loop each component of first + for (JsonTemplateField jsonTemplateFieldToCheck : jsonTemplate.getJsonTemplateFields()) { + for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) { + if (jsonTemplateFieldToCheck.compareWithField(jsonTemplateField)) { + countMatchingFields++; + } + } + } + + if (jsonTemplate.getJsonTemplateFields().size() == countMatchingFields) { + duplicateFields = true; + } + } + return duplicateFields; + } + + /** + * This method gets the specific field status. + * + * @param field The field name + * @return true or false + */ + public boolean fieldStaticStatus(String field) { + if (this.hasFields(field) && this.getSpecificField(field).getStaticValue().equals(true) + && this.getSpecificField(field).getValue() != null) { + return true; + } + return false; + } + + public boolean isVisible(String field) { + return this.getSpecificField(field).getVisible(); + } + + /** + * Set the value of a property of the Field in the json. + * + * @param jsonSchema The Json schema + * @param fieldName The Field name + * @param value The value + */ + public void setValue(JsonObject jsonSchema, String fieldName, String value) { + if (isVisible(fieldName)) { + if (fieldStaticStatus(fieldName)) { + String defaultValue = (String) this.getSpecificField(fieldName).getValue(); + jsonSchema.addProperty(fieldName, defaultValue); + } + else { + jsonSchema.addProperty(fieldName, value); + } + } + } + + /** + * Inject a static value in the json. + * + * @param jsonSchema The json schema object + * @param fieldName The field name + */ + public void injectStaticValue(JsonObject jsonSchema, String fieldName) { + if (isVisible(fieldName)) { + JsonTemplateField toInject = this.getSpecificField(fieldName); + jsonSchema.addProperty(fieldName, (String) toInject.getValue()); + } + } + + @Override + public String toString() { + return " templateFields : " + jsonTemplateFields; + } +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java new file mode 100644 index 000000000..a1e15307c --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateField.java @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.templates; + +public class JsonTemplateField { + private String title; + private Object value; + private Boolean visible; + private Boolean staticValue; + + public JsonTemplateField(String title) { + this.title = title; + } + + /** + * Constructor. + * + * @param title The title + * @param value The value + * @param visible visible or not + * @param staticValue The static value + */ + public JsonTemplateField(String title, Object value, Boolean visible, Boolean staticValue) { + this.title = title; + this.value = value; + this.visible = visible; + this.staticValue = staticValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public Boolean getVisible() { + return visible; + } + + public void setVisible(Boolean visible) { + this.visible = visible; + } + + public Boolean getStaticValue() { + return staticValue; + } + + public void setStaticValue(Boolean staticValue) { + this.staticValue = staticValue; + } + + public String toString() { + return title + " " + value + " " + visible + " " + staticValue; + } + + /** + * This method compares two fields. + * + * @param otherField Compare the current object with the one specified + * @return true if they are totally equals, false otherwise + */ + public boolean compareWithField(Object otherField) { + if (this == otherField) { + return true; + } + if (otherField == null || getClass() != otherField.getClass()) { + return false; + } + + JsonTemplateField jsonTemplateField = (JsonTemplateField) otherField; + + if (title != null ? !title.equals(jsonTemplateField.title) : jsonTemplateField.title != null) { + return false; + } + if (value != null ? !value.equals(jsonTemplateField.value) : jsonTemplateField.value != null) { + return false; + } + if (visible != null ? !visible.equals(jsonTemplateField.visible) : jsonTemplateField.visible != null) { + return false; + } + return staticValue != null ? staticValue.equals(jsonTemplateField.staticValue) : + jsonTemplateField.staticValue == null; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + + JsonTemplateField jsonTemplateField = (JsonTemplateField) object; + + return title != null ? title.equals(jsonTemplateField.title) : jsonTemplateField.title == null; + } + + @Override + public int hashCode() { + return title != null ? title.hashCode() : 0; + } + + /** + * This method test the entire equality. + * + * @param jsonTemplateField1 object one + * @param jsonTemplateField2 object two + * @return true if they are totally equals (all attributes, false otherwise + */ + public static boolean fieldsEquals(JsonTemplateField jsonTemplateField1, JsonTemplateField jsonTemplateField2) { + return (jsonTemplateField2.getTitle().equals(jsonTemplateField1.getTitle()) + && jsonTemplateField2.getValue().equals(jsonTemplateField1.getValue()) + && jsonTemplateField2.getVisible().equals(jsonTemplateField1.getVisible()) + && jsonTemplateField2.getStaticValue().equals(jsonTemplateField1.getStaticValue())); + } + +} diff --git a/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java new file mode 100644 index 000000000..0b399ba0b --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/tosca/update/templates/JsonTemplateManager.java @@ -0,0 +1,187 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update.templates; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.onap.clamp.clds.tosca.update.UnknownComponentException; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.parser.ToscaConverterToJsonSchema; +import org.onap.clamp.clds.tosca.update.parser.ToscaElementParser; +import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.service.Service; + +public class JsonTemplateManager { + private LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates; + private LinkedHashMap<String, ToscaElement> toscaElements; + + /** + * Constructor. + * + * @param toscaYamlContent Policy Tosca Yaml content as string + * @param nativeToscaDatatypes The tosca yaml with tosca native datatypes + * @param jsonSchemaTemplates template properties as string + */ + public JsonTemplateManager(String toscaYamlContent, String nativeToscaDatatypes, String jsonSchemaTemplates) { + if (toscaYamlContent != null && !toscaYamlContent.isEmpty()) { + this.toscaElements = ToscaElementParser.searchAllToscaElements(toscaYamlContent, nativeToscaDatatypes); + this.jsonSchemaTemplates = initializeTemplates(jsonSchemaTemplates); + } + else { + toscaElements = null; + } + } + + //GETTERS & SETTERS + public LinkedHashMap<String, ToscaElement> getToscaElements() { + return toscaElements; + } + + public void setToscaElements(LinkedHashMap<String, ToscaElement> toscaElements) { + this.toscaElements = toscaElements; + } + + public LinkedHashMap<String, JsonTemplate> getJsonSchemaTemplates() { + return jsonSchemaTemplates; + } + + public void setJsonSchemaTemplates(LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates) { + this.jsonSchemaTemplates = jsonSchemaTemplates; + } + + /** + * Add a template. + * + * @param name name + * @param jsonTemplateFields fields + */ + public void addTemplate(String name, List<JsonTemplateField> jsonTemplateFields) { + JsonTemplate jsonTemplate = new JsonTemplate(name, jsonTemplateFields); + //If it is true, the operation does not have any interest : + // replace OR put two different object with the same body + if (!jsonSchemaTemplates.containsKey(jsonTemplate.getName()) || !this.hasTemplate(jsonTemplate)) { + this.jsonSchemaTemplates.put(jsonTemplate.getName(), jsonTemplate); + } + } + + /** + * By name, find and remove a given template. + * + * @param nameTemplate name template + */ + public void removeTemplate(String nameTemplate) { + this.jsonSchemaTemplates.remove(nameTemplate); + } + + /** + * Update Template : adding with true flag, removing with false. + * + * @param nameTemplate name template + * @param jsonTemplateField field name + * @param operation operation + */ + public void updateTemplate(String nameTemplate, JsonTemplateField jsonTemplateField, Boolean operation) { + // Operation = true && field is not present => add Field + if (operation + && !this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) { + this.jsonSchemaTemplates.get(nameTemplate).addField(jsonTemplateField); + } + // Operation = false && field is present => remove Field + else if (!operation + && this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) { + this.jsonSchemaTemplates.get(nameTemplate).removeField(jsonTemplateField); + } + } + + /** + * Check if the JSONTemplates have the same bodies. + * + * @param jsonTemplate template + * @return a boolean + */ + public boolean hasTemplate(JsonTemplate jsonTemplate) { + boolean duplicateTemplate = false; + Collection<String> templatesName = jsonSchemaTemplates.keySet(); + if (templatesName.contains(jsonTemplate.getName())) { + JsonTemplate existingJsonTemplate = jsonSchemaTemplates.get(jsonTemplate.getName()); + duplicateTemplate = existingJsonTemplate.checkFields(jsonTemplate); + } + return duplicateTemplate; + } + + /** + * For a given policy type, get a corresponding JsonObject from the tosca model. + * + * @param policyType The policy type in the tosca + * @param toscaMetadataParser The MetadataParser class that must be used if metadata section are encountered, if null + * they will be skipped + * @return an json object defining the equivalent json schema from the tosca for a given policy type + */ + public JsonObject getJsonSchemaForPolicyType(String policyType, ToscaMetadataParser toscaMetadataParser, + Service serviceModel) + throws UnknownComponentException { + ToscaConverterToJsonSchema + toscaConverterToJsonSchema = new ToscaConverterToJsonSchema(toscaElements, jsonSchemaTemplates, + toscaMetadataParser, serviceModel); + if (toscaConverterToJsonSchema.getToscaElement(policyType) == null) { + throw new UnknownComponentException(policyType); + } + return toscaConverterToJsonSchema.getJsonSchemaOfToscaElement(policyType); + } + + /** + * Create and complete several Templates from file.properties. + * + * @param jsonTemplates The template properties as String + * @return a map + */ + @SuppressWarnings("unused") + private LinkedHashMap<String, JsonTemplate> initializeTemplates(String jsonTemplates) { + + LinkedHashMap<String, JsonTemplate> generatedTemplates = new LinkedHashMap<>(); + JsonObject templates = JsonUtils.GSON.fromJson(jsonTemplates, JsonObject.class); + + for (Map.Entry<String, JsonElement> templateAsJson : templates.entrySet()) { + JsonTemplate jsonTemplate = new JsonTemplate(templateAsJson.getKey()); + JsonObject templateBody = (JsonObject) templateAsJson.getValue(); + for (Map.Entry<String, JsonElement> field : templateBody.entrySet()) { + String fieldName = field.getKey(); + JsonObject bodyFieldAsJson = (JsonObject) field.getValue(); + Object fieldValue = bodyFieldAsJson.get("defaultValue").getAsString(); + Boolean fieldVisible = bodyFieldAsJson.get("visible").getAsBoolean(); + Boolean fieldStatic = bodyFieldAsJson.get("static").getAsBoolean(); + JsonTemplateField + bodyJsonTemplateField = new JsonTemplateField(fieldName, fieldValue, fieldVisible, fieldStatic); + jsonTemplate.getJsonTemplateFields().add(bodyJsonTemplateField); + } + generatedTemplates.put(jsonTemplate.getName(), jsonTemplate); + } + return generatedTemplates; + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java b/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java new file mode 100644 index 000000000..ec0162cb1 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/ClampVersioning.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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============================================ + * Modifications copyright (c) 2018 Nokia + * =================================================================== + * + */ + +package org.onap.clamp.clds.util; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.io.InputStream; +import java.util.Properties; + +/** + * This class give a way to know the Clamp version easily, the version in that + * file is set by maven at build time. + * + */ +public class ClampVersioning { + private static final String RESOURCE_NAME = "clds-version.properties"; + private static final String CLDS_VERSION_PROPERTY = "clds.version"; + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ClampVersioning.class); + + private ClampVersioning() { + } + + /** + * Returns Clds version from properties. + * + * @return Clds version from properties + */ + public static String getCldsVersionFromProps() { + String cldsVersion = ""; + Properties props = new Properties(); + try (InputStream resourceStream = ResourceFileUtils.getResourceAsStream(RESOURCE_NAME)) { + props.load(resourceStream); + cldsVersion = props.getProperty(CLDS_VERSION_PROPERTY); + } catch (Exception ex) { + LOGGER.error("Exception caught during the " + CLDS_VERSION_PROPERTY + " property reading", ex); + } + return cldsVersion; + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java b/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java new file mode 100644 index 000000000..1ddf3a90a --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/CryptoUtils.java @@ -0,0 +1,168 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.util; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.common.base.Charsets; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.util.Properties; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang3.ArrayUtils; + +/** + * CryptoUtils for encrypting/decrypting string based on a Key defined in + * application.properties (Spring config file). + */ +public final class CryptoUtils { + + /** + * Used to log CryptoUtils class. + */ + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CryptoUtils.class); + // Openssl commands: + // Encrypt: echo -n "123456" | openssl aes-128-cbc -e -K <Private Hex key> + // -iv <16 Bytes iv (HEX), be careful it's 32 Hex Chars> | xxd -u -g100 + // Final result is to put in properties file is: IV + Outcome of openssl + // command + // ************************************************************ + // Decrypt: echo -n 'Encrypted string' | xxd -r -ps | openssl aes-128-cbc -d + // -K + // <Private Hex Key> -iv <16 Bytes IV extracted from Encrypted String, be + // careful it's 32 Hex Chars> + /** + * Definition of encryption algorithm. + */ + private static final String ALGORITHM = "AES"; + + /** + * AES Encryption Key environment variable for external configuration. + */ + private static final String AES_ENCRYPTION_KEY = "AES_ENCRYPTION_KEY"; + + /** + * Detailed definition of encryption algorithm. + */ + private static final String ALGORITHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING"; + private static final int IV_BLOCK_SIZE_IN_BITS = 128; + /** + * An Initial Vector of 16 Bytes, so 32 Hexadecimal Chars. + */ + private static final int IV_BLOCK_SIZE_IN_BYTES = IV_BLOCK_SIZE_IN_BITS / 8; + /** + * Key to read in the key.properties file. + */ + private static final String KEY_PARAM = "org.onap.clamp.encryption.aes.key"; + private static final String PROPERTIES_FILE_NAME = "clds/key.properties"; + /** + * The SecretKeySpec created from the Base 64 String key. + */ + private static final SecretKeySpec SECRET_KEY_SPEC = readSecretKeySpec(PROPERTIES_FILE_NAME); + + /** + * Private constructor to avoid creating instances of util class. + */ + private CryptoUtils() { + } + + /** + * Encrypt a value based on the Clamp Encryption Key. + * + * @param value The value to encrypt + * @return The encrypted string + * @throws GeneralSecurityException In case of issue with the encryption + * @throws UnsupportedEncodingException In case of issue with the charset + * conversion + */ + public static String encrypt(String value) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE"); + byte[] iv = new byte[IV_BLOCK_SIZE_IN_BYTES]; + SecureRandom.getInstance("SHA1PRNG").nextBytes(iv); + IvParameterSpec ivspec = new IvParameterSpec(iv); + cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY_SPEC, ivspec); + return Hex.encodeHexString(ArrayUtils.addAll(iv, cipher.doFinal(value.getBytes(Charsets.UTF_8)))); + } + + /** + * Decrypt a value based on the Clamp Encryption Key. + * + * @param message The encrypted string that must be decrypted using the Clamp + * Encryption Key + * @return The String decrypted + * @throws GeneralSecurityException In case of issue with the encryption + * @throws DecoderException In case of issue to decode the HexString + */ + public static String decrypt(String message) throws GeneralSecurityException, DecoderException { + byte[] encryptedMessage = Hex.decodeHex(message.toCharArray()); + Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE"); + IvParameterSpec ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, IV_BLOCK_SIZE_IN_BYTES)); + byte[] realData = ArrayUtils.subarray(encryptedMessage, IV_BLOCK_SIZE_IN_BYTES, encryptedMessage.length); + cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY_SPEC, ivspec); + byte[] decrypted = cipher.doFinal(realData); + return new String(decrypted); + } + + /** + * Method used to generate the SecretKeySpec from a Base64 String. + * + * @param keyString The key as a string in Base 64 + * @return The SecretKeySpec created + * @throws DecoderException In case of issues with the decoding of Base64 + */ + private static SecretKeySpec getSecretKeySpec(String keyString) throws DecoderException { + byte[] key = Hex.decodeHex(keyString.toCharArray()); + return new SecretKeySpec(key, ALGORITHM); + } + + /** + * Reads SecretKeySpec from file specified by propertiesFileName. + * + * @param propertiesFileName File name with properties + * @return SecretKeySpec secret key spec read from propertiesFileName + */ + private static SecretKeySpec readSecretKeySpec(String propertiesFileName) { + Properties props = new Properties(); + try { + // Workaround fix to make encryption key configurable + // System environment variable takes precedence for over clds/key.properties + String encryptionKey = System.getenv(AES_ENCRYPTION_KEY); + if (encryptionKey != null && encryptionKey.trim().length() > 0) { + return getSecretKeySpec(encryptionKey); + } else { + props.load(ResourceFileUtils.getResourceAsStream(propertiesFileName)); + return getSecretKeySpec(props.getProperty(KEY_PARAM)); + } + } catch (IOException | DecoderException e) { + logger.error("Exception occurred during the key reading", e); + return null; + } + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/JsonUtils.java b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java new file mode 100644 index 000000000..8024331f2 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/JsonUtils.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018-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.clds.util; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.time.Instant; + +import org.onap.clamp.authorization.SecureServicePermission; +import org.onap.clamp.authorization.SecureServicePermissionDeserializer; +import org.onap.clamp.dao.model.gson.converter.InstantDeserializer; +import org.onap.clamp.dao.model.gson.converter.InstantSerializer; + +/** + * This class is used to access the GSON with restricted type access. + */ +public class JsonUtils { + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(JsonUtils.class); + + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(SecureServicePermission.class, new SecureServicePermissionDeserializer()).create(); + + public static final Gson GSON_JPA_MODEL = new GsonBuilder() + .registerTypeAdapter(Instant.class, new InstantSerializer()) + .registerTypeAdapter(Instant.class, new InstantDeserializer()).setPrettyPrinting() + .excludeFieldsWithoutExposeAnnotation().create(); + + private JsonUtils() { + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/LogMessages.java b/src/main/java/org/onap/clamp/clds/util/LogMessages.java new file mode 100644 index 000000000..7f4c8781f --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/LogMessages.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.util; + +import com.att.eelf.i18n.EELFResolvableErrorEnum; +import com.att.eelf.i18n.EELFResourceManager; + +public enum LogMessages implements EELFResolvableErrorEnum { + LOGSERVICE_HELLO_MESSAGE, LOGSERVICE_EMAIL_ERROR, LOGSERVICE_EMAIL_CLASS, LOGSERVICE_EMAIL_CLASS_NULL, + PROCESS_INSTANCE_ID; + + static { + EELFResourceManager.loadMessageBundle("logmessages"); + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java new file mode 100644 index 000000000..0ac1a14fc --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/LoggingUtils.java @@ -0,0 +1,414 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.util; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URLConnection; +import java.net.UnknownHostException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +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; +import org.onap.clamp.authorization.AuthorizationController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.event.Level; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * This class handles the special info that appear in the log, like RequestID, + * time context, ... + */ +public class LoggingUtils { + + protected static final Logger logger = LoggerFactory.getLogger(LoggingUtils.class); + + private static final DateFormat DATE_FORMAT = createDateFormat(); + + private static final String DATE_FORMATTER_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; + + /** String constant for messages <tt>ENTERING</tt>, <tt>EXITING</tt>, etc. */ + private static final String EMPTY_MESSAGE = ""; + + /** Logger delegate. */ + private Logger mlogger; + + /** Automatic UUID, overrideable per adapter or per invocation. */ + private static UUID sInstanceUUID = UUID.randomUUID(); + + /** + * Constructor. + */ + public LoggingUtils(final Logger loggerP) { + this.mlogger = checkNotNull(loggerP); + } + + /** + * Set request related logging variables in thread local data via MDC. + * + * @param service Service Name of API (ex. "PUT template") + * @param partner Partner name (client or user invoking API) + */ + public static void setRequestContext(String service, String partner) { + MDC.put("RequestId", UUID.randomUUID().toString()); + MDC.put("ServiceName", service); + MDC.put("PartnerName", partner); + // Defaulting to HTTP/1.1 protocol + MDC.put("Protocol", "HTTP/1.1"); + try { + MDC.put("ServerFQDN", InetAddress.getLocalHost().getCanonicalHostName()); + MDC.put("ServerIPAddress", InetAddress.getLocalHost().getHostAddress()); + } catch (UnknownHostException e) { + logger.error("Failed to initiate setRequestContext", e); + } + } + + /** + * Set time related logging variables in thread local data via MDC. + * + * @param beginTimeStamp Start time + * @param endTimeStamp End time + */ + public static void setTimeContext(@NotNull Date beginTimeStamp, @NotNull Date endTimeStamp) { + MDC.put("EntryTimestamp", generateTimestampStr(beginTimeStamp)); + MDC.put("EndTimestamp", generateTimestampStr(endTimeStamp)); + MDC.put("ElapsedTime", String.valueOf(endTimeStamp.getTime() - beginTimeStamp.getTime())); + } + + /** + * Set response related logging variables in thread local data via MDC. + * + * @param code Response code ("0" indicates success) + * @param description Response description + * @param className class name of invoking class + */ + public static void setResponseContext(String code, String description, String className) { + MDC.put("ResponseCode", code); + MDC.put("StatusCode", "0".equals(code) ? "COMPLETE" : "ERROR"); + MDC.put("ResponseDescription", description != null ? description : ""); + MDC.put("ClassName", className != null ? className : ""); + } + + /** + * Set target related logging variables in thread local data via MDC. + * + * @param targetEntity Target entity (an external/sub component, for ex. "sdc") + * @param targetServiceName Target service name (name of API invoked on target) + */ + public static void setTargetContext(String targetEntity, String targetServiceName) { + MDC.put("TargetEntity", targetEntity != null ? targetEntity : ""); + MDC.put("TargetServiceName", targetServiceName != null ? targetServiceName : ""); + } + + /** + * Set error related logging variables in thread local data via MDC. + * + * @param code Error code + * @param description Error description + */ + public static void setErrorContext(String code, String description) { + MDC.put("ErrorCode", code); + MDC.put("ErrorDescription", description != null ? description : ""); + } + + private static String generateTimestampStr(Date timeStamp) { + return DATE_FORMAT.format(timeStamp); + } + + /** + * Get a previously stored RequestID for the thread local data via MDC. If + * one was not previously stored, generate one, store it, and return that + * one. + * + * @return A string with the request ID + */ + public static String getRequestId() { + String requestId = MDC.get(OnapLogConstants.Mdcs.REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = UUID.randomUUID().toString(); + MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId); + } + return requestId; + } + + private static DateFormat createDateFormat() { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + return dateFormat; + } + + /********************************************************************************************* + * Method for ONAP Application Logging Specification v1.2 + ********************************************************************************************/ + + /** + * Report <tt>ENTERING</tt> marker. + * + * @param request non-null incoming request (wrapper) + * @param serviceName service name + */ + public void entering(HttpServletRequest request, String serviceName) { + // MDC.clear(); + checkNotNull(request); + // Extract MDC values from standard HTTP headers. + final String requestId = + defaultToUuid(request.getHeader(OnapLogConstants.Headers.REQUEST_ID)); + final String invocationId = + defaultToUuid(request.getHeader(OnapLogConstants.Headers.INVOCATION_ID)); + final String partnerName = + defaultToEmpty(request.getHeader(OnapLogConstants.Headers.PARTNER_NAME)); + + // Default the partner name to the user name used to login to clamp + if (partnerName.equalsIgnoreCase(EMPTY_MESSAGE)) { + MDC.put(OnapLogConstants.Mdcs.PARTNER_NAME, + AuthorizationController.getPrincipalName(SecurityContextHolder.getContext())); + } + + // Set standard MDCs. Override this entire method if you want to set + // others, OR set them BEFORE or AFTER the invocation of #entering, + // depending on where you need them to appear, OR extend the + // ServiceDescriptor to add them. + MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC) + .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO))); + MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId); + MDC.put(OnapLogConstants.Mdcs.INVOCATION_ID, invocationId); + MDC.put(OnapLogConstants.Mdcs.CLIENT_IP_ADDRESS, defaultToEmpty(request.getRemoteAddr())); + MDC.put(OnapLogConstants.Mdcs.SERVER_FQDN, defaultToEmpty(request.getServerName())); + MDC.put(OnapLogConstants.Mdcs.INSTANCE_UUID, defaultToEmpty(sInstanceUUID)); + + // Default the service name to the requestURI, in the event that + // no value has been provided. + if (serviceName == null || serviceName.equalsIgnoreCase(EMPTY_MESSAGE)) { + MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, request.getRequestURI()); + } else { + MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, serviceName); + } + + // Set the Response Status code to in progress + MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE, + OnapLogConstants.ResponseStatus.INPROGRESS.toString()); + setElapsedTime(); + + this.mlogger.info(OnapLogConstants.Markers.ENTRY, "Entering"); + } + + /** + * Report <tt>EXITING</tt> marker. + * + * + * @param code response code + * @param descrption response description + * @param severity response severity + * @param status response status code + */ + public void exiting(int code, String descrption, Level severity, + OnapLogConstants.ResponseStatus status) { + try { + + MDC.put(OnapLogConstants.Mdcs.RESPONSE_CODE, defaultToEmpty(code)); + MDC.put(OnapLogConstants.Mdcs.RESPONSE_DESCRIPTION, defaultToEmpty(descrption)); + MDC.put(OnapLogConstants.Mdcs.RESPONSE_SEVERITY, defaultToEmpty(severity)); + MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE, defaultToEmpty(status)); + + setElapsedTime(); + this.mlogger.info(OnapLogConstants.Markers.EXIT, "Exiting"); + } finally { + MDC.clear(); + } + } + + private void setElapsedTime() { + ZonedDateTime startTime = + ZonedDateTime.parse(MDC.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP), + DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC)); + ZonedDateTime endTime = ZonedDateTime.now(ZoneOffset.UTC); + long duration = ChronoUnit.MILLIS.between(startTime, endTime); + MDC.put(OnapLogConstants.Mdcs.ELAPSED_TIME, String.valueOf(duration)); + } + + /** + * Get the property value. + * + * @param name The name of the property + * @return The value of the property + */ + public String getProperties(String name) { + return MDC.get(name); + } + + /** + * Report pending invocation with <tt>INVOKE</tt> marker, + * setting standard ONAP logging headers automatically. + * + * @param con The HTTP url connection + * @param targetEntity The target entity + * @param targetServiceName The target service name + * @return The HTTP url connection + */ + public HttpURLConnection invoke(final HttpURLConnection con, String targetEntity, + String targetServiceName) { + return this.invokeGeneric(con, targetEntity, targetServiceName); + } + + /** + * Report pending invocation with <tt>INVOKE</tt> marker, + * setting standard ONAP logging headers automatically. + * + * @param targetEntity The target entity + * @param targetServiceName The target service name + */ + public void invoke(String targetEntity, String targetServiceName) { + final String invocationId = UUID.randomUUID().toString(); + + 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, "INVOKE"); + this.mlogger.info(OnapLogConstants.Markers.INVOKE_SYNCHRONOUS + "{" + invocationId + "}"); + } + + /** + * Report pending invocation with <tt>INVOKE</tt> marker, + * setting standard ONAP logging headers automatically. + * + * @param con The HTTPS url connection + * @param targetEntity The target entity + * @param targetServiceName The target service name + * @return The HTTPS url connection + */ + public HttpsURLConnection invokeHttps(final HttpsURLConnection con, String targetEntity, + String targetServiceName) { + return this.invokeGeneric(con, targetEntity, targetServiceName); + } + + /** + * Report pending invocation with <tt>INVOKE-RETURN</tt> marker. + */ + public void invokeReturn() { + MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE, + OnapLogConstants.ResponseStatus.COMPLETE.toString()); + // Add the Invoke-return marker and clear the needed MDC + this.mlogger.info(OnapLogConstants.Markers.INVOKE_RETURN, "INVOKE-RETURN"); + invokeReturnContext(); + } + + /** + * Dependency-free nullcheck. + * + * @param in to be checked + * @param <T> argument (and return) type + * @return input arg + */ + private static <T> T checkNotNull(final T in) { + if (in == null) { + throw new NullPointerException(); + } + return in; + } + + /** + * Dependency-free string default. + * + * @param in to be filtered + * @return input string or null + */ + private static String defaultToEmpty(final Object in) { + if (in == null) { + return ""; + } + return in.toString(); + } + + /** + * Dependency-free string default. + * + * @param in to be filtered + * @return input string or null + */ + private static String defaultToUuid(final String in) { + if (in == null) { + return UUID.randomUUID().toString(); + } + return in; + } + + /** + * Set target related logging variables in thread local data via MDC. + * + * @param targetEntity Target entity (an external/sub component, for ex. "sdc") + * @param targetServiceName Target service name (name of API invoked on target) + * @param invocationId The invocation ID + */ + private void invokeContext(String targetEntity, String targetServiceName, String invocationId) { + MDC.put(OnapLogConstants.Mdcs.TARGET_ENTITY, defaultToEmpty(targetEntity)); + MDC.put(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME, defaultToEmpty(targetServiceName)); + MDC.put(OnapLogConstants.Mdcs.INVOCATIONID_OUT, invocationId); + MDC.put(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC) + .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO))); + } + + /** + * Clear target related logging variables in thread local data via MDC. + */ + private void invokeReturnContext() { + MDC.remove(OnapLogConstants.Mdcs.TARGET_ENTITY); + MDC.remove(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME); + MDC.remove(OnapLogConstants.Mdcs.INVOCATIONID_OUT); + MDC.remove(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP); + MDC.remove(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE); + } + + private <T extends URLConnection> T invokeGeneric(final T 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_SYNCHRONOUS + "{" + invocationId + "}"); + return con; + } +} diff --git a/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java b/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java new file mode 100644 index 000000000..8952e5df1 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/OnapLogConstants.java @@ -0,0 +1,304 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.util; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +/** + * Constants for standard ONAP headers, MDCs, etc. + */ +public final class OnapLogConstants { + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Constructors. + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Hide and forbid construction. + */ + private OnapLogConstants() { + throw new UnsupportedOperationException(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Inner classes. + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Marker constants. + */ + public static final class Markers { + + /** Marker reporting invocation. */ + public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE"); + + /** Marker reporting invocation return. */ + public static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN"); + + /** Marker reporting synchronous invocation. */ + public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS"); + + /** Marker reporting asynchronous invocation. */ + public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS"); + + /** Marker reporting entry into a component. */ + public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY"); + + /** Marker reporting exit from a component. */ + public static final Marker EXIT = MarkerFactory.getMarker("EXIT"); + + /** + * Build nested, detached marker. + * + * @param m1 top token. + * @param m2 sub-token. + * @return detached Marker. + */ + private static Marker build(final String m1, final String m2) { + final Marker marker = MarkerFactory.getDetachedMarker(m1); + marker.add(MarkerFactory.getDetachedMarker(m2)); + return marker; + } + + /** + * Hide and forbid construction. + */ + private Markers() { + throw new UnsupportedOperationException(); + } + } + + /** + * MDC name constants. + */ + public static final class Mdcs { + + // Tracing. //////////////////////////////////////////////////////////// + + /** MDC correlating messages for an invocation. */ + public static final String INVOCATION_ID = "InvocationID"; + + public static final String SERVER_INVOCATION_ID = "ServerInvocationId"; + + public static final String CLIENT_INVOCATION_ID = "ClientInvocationId"; + + /** MDC correlating messages for a logical transaction. */ + public static final String REQUEST_ID = "RequestID"; + + /** MDC recording calling partner name. */ + public static final String PARTNER_NAME = "PartnerName"; + + /** MDC recording current service. */ + public static final String SERVICE_NAME = "ServiceName"; + + /** MDC recording target service. */ + public static final String TARGET_SERVICE_NAME = "TargetServiceName"; + + /** MDC recording InvocationID Out. */ + public static final String INVOCATIONID_OUT = "InvocationIDOut"; + + /** MDC recording target entity. */ + public static final String TARGET_ENTITY = "TargetEntity"; + + /** MDC recording target element. */ + public static final String TARGET_ELEMENT = "TargetElement"; + + /** MDC recording current service instance id. */ + public static final String SERVICE_INSTANCE_ID = "ServiceInstanceID"; + + /** MDC recording current instance id. */ + public static final String INSTANCE_UUID = "InstanceID"; + + // Network. //////////////////////////////////////////////////////////// + + /** MDC recording caller address. */ + public static final String CLIENT_IP_ADDRESS = "ClientIPAddress"; + + /** MDC recording server IP address. */ + public static final String SERVER_IP_ADDRESS = "ServerIPAddress"; + + /** MDC recording server FQDN. */ + public static final String SERVER_FQDN = "ServerFQDN"; + + /** MDC recording virtual server name. */ + public static final String VIRTUAL_SERVER_NAME = "VirtualServerName"; + + /** MDC recording context name. */ + public static final String CONTEXT_NAME = "ContextName"; + + /** + * MDC recording timestamp at the start of the current request, + * with the same scope as {@link #REQUEST_ID}. + * + * <p> + * Open issues: + * <ul> + * <ul> + * Easily confused with {@link #INVOKE_TIMESTAMP}. + * </ul> + * <ul> + * No mechanism for propagation between components, e.g. via HTTP headers. + * </ul> + * <ul> + * Whatever mechanism we define, it's going to be costly. + * </ul> + * </ul> + * </p> + */ + public static final String ENTRY_TIMESTAMP = "EntryTimestamp"; + + /** MDC recording timestamp at the start of the current invocation. */ + public static final String INVOKE_TIMESTAMP = "InvokeTimestamp"; + + /** MDC recording elapsed time. */ + public static final String ELAPSED_TIME = "ElapsedTime"; + + /** MDC recording log timestamp. */ + public static final String LOG_TIMESTAMP = "LogTimestamp"; + + // Outcomes. /////////////////////////////////////////////////////////// + + /** MDC reporting outcome code. */ + public static final String RESPONSE_CODE = "ResponseCode"; + + /** MDC reporting outcome description. */ + public static final String RESPONSE_DESCRIPTION = "ResponseDesc"; + + /** MDC reporting severity */ + public static final String RESPONSE_SEVERITY = "Severity"; + + /** MDC reporting response status code */ + public static final String RESPONSE_STATUS_CODE = "StatusCode"; + + /** MDC recording error code. */ + public static final String ERROR_CODE = "ErrorCode"; + + /** MDC recording error description. */ + public static final String ERROR_DESC = "ErrorDesc"; + + // Unsorted. /////////////////////////////////////////////////////////// + + /** + * Hide and forbid construction. + */ + private Mdcs() { + throw new UnsupportedOperationException(); + } + } + + /** + * Header name constants. + */ + public static final class Headers { + + /** HTTP <tt>X-ONAP-RequestID</tt> header. */ + public static final String REQUEST_ID = "X-ONAP-RequestID"; + + /** HTTP <tt>X-InvocationID</tt> header. */ + public static final String INVOCATION_ID = "X-ONAP-InvocationID"; + + /** HTTP <tt>X-ONAP-PartnerName</tt> header. */ + public static final String PARTNER_NAME = "X-ONAP-PartnerName"; + + /** + * Hide and forbid construction. + */ + private Headers() { + throw new UnsupportedOperationException(); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Enums. + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Response success or not, for setting <tt>StatusCode</tt>. + */ + public enum ResponseStatus { + + /** Success. */ + COMPLETE, + + /** Not. */ + ERROR, + + /** In Progress. */ + INPROGRESS + } + + /** + * Synchronous or asynchronous execution, for setting invocation marker. + */ + public enum InvocationMode { + + /** Synchronous, blocking. */ + SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS), + + /** Asynchronous, non-blocking. */ + ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS); + + /** Enum value. */ + private String mString; + + /** Corresponding marker. */ + private Marker mMarker; + + /** + * Construct enum. + * + * @param s enum value. + * @param m corresponding Marker. + */ + InvocationMode(final String s, final Marker m) { + this.mString = s; + this.mMarker = m; + } + + /** + * Get Marker for enum. + * + * @return Marker. + */ + public Marker getMarker() { + return this.mMarker; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return this.mString; + } + } + +} diff --git a/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java new file mode 100644 index 000000000..f858ed2b8 --- /dev/null +++ b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtils.java @@ -0,0 +1,89 @@ +/*- + * ============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.clds.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + +/** + * Utility methods supporting resources accesses. + */ +public final class ResourceFileUtils { + + /** + * getResourceAsStram supports the "file:" prefix as they use URL. + * So here we want to eliminate classpath: prefix, so that this class can get + * files from jar resource or file system. + */ + + private static final String CLASSPATH_PREFIX = "classpath:"; + + /** + * Private constructor to avoid creating instances of util class. + */ + private ResourceFileUtils() { + } + + /** + * Method to access a file from the jar resource folder or file system. + * Give the prefix "classpath:" so that it accesses the jar resource folder (default case) + * or the prefix "file:" so that it accesses the file system. + * + * @param fileName The path of the resource (no prefix it will be a classpath access, + * "classpath:/myfilename" or "file:/myfilename") + * @return The file as inputStream + */ + public static InputStream getResourceAsStream(String fileName) { + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( + fileName.startsWith(CLASSPATH_PREFIX) ? fileName.replaceFirst(CLASSPATH_PREFIX, "") : fileName); + if (is == null) { + throw new IllegalArgumentException("Unable to find resource: " + fileName); + } + return is; + } + + /** + * Method to access a resource file as a string. + * Give the prefix "classpath:" so that it accesses the jar resource folder (default case) + * or the prefix "file:" so that it accesses the file system. + * + * @param fileName The path of the resource (no prefix it will be a classpath access, + * "classpath:/myfilename" or "file:/myfilename") + * @return The file as String + * @throws IOException In case of failure to find the file. + */ + public static String getResourceAsString(String fileName) throws IOException { + try (InputStream is = getResourceAsStream(fileName)) { + return streamToString(is); + } + } + + private static String streamToString(InputStream inputStream) { + try (Scanner scanner = new Scanner(inputStream)) { + Scanner delimitedScanner = scanner.useDelimiter("\\A"); + return delimitedScanner.hasNext() ? delimitedScanner.next() : ""; + } + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java b/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java new file mode 100644 index 000000000..ca5f37656 --- /dev/null +++ b/src/main/java/org/onap/clamp/configuration/ClampGsonDataFormat.java @@ -0,0 +1,172 @@ +/*- + * ============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.configuration; + +import com.google.gson.Gson; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +import org.apache.camel.Exchange; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.DataFormatName; +import org.apache.camel.support.ServiceSupport; +import org.apache.camel.util.IOHelper; +import org.onap.clamp.clds.util.JsonUtils; + +public class ClampGsonDataFormat extends ServiceSupport implements DataFormat, DataFormatName { + private Gson gson; + private Class<?> unmarshalType; + private Type unmarshalGenericType; + private boolean contentTypeHeader = true; + + public ClampGsonDataFormat() { + this(Object.class); + } + + /** + * Use the default Gson {@link Gson} and with a custom unmarshal type. + * + * @param unmarshalType the custom unmarshal type + */ + public ClampGsonDataFormat(Class<?> unmarshalType) { + this(null, unmarshalType); + } + + /** + * Use a custom Gson mapper and and unmarshal type. + * + * @param gson the custom mapper + * @param unmarshalType the custom unmarshal type + */ + public ClampGsonDataFormat(Gson gson, Class<?> unmarshalType) { + this.gson = gson; + this.unmarshalType = unmarshalType; + } + + /** + * Use the default Gson {@link Gson} and with a custom unmarshal generic type. + * + * @param unmarshalGenericType the custom unmarshal generic type + */ + public ClampGsonDataFormat(Type unmarshalGenericType) { + this(null, unmarshalGenericType); + } + + /** + * Use a custom Gson mapper and and unmarshal token type. + * + * @param gson the custom mapper + * @param unmarshalGenericType the custom unmarshal generic type + */ + public ClampGsonDataFormat(Gson gson, Type unmarshalGenericType) { + this.gson = gson; + this.unmarshalGenericType = unmarshalGenericType; + } + + @Override + public String getDataFormatName() { + return "clamp-gson"; + } + + @Override + public void marshal(final Exchange exchange, final Object graph, final OutputStream stream) throws Exception { + try (final OutputStreamWriter osw = new OutputStreamWriter(stream, StandardCharsets.UTF_8); + final BufferedWriter writer = IOHelper.buffered(osw)) { + gson.toJson(graph, writer); + } + + if (contentTypeHeader) { + if (exchange.hasOut()) { + exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "application/json"); + } else { + exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json"); + } + } + } + + @Override + public Object unmarshal(final Exchange exchange, final InputStream stream) throws Exception { + try (final InputStreamReader isr = new InputStreamReader(stream, StandardCharsets.UTF_8); + final BufferedReader reader = IOHelper.buffered(isr)) { + if (unmarshalGenericType == null) { + return gson.fromJson(reader, unmarshalType); + } else { + return gson.fromJson(reader, unmarshalGenericType); + } + } + } + + @Override + protected void doStart() throws Exception { + if (gson == null) { + gson = JsonUtils.GSON_JPA_MODEL; + } + } + + @Override + protected void doStop() throws Exception { + // noop + } + + // Properties + // ------------------------------------------------------------------------- + + public Class<?> getUnmarshalType() { + return this.unmarshalType; + } + + public void setUnmarshalType(Class<?> unmarshalType) { + this.unmarshalType = unmarshalType; + } + + public Type getUnmarshalGenericType() { + return this.unmarshalGenericType; + } + + public void setUnmarshalGenericType(Type unmarshalGenericType) { + this.unmarshalGenericType = unmarshalGenericType; + } + + public boolean isContentTypeHeader() { + return contentTypeHeader; + } + + /** + * If enabled then Gson will set the Content-Type header to + * <tt>application/json</tt> when marshalling. + */ + public void setContentTypeHeader(boolean contentTypeHeader) { + this.contentTypeHeader = contentTypeHeader; + } + + public Gson getGson() { + return this.gson; + } +} diff --git a/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java new file mode 100644 index 000000000..2d63e55fa --- /dev/null +++ b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantDeserializer.java @@ -0,0 +1,47 @@ +/*- + * ============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.dao.model.gson.converter; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; + +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.Locale; + +public class InstantDeserializer implements JsonDeserializer<Instant> { + + DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.US) + .withZone(ZoneId.systemDefault()); + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { + return Instant.parse(json.getAsString()); + + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java new file mode 100644 index 000000000..cdb439e46 --- /dev/null +++ b/src/main/java/org/onap/clamp/dao/model/gson/converter/InstantSerializer.java @@ -0,0 +1,41 @@ +/*- + * ============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.dao.model.gson.converter; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.format.DateTimeFormatter; + +public class InstantSerializer implements JsonSerializer<Instant> { + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(DateTimeFormatter.ISO_INSTANT.format(src)); + } +}
\ No newline at end of file diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java new file mode 100644 index 000000000..f5aba4e11 --- /dev/null +++ b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java @@ -0,0 +1,109 @@ +/*- + * ============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.dao.model.jsontype; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.BasicBinder; +import org.hibernate.type.descriptor.sql.BasicExtractor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +public class JsonStringSqlTypeDescriptor implements SqlTypeDescriptor { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 1103168570216921981L; + + public static final JsonStringSqlTypeDescriptor INSTANCE = new JsonStringSqlTypeDescriptor(); + + @Override + public int getSqlType() { + return Types.OTHER; + } + + @Override + public boolean canBeRemapped() { + return true; + } + + @Override + public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) { + return new BasicBinder<X>(javaTypeDescriptor, this) { + @Override + protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) + throws SQLException { + st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options)); + } + + @Override + protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) + throws SQLException { + st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options)); + } + }; + } + + @Override + public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) { + return new BasicExtractor<X>(javaTypeDescriptor, this) { + @Override + protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException { + return javaTypeDescriptor.wrap(extractJson(rs, name), options); + } + + @Override + protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException { + return javaTypeDescriptor.wrap(extractJson(statement, index), options); + } + + @Override + protected X doExtract(CallableStatement statement, String name, WrapperOptions options) + throws SQLException { + return javaTypeDescriptor.wrap(extractJson(statement, name), options); + } + }; + } + + protected Object extractJson(ResultSet rs, String name) throws SQLException { + return rs.getObject(name); + } + + protected Object extractJson(CallableStatement statement, int index) throws SQLException { + return statement.getObject(index); + } + + protected Object extractJson(CallableStatement statement, String name) throws SQLException { + return statement.getObject(name); + } + +} diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java new file mode 100644 index 000000000..518ec2d04 --- /dev/null +++ b/src/main/java/org/onap/clamp/dao/model/jsontype/JsonTypeDescriptor.java @@ -0,0 +1,107 @@ +/*- + * ============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.dao.model.jsontype; + +import com.google.gson.JsonObject; + +import java.io.Serializable; + +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; +import org.onap.clamp.clds.util.JsonUtils; + +public class JsonTypeDescriptor extends AbstractTypeDescriptor<JsonObject> { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = -3439698221196089003L; + + public static final JsonTypeDescriptor INSTANCE = new JsonTypeDescriptor(); + + /** + * Creates an instance of JsonTypeDescriptor. + */ + public JsonTypeDescriptor() { + super(JsonObject.class, new ImmutableMutabilityPlan<JsonObject>() { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 1169396106518110214L; + + @Override + public Serializable disassemble(JsonObject value) { + return JsonUtils.GSON_JPA_MODEL.toJson(value); + } + + @Override + public JsonObject assemble(Serializable cached) { + return JsonUtils.GSON_JPA_MODEL.fromJson((String) cached, JsonObject.class); + } + + }); + } + + @Override + public String toString(JsonObject value) { + return JsonUtils.GSON_JPA_MODEL.toJson(value); + } + + @Override + public JsonObject fromString(String string) { + return JsonUtils.GSON_JPA_MODEL.fromJson(string, JsonObject.class); + } + + @Override + public <X> X unwrap(JsonObject value, Class<X> type, WrapperOptions options) { + if (value == null) { + return null; + } + + if (String.class.isAssignableFrom(type)) { + return (X) toString(value); + } + + if (JsonObject.class.isAssignableFrom(type)) { + return (X) JsonUtils.GSON_JPA_MODEL.toJson(toString(value)); + } + throw unknownUnwrap(type); + } + + @Override + public <X> JsonObject wrap(X value, WrapperOptions options) { + if (value == null) { + return null; + } + + if (String.class.isInstance(value)) { + return JsonUtils.GSON_JPA_MODEL.fromJson((String) value, JsonObject.class); + } + + throw unknownWrap(value.getClass()); + } + +} diff --git a/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java b/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java new file mode 100644 index 000000000..621fa8dad --- /dev/null +++ b/src/main/java/org/onap/clamp/dao/model/jsontype/StringJsonUserType.java @@ -0,0 +1,52 @@ +/*- + * ============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.dao.model.jsontype; + +import com.google.gson.JsonObject; + +import org.hibernate.type.AbstractSingleColumnStandardBasicType; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +public class StringJsonUserType extends AbstractSingleColumnStandardBasicType<JsonObject> { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = -7929809808079327767L; + + public StringJsonUserType() { + super(JsonStringSqlTypeDescriptor.INSTANCE, JsonTypeDescriptor.INSTANCE); + } + + public StringJsonUserType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor<JsonObject> javaTypeDescriptor) { + super(sqlTypeDescriptor, javaTypeDescriptor); + } + + @Override + public String getName() { + return "json"; + } + +} diff --git a/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java b/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java new file mode 100644 index 000000000..e31406b2c --- /dev/null +++ b/src/main/java/org/onap/clamp/flow/log/FlowLogOperation.java @@ -0,0 +1,101 @@ +/*- + * ============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.flow.log; + +import javax.servlet.http.HttpServletRequest; +import org.apache.camel.Exchange; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.clds.util.OnapLogConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +/** + * The Flow log operations. + */ +@Component +public class FlowLogOperation { + + protected static final Logger logger = LoggerFactory.getLogger(FlowLogOperation.class); + private LoggingUtils util = new LoggingUtils(logger); + + @Autowired + private HttpServletRequest request; + + /** + * Generate the entry log. + * + * @param serviceDesc + * The service description the loop name + */ + public void startLog(Exchange exchange, String serviceDesc) { + util.entering(request, serviceDesc); + exchange.setProperty(OnapLogConstants.Headers.REQUEST_ID, + util.getProperties(OnapLogConstants.Mdcs.REQUEST_ID)); + exchange.setProperty(OnapLogConstants.Headers.INVOCATION_ID, + util.getProperties(OnapLogConstants.Mdcs.INVOCATION_ID)); + exchange.setProperty(OnapLogConstants.Headers.PARTNER_NAME, + util.getProperties(OnapLogConstants.Mdcs.PARTNER_NAME)); + } + + /** + * Generate the exiting log. + */ + public void endLog() { + util.exiting(HttpStatus.OK.value(), "Successful", Level.INFO, + OnapLogConstants.ResponseStatus.COMPLETE); + } + + /** + * Generate the error exiting log. + */ + public void errorLog() { + util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Failed", Level.INFO, + OnapLogConstants.ResponseStatus.ERROR); + } + + /** + * Generate the error exiting log. + */ + public void httpErrorLog() { + + } + + /** + * Generate the invoke log. + */ + public void invokeLog(String targetEntity, String targetServiceName) { + util.invoke(targetEntity, targetServiceName); + } + + /** + * Generate the invoke return marker. + */ + public void invokeReturnLog() { + util.invokeReturn(); + } +} diff --git a/src/main/java/org/onap/clamp/loop/CsarInstaller.java b/src/main/java/org/onap/clamp/loop/CsarInstaller.java new file mode 100644 index 000000000..6752a1a36 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/CsarInstaller.java @@ -0,0 +1,210 @@ +/*- + * ============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.loop; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import org.json.simple.parser.ParseException; +import org.onap.clamp.clds.client.DcaeInventoryServices; +import org.onap.clamp.clds.client.PolicyEngineServices; +import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintMicroService; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintParser; +import org.onap.clamp.clds.sdc.controller.installer.ChainGenerator; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.loop.cds.CdsDataInstaller; +import org.onap.clamp.loop.service.CsarServiceInstaller; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.LoopTemplatesRepository; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +/** + * This class will be instantiated by spring config, and used by Sdc Controller. + * There is no state kept by the bean. It's used to deploy the csar/notification + * received from SDC in DB. + */ +@Component +@Qualifier("csarInstaller") +public class CsarInstaller { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarInstaller.class); + + @Autowired + private PolicyModelsRepository policyModelsRepository; + + @Autowired + private LoopTemplatesRepository loopTemplatesRepository; + + @Autowired + private ChainGenerator chainGenerator; + + @Autowired + private DcaeInventoryServices dcaeInventoryService; + + @Autowired + private CsarServiceInstaller csarServiceInstaller; + + @Autowired + private CdsDataInstaller cdsDataInstaller; + + @Autowired + private PolicyEngineServices policyEngineServices; + + /** + * Verify whether Csar is deployed. + * + * @param csar The Csar Handler + * @return The flag indicating whether Csar is deployed + * @throws SdcArtifactInstallerException The SdcArtifactInstallerException + */ + public boolean isCsarAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException { + boolean alreadyInstalled = csarServiceInstaller.isServiceAlreadyDeployed(csar); + + for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) { + alreadyInstalled = alreadyInstalled + && loopTemplatesRepository.existsById(LoopTemplate.generateLoopTemplateName( + csar.getSdcNotification().getServiceName(), csar.getSdcNotification().getServiceVersion(), + blueprint.getValue().getResourceAttached().getResourceInstanceName(), + blueprint.getValue().getBlueprintArtifactName())); + } + return alreadyInstalled; + } + + /** + * Install the service and loop templates from the csar. + * + * @param csar The Csar Handler + * @throws SdcArtifactInstallerException The SdcArtifactInstallerException + * @throws InterruptedException The InterruptedException + * @throws BlueprintParserException In case of issues with the blueprint + * parsing + */ + public void installTheCsar(CsarHandler csar) + throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException { + logger.info("Installing the CSAR " + csar.getFilePath()); + Service associatedService = csarServiceInstaller.installTheService(csar); + cdsDataInstaller.installCdsServiceProperties(csar, associatedService); + + installTheLoopTemplates(csar, associatedService); + logger.info("Successfully installed the CSAR " + csar.getFilePath()); + } + + /** + * Install the loop templates from the csar. + * + * @param csar The Csar Handler + * @param service The service object that is related to the loop + * @throws SdcArtifactInstallerException The SdcArtifactInstallerException + * @throws InterruptedException The InterruptedException + * @throws BlueprintParserException In case of issues with the blueprint + * parsing + */ + public void installTheLoopTemplates(CsarHandler csar, Service service) + throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException { + try { + logger.info("Installing the Loops"); + for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) { + logger.info("Processing blueprint " + blueprint.getValue().getBlueprintArtifactName()); + loopTemplatesRepository.save(createLoopTemplateFromBlueprint(csar, blueprint.getValue(), service)); + } + logger.info("Successfully installed the Loops "); + } catch (IOException e) { + throw new SdcArtifactInstallerException("Exception caught during the Loop installation in database", e); + } catch (ParseException e) { + throw new SdcArtifactInstallerException("Exception caught during the Dcae query to get ServiceTypeId", e); + } + } + + private LoopTemplate createLoopTemplateFromBlueprint(CsarHandler csar, BlueprintArtifact blueprintArtifact, + Service service) + throws IOException, ParseException, InterruptedException, BlueprintParserException, + SdcArtifactInstallerException { + LoopTemplate newLoopTemplate = new LoopTemplate(); + newLoopTemplate.setBlueprint(blueprintArtifact.getDcaeBlueprint()); + newLoopTemplate.setName(LoopTemplate.generateLoopTemplateName(csar.getSdcNotification().getServiceName(), + csar.getSdcNotification().getServiceVersion(), + blueprintArtifact.getResourceAttached().getResourceInstanceName(), + blueprintArtifact.getBlueprintArtifactName())); + List<BlueprintMicroService> microServicesChain = chainGenerator + .getChainOfMicroServices(BlueprintParser.getMicroServices(blueprintArtifact.getDcaeBlueprint())); + if (microServicesChain.isEmpty()) { + microServicesChain = BlueprintParser.fallbackToOneMicroService(); + } + newLoopTemplate.setModelService(service); + newLoopTemplate.addLoopElementModels(createMicroServiceModels(blueprintArtifact, microServicesChain)); + newLoopTemplate.setMaximumInstancesAllowed(0); + DcaeInventoryResponse dcaeResponse = queryDcaeToGetServiceTypeId(blueprintArtifact); + newLoopTemplate.setDcaeBlueprintId(dcaeResponse.getTypeId()); + return newLoopTemplate; + } + + private HashSet<LoopElementModel> createMicroServiceModels(BlueprintArtifact blueprintArtifact, + List<BlueprintMicroService> microServicesChain) + throws SdcArtifactInstallerException { + HashSet<LoopElementModel> newSet = new HashSet<>(); + for (BlueprintMicroService microService : microServicesChain) { + LoopElementModel loopElementModel = + new LoopElementModel(microService.getModelType(), LoopElementModel.MICRO_SERVICE_TYPE, + null); + newSet.add(loopElementModel); + PolicyModel newPolicyModel = policyEngineServices.createPolicyModelFromPolicyEngine(microService); + if (newPolicyModel != null) { + loopElementModel.addPolicyModel(newPolicyModel); + } else { + throw new SdcArtifactInstallerException( + "Unable to find the policy specified in the blueprint " + + blueprintArtifact.getBlueprintArtifactName() + ") on the Policy Engine:" + + microService.getModelType() + "/" + microService.getModelVersion()); + } + } + return newSet; + } + + /** + * Get the service blueprint Id in the Dcae inventory using the SDC UUID. + * + * @return The DcaeInventoryResponse object containing the dcae values + */ + private DcaeInventoryResponse queryDcaeToGetServiceTypeId(BlueprintArtifact blueprintArtifact) + throws IOException, ParseException, InterruptedException { + return dcaeInventoryService.getDcaeInformation(blueprintArtifact.getBlueprintArtifactName(), + blueprintArtifact.getBlueprintInvariantServiceUuid(), + blueprintArtifact.getResourceAttached().getResourceInvariantUUID()); + } + +} diff --git a/src/main/java/org/onap/clamp/loop/Loop.java b/src/main/java/org/onap/clamp/loop/Loop.java new file mode 100644 index 000000000..36f74221e --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/Loop.java @@ -0,0 +1,391 @@ +/*- + * ============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.loop; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.SortNatural; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; +import org.onap.clamp.loop.common.AuditEntity; +import org.onap.clamp.loop.components.external.DcaeComponent; +import org.onap.clamp.loop.components.external.ExternalComponent; +import org.onap.clamp.loop.components.external.PolicyComponent; +import org.onap.clamp.loop.deploy.DcaeDeployParameters; +import org.onap.clamp.loop.log.LoopLog; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; + +@Entity +@Table(name = "loops") +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public class Loop extends AuditEntity implements Serializable { + + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522707701388642L; + + @Id + @Expose + @Column(nullable = false, name = "name", unique = true) + private String name; + + @Expose + @Column(name = "dcae_deployment_id") + private String dcaeDeploymentId; + + @Expose + @Column(name = "dcae_deployment_status_url") + private String dcaeDeploymentStatusUrl; + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "global_properties_json") + private JsonObject globalPropertiesJson; + + @Expose + @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) + @JoinColumn(name = "service_uuid") + private Service modelService; + + @Expose + @Column(nullable = false, name = "last_computed_state") + @Enumerated(EnumType.STRING) + private LoopState lastComputedState; + + @Expose + @Transient + private final Map<String, ExternalComponent> components = new HashMap<>(); + + @Expose + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true) + private Set<OperationalPolicy> operationalPolicies = new HashSet<>(); + + @Expose + @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) + @JoinTable(name = "loops_to_microservicepolicies", joinColumns = @JoinColumn(name = "loop_name"), + inverseJoinColumns = @JoinColumn(name = "microservicepolicy_name")) + private Set<MicroServicePolicy> microServicePolicies = new HashSet<>(); + + @Expose + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true) + @SortNatural + private SortedSet<LoopLog> loopLogs = new TreeSet<>(); + + @Expose + @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) + @JoinColumn(name = "loop_template_name", nullable = false) + private LoopTemplate loopTemplate; + + private void initializeExternalComponents() { + this.addComponent(new PolicyComponent()); + this.addComponent(new DcaeComponent()); + } + + /** + * Public constructor. + */ + public Loop() { + initializeExternalComponents(); + } + + /** + * Constructor. + */ + public Loop(String name) { + this.name = name; + this.lastComputedState = LoopState.DESIGN; + this.globalPropertiesJson = new JsonObject(); + initializeExternalComponents(); + } + + /** + * This constructor creates a loop from a loop template. + * + * @param name The loop name + * @param loopTemplate The loop template from which a new loop instance must be created + */ + public Loop(String name, LoopTemplate loopTemplate, ToscaConverterWithDictionarySupport toscaConverter) { + this(name); + this.setLoopTemplate(loopTemplate); + this.setModelService(loopTemplate.getModelService()); + loopTemplate.getLoopElementModelsUsed().forEach(element -> { + if (LoopElementModel.MICRO_SERVICE_TYPE.equals(element.getLoopElementModel().getLoopElementType())) { + this.addMicroServicePolicy((MicroServicePolicy) element.getLoopElementModel() + .createPolicyInstance(this, toscaConverter)); + } + else if (LoopElementModel.OPERATIONAL_POLICY_TYPE + .equals(element.getLoopElementModel().getLoopElementType())) { + this.addOperationalPolicy((OperationalPolicy) element.getLoopElementModel() + .createPolicyInstance(this, toscaConverter)); + } + }); + this.setGlobalPropertiesJson(DcaeDeployParameters.getDcaeDeploymentParametersInJson(this)); + } + + public String getName() { + return name; + } + + void setName(String name) { + this.name = name; + } + + public String getDcaeDeploymentId() { + return dcaeDeploymentId; + } + + void setDcaeDeploymentId(String dcaeDeploymentId) { + this.dcaeDeploymentId = dcaeDeploymentId; + } + + public String getDcaeDeploymentStatusUrl() { + return dcaeDeploymentStatusUrl; + } + + void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { + this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl; + } + + public LoopState getLastComputedState() { + return lastComputedState; + } + + void setLastComputedState(LoopState lastComputedState) { + this.lastComputedState = lastComputedState; + } + + public Set<OperationalPolicy> getOperationalPolicies() { + return operationalPolicies; + } + + void setOperationalPolicies(Set<OperationalPolicy> operationalPolicies) { + this.operationalPolicies = operationalPolicies; + } + + public Set<MicroServicePolicy> getMicroServicePolicies() { + return microServicePolicies; + } + + void setMicroServicePolicies(Set<MicroServicePolicy> microServicePolicies) { + this.microServicePolicies = microServicePolicies; + } + + public JsonObject getGlobalPropertiesJson() { + return globalPropertiesJson; + } + + void setGlobalPropertiesJson(JsonObject globalPropertiesJson) { + this.globalPropertiesJson = globalPropertiesJson; + } + + public Set<LoopLog> getLoopLogs() { + return loopLogs; + } + + void setLoopLogs(SortedSet<LoopLog> loopLogs) { + this.loopLogs = loopLogs; + } + + /** + * This method adds an operational policy to the loop. + * + * @param opPolicy the operationalPolicy to add + */ + public void addOperationalPolicy(OperationalPolicy opPolicy) { + operationalPolicies.add(opPolicy); + opPolicy.setLoop(this); + } + + /** + * This method removes an operational policy to the loop. + * + * @param opPolicy the operationalPolicy to add + */ + public void removeOperationalPolicy(OperationalPolicy opPolicy) { + operationalPolicies.remove(opPolicy); + } + + /** + * This method adds an micro service policy to the loop. + * + * @param microServicePolicy the micro service to add + */ + public void addMicroServicePolicy(MicroServicePolicy microServicePolicy) { + microServicePolicies.add(microServicePolicy); + microServicePolicy.getUsedByLoops().add(this); + } + + public void addLog(LoopLog log) { + log.setLoop(this); + this.loopLogs.add(log); + } + + public Service getModelService() { + return modelService; + } + + void setModelService(Service modelService) { + this.modelService = modelService; + } + + public Map<String, ExternalComponent> getComponents() { + refreshDcaeComponents(); + return components; + } + + public ExternalComponent getComponent(String componentName) { + refreshDcaeComponents(); + return this.components.get(componentName); + } + + public void addComponent(ExternalComponent component) { + this.components.put(component.getComponentName(), component); + } + + public LoopTemplate getLoopTemplate() { + return loopTemplate; + } + + public void setLoopTemplate(LoopTemplate loopTemplate) { + this.loopTemplate = loopTemplate; + } + + private void refreshDcaeComponents() { + if (!this.loopTemplate.getUniqueBlueprint()) { + this.components.remove("DCAE"); + for (MicroServicePolicy policy : this.microServicePolicies) { + if (!this.components.containsKey("DCAE_" + policy.getName())) { + this.addComponent(new DcaeComponent(policy.getName())); + } + } + } + } + + /** + * Return the operationalPolicy object with the opPolicyName. + * + * @param opPolicyName The operationalPolicy name + * @return The OperationalPolicy object found in loop object + */ + public OperationalPolicy getOperationalPolicy(String opPolicyName) { + for (OperationalPolicy operationalPolicy : this.getOperationalPolicies()) { + if (operationalPolicy.getName().equals(opPolicyName)) { + return operationalPolicy; + } + } + return null; + } + + /** + * Return the microServicePolicy object with the msPolicyName. + * + * @param msPolicyName The microServicePolicy name + * @return The MicroServicePolicy object found in loop object + */ + public MicroServicePolicy getMicroServicePolicy(String msPolicyName) { + for (MicroServicePolicy microServicePolicy : this.getMicroServicePolicies()) { + if (microServicePolicy.getName().equals(msPolicyName)) { + return microServicePolicy; + } + } + return null; + } + + /** + * Generate the loop name. + * + * @param serviceName The service name + * @param serviceVersion The service version + * @param resourceName The resource name + * @param blueprintFileName The blueprint file name + * @return The generated loop name + */ + public static String generateLoopName(String serviceName, String serviceVersion, String resourceName, + String blueprintFileName) { + StringBuilder buffer = new StringBuilder("LOOP_").append(serviceName).append("_v").append(serviceVersion) + .append("_").append(resourceName).append("_").append(blueprintFileName.replaceAll(".yaml", "")); + return buffer.toString().replace('.', '_').replaceAll(" ", ""); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Loop other = (Loop) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } + else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/org/onap/clamp/loop/LoopController.java b/src/main/java/org/onap/clamp/loop/LoopController.java new file mode 100644 index 000000000..603726f56 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/LoopController.java @@ -0,0 +1,204 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.loop; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.List; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.clds.util.JsonUtils; +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.stereotype.Controller; + +@Controller +public class LoopController { + + private final LoopService loopService; + + private final ToscaConverterWithDictionarySupport toscaConverter; + + private final OperationalPolicyService operationalPolicyService; + + private final MicroServicePolicyService microServicePolicyService; + + private static final Type OPERATIONAL_POLICY_TYPE = new TypeToken<List<OperationalPolicy>>() { + }.getType(); + + private static final Type MICROSERVICE_POLICY_TYPE = new TypeToken<List<MicroServicePolicy>>() { + }.getType(); + + + /** + * Constructor. + * + * @param loopService loopService + * @param operationalPolicyService operationalPolicyService + * @param microServicePolicyService microServicePolicyService + * @param toscaConverter toscaConverter + */ + @Autowired + public LoopController(LoopService loopService, OperationalPolicyService operationalPolicyService, + MicroServicePolicyService microServicePolicyService, + ToscaConverterWithDictionarySupport toscaConverter) { + this.loopService = loopService; + this.toscaConverter = toscaConverter; + this.operationalPolicyService = operationalPolicyService; + this.microServicePolicyService = microServicePolicyService; + } + + public Loop createLoop(String loopName, String templateName) { + return loopService.createLoopFromTemplate(loopName, templateName); + } + + public List<String> getLoopNames() { + return loopService.getClosedLoopNames(); + } + + public Loop getLoop(String loopName) { + return loopService.getLoop(loopName); + } + + /** + * Update the Operational Policy properties. + * + * @param loopName The loop name + * @param operationalPoliciesJson The new Operational Policy properties + * @return The updated loop + */ + public Loop updateOperationalPolicies(String loopName, JsonArray operationalPoliciesJson) { + List<OperationalPolicy> operationalPolicies = JsonUtils.GSON_JPA_MODEL.fromJson(operationalPoliciesJson, + OPERATIONAL_POLICY_TYPE); + return loopService.updateAndSaveOperationalPolicies(loopName, operationalPolicies); + } + + /** + * Update the whole array of MicroService policies properties. + * + * @param loopName The loop name + * @param microServicePoliciesJson The array of all MicroService policies + * properties + * @return The updated loop + */ + public Loop updateMicroservicePolicies(String loopName, JsonArray microServicePoliciesJson) { + List<MicroServicePolicy> microservicePolicies = JsonUtils.GSON_JPA_MODEL.fromJson(microServicePoliciesJson, + MICROSERVICE_POLICY_TYPE); + return loopService.updateAndSaveMicroservicePolicies(loopName, microservicePolicies); + } + + /** + * Update the global properties. + * + * @param loopName The loop name + * @param globalProperties The updated global properties + * @return The updated loop + */ + public Loop updateGlobalPropertiesJson(String loopName, JsonObject globalProperties) { + return loopService.updateAndSaveGlobalPropertiesJson(loopName, globalProperties); + } + + /** + * This method add an operational policy to a loop instance. + * + * @param loopName The loop name + * @param policyType The policy model type + * @param policyVersion The policy model version + * @return The loop modified + */ + public Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException { + return loopService.addOperationalPolicy(loopName, policyType, policyVersion); + } + + /** + * This method removes an operational policy from a loop instance. + * + * @param loopName The loop name + * @param policyType The policy model type + * @param policyVersion The policy model version + * @return The loop modified + */ + public Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) { + return loopService.removeOperationalPolicy(loopName, policyType, policyVersion); + } + + /** + * This method deletes the loop. + * + * @param loopName The loop Name + */ + public void deleteLoop(String loopName) { + loopService.deleteLoop(loopName); + } + + /** + * Update one MicroService policy properties. + * + * @param loopName The loop name + * @param newMicroservicePolicy The new MicroService policy properties + * @return The updated MicroService policy + */ + public MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) { + return loopService.updateMicroservicePolicy(loopName, newMicroservicePolicy); + } + + /** + * Refresh the Operational Policy Json representation of the loop. + * + * @param loop The loop + * @param operationalPolicyName The operational policy name that needs a refresh + * @return The loop object + */ + public Loop refreshOperationalPolicyJsonRepresentation(Loop loop, String operationalPolicyName) { + for (OperationalPolicy operationalPolicy : loop.getOperationalPolicies()) { + if (operationalPolicy.getName().equals(operationalPolicyName)) { + this.operationalPolicyService + .refreshOperationalPolicyJsonRepresentation(operationalPolicy, toscaConverter); + } + } + return loop; + } + + /** + * Refresh the Config Policy Json representation of the loop. + * + * @param loop The loop + * @param microServicePolicyName The microservice policy name that needs a refresh + * @return The loop object + */ + public Loop refreshMicroServicePolicyJsonRepresentation(Loop loop, String microServicePolicyName) { + for (MicroServicePolicy microServicePolicy : loop.getMicroServicePolicies()) { + if (microServicePolicy.getName().equals(microServicePolicyName)) { + this.microServicePolicyService + .refreshMicroServicePolicyJsonRepresentation(microServicePolicy, toscaConverter, loop); + } + } + return loop; + } +} diff --git a/src/main/java/org/onap/clamp/loop/LoopService.java b/src/main/java/org/onap/clamp/loop/LoopService.java new file mode 100644 index 000000000..5f0822816 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/LoopService.java @@ -0,0 +1,190 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.loop; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.List; +import java.util.Set; +import javax.persistence.EntityNotFoundException; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.loop.template.LoopTemplatesService; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelsService; +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.stereotype.Service; + +@Service +public class LoopService { + + @Autowired + private LoopsRepository loopsRepository; + + @Autowired + private MicroServicePolicyService microservicePolicyService; + + @Autowired + private OperationalPolicyService operationalPolicyService; + + @Autowired + private PolicyModelsService policyModelsService; + + @Autowired + private LoopTemplatesService loopTemplateService; + + @Autowired + private ToscaConverterWithDictionarySupport toscaConverter; + + Loop saveOrUpdateLoop(Loop loop) { + return loopsRepository.save(loop); + } + + List<String> getClosedLoopNames() { + return loopsRepository.getAllLoopNames(); + } + + public Loop getLoop(String loopName) { + return loopsRepository.findById(loopName).orElse(null); + } + + public void deleteLoop(String loopName) { + loopsRepository.deleteById(loopName); + } + + /** + * Creates a Loop Instance from Loop Template Name. + * + * @param loopName Name of the Loop to be created + * @param templateName Loop Template to used for Loop + * @return Loop Instance + */ + public Loop createLoopFromTemplate(String loopName, String templateName) { + return loopsRepository + .save(new Loop(loopName, loopTemplateService.getLoopTemplate(templateName), toscaConverter)); + } + + /** + * This method is used to refresh the DCAE deployment status fields. + * + * @param loop The loop instance to be modified + * @param deploymentId The deployment ID as returned by DCAE + * @param deploymentUrl The Deployment URL as returned by DCAE + */ + public void updateDcaeDeploymentFields(Loop loop, String deploymentId, String deploymentUrl) { + loop.setDcaeDeploymentId(deploymentId); + loop.setDcaeDeploymentStatusUrl(deploymentUrl); + loopsRepository.saveAndFlush(loop); + } + + public void updateLoopState(Loop loop, String newState) { + loop.setLastComputedState(LoopState.valueOf(newState)); + loopsRepository.save(loop); + } + + /** + * This method add an operational policy to a loop instance. + * This creates an operational policy from the policy model info and not the loop element model + * + * @param loopName The loop name + * @param policyType The policy model type + * @param policyVersion The policy model version + * @return The loop modified + */ + Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException { + Loop loop = getLoop(loopName); + PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion); + Set<OperationalPolicy> opPolicySet = loop.getOperationalPolicies(); + for (OperationalPolicy opPolicy : opPolicySet) { + if (opPolicy.getPolicyModel().equals(policyModel)) { + throw new IllegalArgumentException( + "This type of Operational Policy is already added to the loop. Please choose another one."); + } + } + if (policyModel == null) { + return null; + } + loop.addOperationalPolicy( + new OperationalPolicy(loop, loop.getModelService(), policyModel, toscaConverter)); + return loopsRepository.saveAndFlush(loop); + } + + /** + * This method remove an operational policy to a loop instance. + * + * @param loopName The loop name + * @param policyType The policy model type + * @param policyVersion The policy model version + * @return The loop modified + */ + Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) { + Loop loop = getLoop(loopName); + PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion); + if (policyModel == null) { + return null; + } + for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) { + if (opPolicy.getPolicyModel().getPolicyModelType().equals(policyType) + && opPolicy.getPolicyModel().getVersion().equals(policyVersion)) { + loop.removeOperationalPolicy(opPolicy); + break; + } + } + return loopsRepository.saveAndFlush(loop); + } + + Loop updateAndSaveOperationalPolicies(String loopName, List<OperationalPolicy> newOperationalPolicies) { + Loop loop = findClosedLoopByName(loopName); + Set<OperationalPolicy> newPolicies = operationalPolicyService.updatePolicies(loop, newOperationalPolicies); + loop.setOperationalPolicies(newPolicies); + return loopsRepository.save(loop); + } + + Loop updateAndSaveMicroservicePolicies(String loopName, List<MicroServicePolicy> newMicroservicePolicies) { + Loop loop = findClosedLoopByName(loopName); + Set<MicroServicePolicy> newPolicies = microservicePolicyService.updatePolicies(loop, newMicroservicePolicies); + loop.setMicroServicePolicies(newPolicies); + return loopsRepository.save(loop); + } + + Loop updateAndSaveGlobalPropertiesJson(String loopName, JsonObject newGlobalPropertiesJson) { + Loop loop = findClosedLoopByName(loopName); + loop.setGlobalPropertiesJson(newGlobalPropertiesJson); + return loopsRepository.save(loop); + } + + MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) { + Loop loop = findClosedLoopByName(loopName); + return microservicePolicyService.getAndUpdateMicroServicePolicy(loop, newMicroservicePolicy); + } + + private Loop findClosedLoopByName(String loopName) { + return loopsRepository.findById(loopName) + .orElseThrow(() -> new EntityNotFoundException("Couldn't find closed loop named: " + loopName)); + } +} + diff --git a/src/main/java/org/onap/clamp/loop/LoopState.java b/src/main/java/org/onap/clamp/loop/LoopState.java new file mode 100644 index 000000000..4707730ce --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/LoopState.java @@ -0,0 +1,28 @@ +/*- + * ============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.loop; + +public enum LoopState { + DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING; +} diff --git a/src/main/java/org/onap/clamp/loop/LoopsRepository.java b/src/main/java/org/onap/clamp/loop/LoopsRepository.java new file mode 100644 index 000000000..aaa49116f --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/LoopsRepository.java @@ -0,0 +1,37 @@ +/*- + * ============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.loop; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface LoopsRepository extends JpaRepository<Loop, String> { + + @Query("SELECT loop.name FROM Loop as loop") + List<String> getAllLoopNames(); +} diff --git a/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java b/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java new file mode 100644 index 000000000..d18cae1d6 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/cds/CdsDataInstaller.java @@ -0,0 +1,173 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * 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. + * 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.loop.cds; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import org.onap.clamp.clds.client.CdsServices; +import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.service.ServicesRepository; +import org.onap.sdc.tosca.parser.enums.SdcTypes; +import org.onap.sdc.toscaparser.api.NodeTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * This class installs the cds data in the service model properties. + * This can be refreshed later on by clicking on the button refresh, when recomputing the json schema. + */ +@Component +public class CdsDataInstaller { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsDataInstaller.class); + + @Autowired + CdsServices cdsServices; + + @Autowired + ServicesRepository serviceRepository; + + public static final String CONTROLLER_PROPERTIES = "controllerProperties"; + public static final String SDNC_MODEL_NAME = "sdnc_model_name"; + public static final String SDNC_MODEL_VERSION = "sdnc_model_version"; + + /** + * This method installs the service model properties for CDS in the service object given in input. + * + * @param csar The csar from sdc + * @param service the service object already provisioned with csar data + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public Service installCdsServiceProperties(CsarHandler csar, Service service) { + // Iterate on all types defined in the tosca lib + for (SdcTypes type : SdcTypes.values()) { + JsonObject resourcesPropByType = service.getResourceByType(type.getValue()); + // For each type, get the metadata of each nodetemplate + for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) { + // get cds artifact information and save in resources Prop + if (SdcTypes.PNF == type || SdcTypes.VF == type) { + JsonObject controllerProperties = createCdsArtifactProperties( + String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_NAME)), + String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_VERSION))); + if (controllerProperties != null) { + resourcesPropByType.getAsJsonObject(nodeTemplate.getName()) + .add(CONTROLLER_PROPERTIES, controllerProperties); + logger.info("Successfully installed the CDS data in Service"); + } + else { + logger.warn("Skipping CDS data installation in Service, as sdnc_model_name and " + + "sdnc_model_version are not provided in the CSAR"); + } + } + } + } + serviceRepository.save(service); + + return service; + } + + /** + * This method updates the service model properties for CDS in the service object given in input. + * + * @param service the service object already provisioned with csar data + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public Service updateCdsServiceProperties(Service service) { + // Iterate on all types defined in the tosca lib + for (SdcTypes type : SdcTypes.values()) { + JsonObject resourcesPropByType = service.getResourceByType(type.getValue()); + for (String resourceName : resourcesPropByType.keySet()) { + // get cds artifact information and save in resources Prop + if ((SdcTypes.PNF == type || SdcTypes.VF == type) && resourcesPropByType.getAsJsonObject(resourceName) + .getAsJsonObject(CONTROLLER_PROPERTIES) != null) { + JsonObject controllerProperties = + createCdsArtifactProperties(resourcesPropByType.getAsJsonObject(resourceName) + .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_NAME) + .getAsString(), + resourcesPropByType.getAsJsonObject(resourceName) + .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_VERSION) + .getAsString()); + if (controllerProperties != null) { + resourcesPropByType.getAsJsonObject(resourceName) + .add(CONTROLLER_PROPERTIES, controllerProperties); + } + } + } + } + serviceRepository.save(service); + logger.info("Successfully updated the CDS data in Service"); + return service; + } + + /** + * Retrieve CDS artifacts information from node template and save in resource object. + * + * @param sdncModelName sdnc model name + * @param sdncModelVersion sdnc model version + * @return Returns CDS artifacts information + */ + private JsonObject createCdsArtifactProperties(String sdncModelName, String sdncModelVersion) { + if (sdncModelName != null && !"null".equals(sdncModelName) + && sdncModelVersion != null && !"null".equals(sdncModelVersion)) { + JsonObject controllerProperties = new JsonObject(); + controllerProperties.addProperty(SDNC_MODEL_NAME, sdncModelName); + controllerProperties.addProperty(SDNC_MODEL_VERSION, sdncModelVersion); + + CdsBpWorkFlowListResponse response = + queryCdsToGetWorkFlowList(sdncModelName, sdncModelVersion); + if (response == null) { + return controllerProperties; + } + + JsonObject workFlowProps = new JsonObject(); + for (String workFlow : response.getWorkflows()) { + logger.info("Found CDS workflow " + workFlow + " for model name " + sdncModelName + " and version " + + sdncModelVersion); + JsonObject inputs = queryCdsToGetWorkFlowInputProperties(response.getBlueprintName(), + response.getVersion(), workFlow); + workFlowProps.add(workFlow, inputs); + } + + 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/loop/common/AuditEntity.java b/src/main/java/org/onap/clamp/loop/common/AuditEntity.java new file mode 100644 index 000000000..7ce12ec6b --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/common/AuditEntity.java @@ -0,0 +1,148 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.common; + +import com.google.gson.annotations.Expose; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +/** + * This class is the parent of the hibernate entities requiring to be audited. + */ +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class AuditEntity { + + @Expose + @CreatedDate + @Column(name = "created_timestamp", nullable = false, updatable = false) + private Instant createdDate; + + @Expose + @LastModifiedDate + @Column(name = "updated_timestamp", nullable = false) + private Instant updatedDate; + + @Expose + @LastModifiedBy + @Column(name = "updated_by") + private String updatedBy; + + @Expose + @CreatedBy + @Column(name = "created_by") + private String createdBy; + + public Instant getCreatedDate() { + return createdDate; + } + + /** + * createdDate setter. + * + * @param createdDate The created Date object + */ + public void setCreatedDate(Instant createdDate) { + if (createdDate != null) { + this.createdDate = createdDate.truncatedTo(ChronoUnit.SECONDS); + } + else { + this.createdDate = null; + } + } + + /** + * updatedDate getter. + * + * @return the updatedDate + */ + public Instant getUpdatedDate() { + return updatedDate; + } + + /** + * updatedDate setter. + * + * @param updatedDate updatedDate to set + */ + public void setUpdatedDate(Instant updatedDate) { + if (updatedDate != null) { + this.updatedDate = updatedDate.truncatedTo(ChronoUnit.SECONDS); + } + else { + this.updatedDate = null; + } + } + + /** + * updatedBy getter. + * + * @return the updatedBy + */ + public String getUpdatedBy() { + return updatedBy; + } + + /** + * updatedBy setter. + * + * @param updatedBy the updatedBy + */ + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + /** + * createdBy getter. + * + * @return the createdBy + */ + public String getCreatedBy() { + return createdBy; + } + + /** + * createdBy setter. + * + * @param createdBy the createdBy to set + */ + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + /** + * Empty constructor. + */ + public AuditEntity() { + } + +} diff --git a/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java b/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java new file mode 100644 index 000000000..8b8547195 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/components/external/DcaeComponent.java @@ -0,0 +1,253 @@ +/*- + * ============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.loop.components.external; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +import javax.persistence.Transient; +import org.apache.camel.Exchange; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse; +import org.onap.clamp.clds.model.dcae.DcaeOperationStatusResponse; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.policy.microservice.MicroServicePolicy; + +public class DcaeComponent extends ExternalComponent { + + @Transient + private static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeComponent.class); + + private static final String DCAE_DEPLOYMENT_PREFIX = "CLAMP_"; + private static final String DEPLOYMENT_PARAMETER = "dcaeDeployParameters"; + private static final String DCAE_SERVICETYPE_ID = "serviceTypeId"; + private static final String DCAE_INPUTS = "inputs"; + public static final String UNIQUE_BLUEPRINT_PARAMETERS = "uniqueBlueprintParameters"; + + private String name; + + public static final ExternalComponentState BLUEPRINT_DEPLOYED = new ExternalComponentState("BLUEPRINT_DEPLOYED", + "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop"); + public static final ExternalComponentState PROCESSING_MICROSERVICE_INSTALLATION = new ExternalComponentState( + "PROCESSING_MICROSERVICE_INSTALLATION", "Clamp has requested DCAE to install the microservices " + + "defined in the DCAE blueprint and it's currently processing the request"); + public static final ExternalComponentState MICROSERVICE_INSTALLATION_FAILED = new ExternalComponentState( + "MICROSERVICE_INSTALLATION_FAILED", + "Clamp has requested DCAE to install the microservices defined in the DCAE blueprint and it failed"); + public static final ExternalComponentState MICROSERVICE_INSTALLED_SUCCESSFULLY = new ExternalComponentState( + "MICROSERVICE_INSTALLED_SUCCESSFULLY", + "Clamp has requested DCAE to install the DCAE blueprint and it has been installed successfully"); + public static final ExternalComponentState PROCESSING_MICROSERVICE_UNINSTALLATION = new ExternalComponentState( + "PROCESSING_MICROSERVICE_UNINSTALLATION", "Clamp has requested DCAE to uninstall the microservices " + + "defined in the DCAE blueprint and it's currently processing the request"); + public static final ExternalComponentState MICROSERVICE_UNINSTALLATION_FAILED = new ExternalComponentState( + "MICROSERVICE_UNINSTALLATION_FAILED", + "Clamp has requested DCAE to uninstall the microservices defined in the DCAE blueprint and it failed"); + public static final ExternalComponentState MICROSERVICE_UNINSTALLED_SUCCESSFULLY = new ExternalComponentState( + "MICROSERVICE_UNINSTALLED_SUCCESSFULLY", + "Clamp has requested DCAE to uninstall the DCAE blueprint and it has been uninstalled successfully"); + public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR", + "There was an error during the request done to DCAE, look at the logs or try again"); + + public DcaeComponent() { + super(BLUEPRINT_DEPLOYED); + this.name = "DCAE"; + } + + public DcaeComponent(String name) { + super(BLUEPRINT_DEPLOYED); + this.name = "DCAE_" + name; + } + + @Override + public String getComponentName() { + return name; + } + + + /** + * Convert the json response to a DcaeOperationStatusResponse. + * + * @param responseBody The DCAE response Json paylaod + * @return The dcae object provisioned + */ + public static DcaeOperationStatusResponse convertDcaeResponse(String responseBody) { + if (responseBody != null && !responseBody.isEmpty()) { + return JsonUtils.GSON_JPA_MODEL.fromJson(responseBody, DcaeOperationStatusResponse.class); + } else { + return null; + } + } + + /** + * Generate the deployment id, it's random. + * + * @return The deployment id + */ + public static String generateDeploymentId() { + return DCAE_DEPLOYMENT_PREFIX + UUID.randomUUID(); + } + + /** + * This method prepare the url returned by DCAE to check the status if fine. It + * extracts it from the dcaeResponse. + * + * @param dcaeResponse The dcae response object + * @return the Right Url modified if needed + */ + public static String getStatusUrl(DcaeOperationStatusResponse dcaeResponse) { + return dcaeResponse.getLinks().getStatus().replaceAll("http:", "http4:").replaceAll("https:", "https4:"); + } + + /** + * Return the deploy payload for DCAE. + * + * @param loop The loop object + * @return The payload used to send deploy closed loop request + */ + public static String getDeployPayload(Loop loop) { + JsonObject globalProp = loop.getGlobalPropertiesJson(); + JsonObject deploymentProp = globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject( + UNIQUE_BLUEPRINT_PARAMETERS); + + String serviceTypeId = loop.getLoopTemplate().getDcaeBlueprintId(); + + JsonObject rootObject = new JsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId); + if (deploymentProp != null) { + rootObject.add(DCAE_INPUTS, deploymentProp); + } + logger.info("DCAE Deploy payload for unique blueprint: " + rootObject.toString()); + return rootObject.toString(); + } + + /** + * Return the deploy payload for DCAE. + * + * @param loop The loop object + * @param microServicePolicy The micro service policy + * @return The payload used to send deploy closed loop request + */ + public static String getDeployPayload(Loop loop, MicroServicePolicy microServicePolicy) { + JsonObject globalProp = loop.getGlobalPropertiesJson(); + JsonObject deploymentProp = + globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject(microServicePolicy.getName()); + + String serviceTypeId = microServicePolicy.getDcaeBlueprintId(); + + JsonObject rootObject = new JsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId); + if (deploymentProp != null) { + rootObject.add(DCAE_INPUTS, deploymentProp); + } + logger.info("DCAE Deploy payload for multiple blueprints: " + rootObject.toString()); + return rootObject.toString(); + } + + /** + * Return the uninstallation payload for DCAE. + * + * @param loop The loop object + * @return The payload in string (json) + */ + public static String getUndeployPayload(Loop loop) { + JsonObject rootObject = new JsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, loop.getLoopTemplate().getDcaeBlueprintId()); + logger.info("DCAE Undeploy payload for unique blueprint: " + rootObject.toString()); + return rootObject.toString(); + } + + /** + * Return the uninstallation payload for DCAE. + * + * @param policy The microServicePolicy object + * @return The payload in string (json) + */ + public static String getUndeployPayload(MicroServicePolicy policy) { + JsonObject rootObject = new JsonObject(); + rootObject.addProperty(DCAE_SERVICETYPE_ID, policy.getDcaeBlueprintId()); + logger.info("DCAE Undeploy payload for multiple blueprints: " + rootObject.toString()); + return rootObject.toString(); + } + + @Override + public ExternalComponentState computeState(Exchange camelExchange) { + + DcaeOperationStatusResponse dcaeResponse = (DcaeOperationStatusResponse) camelExchange.getIn().getExchange() + .getProperty("dcaeResponse"); + + if (dcaeResponse == null) { + setState(BLUEPRINT_DEPLOYED); + } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("succeeded")) { + setState(MICROSERVICE_INSTALLED_SUCCESSFULLY); + } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("processing")) { + setState(PROCESSING_MICROSERVICE_INSTALLATION); + } else if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("failed")) { + setState(MICROSERVICE_INSTALLATION_FAILED); + } else if (dcaeResponse.getOperationType().equals("uninstall") + && dcaeResponse.getStatus().equals("succeeded")) { + setState(MICROSERVICE_UNINSTALLED_SUCCESSFULLY); + } else if (dcaeResponse.getOperationType().equals("uninstall") + && dcaeResponse.getStatus().equals("processing")) { + setState(PROCESSING_MICROSERVICE_UNINSTALLATION); + } else if (dcaeResponse.getOperationType().equals("uninstall") && dcaeResponse.getStatus().equals("failed")) { + setState(MICROSERVICE_UNINSTALLATION_FAILED); + } else { + setState(IN_ERROR); + } + return this.getState(); + } + + /** + * Convert the json response to a DcaeInventoryResponse. + * + * @param responseBody The DCAE response Json paylaod + * @return list of DcaeInventoryResponse + * @throws ParseException In case of issues with the Json parsing + */ + public static List<DcaeInventoryResponse> convertToDcaeInventoryResponse(String responseBody) + throws ParseException { + JSONParser parser = new JSONParser(); + JSONObject jsonObj = (JSONObject) parser.parse(responseBody); + JSONArray itemsArray = (JSONArray) jsonObj.get("items"); + Iterator it = itemsArray.iterator(); + List<DcaeInventoryResponse> inventoryResponseList = new LinkedList<>(); + while (it.hasNext()) { + JSONObject item = (JSONObject) it.next(); + DcaeInventoryResponse response = JsonUtils.GSON.fromJson(item.toString(), DcaeInventoryResponse.class); + inventoryResponseList.add(response); + } + return inventoryResponseList; + } +} diff --git a/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java new file mode 100644 index 000000000..2be707fe4 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponent.java @@ -0,0 +1,59 @@ +/*- + * ============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.loop.components.external; + +import com.google.gson.annotations.Expose; + +import org.apache.camel.Exchange; + +/** + * Should be abstract but Gson can't instantiate it if it's an abstract. + */ +public class ExternalComponent { + @Expose + private ExternalComponentState componentState; + + public void setState(ExternalComponentState newState) { + this.componentState = newState; + } + + public ExternalComponentState getState() { + return this.componentState; + } + + public String getComponentName() { + return null; + } + + public ExternalComponentState computeState(Exchange camelExchange) { + return new ExternalComponentState("INIT", "no desc", 0); + } + + public ExternalComponent(ExternalComponentState initialState) { + setState(initialState); + } + + public ExternalComponent() { + } +} diff --git a/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java new file mode 100644 index 000000000..a57234af0 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/components/external/ExternalComponentState.java @@ -0,0 +1,128 @@ +/*- + * ============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.loop.components.external; + +import com.google.gson.annotations.Expose; + +/** + * This is a transient state reflecting the deployment status of a component. It + * can be Policy, DCAE, or whatever... This is object is generic. Clamp is now + * stateless, so it triggers the different components at runtime, the status per + * component is stored here. The state level is used to re-compute the global + * state when multiple sub states are required for that computation (generally + * provided sequentially to the method computeState from the camel routes. + * + */ +public class ExternalComponentState implements Comparable<ExternalComponentState> { + @Expose + private String stateName; + @Expose + private String description; + private int stateLevel; + + /** + * Constructor taking stateName, description and its level. + * + * @param stateName The stateName in string + * @param description The description in string + * @param level The level, higher value has higher priority and can't be + * down-graded + */ + public ExternalComponentState(String stateName, String description, int level) { + this.stateName = stateName; + this.description = description; + this.stateLevel = level; + } + + public ExternalComponentState(String stateName, String description) { + this(stateName, description, 0); + } + + public ExternalComponentState() { + } + + public String getStateName() { + return stateName; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + return stateName; + } + + public int getLevel() { + return stateLevel; + } + + public void setLevel(int priority) { + this.stateLevel = priority; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((stateName == null) ? 0 : stateName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ExternalComponentState other = (ExternalComponentState) obj; + if (stateName == null) { + if (other.stateName != null) { + return false; + } + } else if (!stateName.equals(other.stateName)) { + return false; + } + return true; + } + + /** + * This method compares this object by using the level of them. + * + * @param stateToCompare The state to compare to the current object + * @return If the one given in input has a higher level than the current object + * it returns -1, 1 otherwise and 0 if equals. + */ + @Override + public int compareTo(ExternalComponentState stateToCompare) { + return Integer.compare(this.getLevel(), stateToCompare.getLevel()); + } + +} diff --git a/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java b/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java new file mode 100644 index 000000000..4ea5b7118 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/components/external/PolicyComponent.java @@ -0,0 +1,195 @@ +/*- + * ============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.loop.components.external; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.persistence.Transient; +import org.apache.camel.Exchange; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; + +public class PolicyComponent extends ExternalComponent { + + @Transient + private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyComponent.class); + + public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR", + "There was an error during the sending to policy, the policy engine may be corrupted or inconsistent", 100); + public static final ExternalComponentState NOT_SENT = new ExternalComponentState("NOT_SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + public static final ExternalComponentState SENT = new ExternalComponentState("SENT", + "The policies defined have been created but NOT deployed on the policy engine", 50); + public static final ExternalComponentState SENT_AND_DEPLOYED = new ExternalComponentState("SENT_AND_DEPLOYED", + "The policies defined have been created and deployed on the policy engine", 10); + public static final ExternalComponentState UNKNOWN = new ExternalComponentState("UNKNOWN", + "The current status is not clear. Need to refresh the status to get the current status.", 0); + + /** + * Default constructor. + */ + public PolicyComponent() { + /* + * We assume it's good by default as we will receive the state for each policy + * on by one, each time we increase the level we can't decrease it anymore. + * That's why it starts with the lowest one SENT_AND_DEPLOYED. + */ + super(UNKNOWN); + } + + @Override + public String getComponentName() { + return "POLICY"; + } + + /** + * Generates the Json that must be sent to policy to add all policies to Active + * PDP group. + * @param loop the loop object + * @param action POST (to add policy to group) or DELETE (to delete policy from group) + * @return The json, payload to send + */ + public static String createPoliciesPayloadPdpGroup(Loop loop, String action) { + Map<String, Map<String, List<JsonObject>>> pdpGroupMap = new HashMap<>(); + for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) { + updatePdpGroupMap(opPolicy.getPdpGroup(), opPolicy.getPdpSubgroup(), + opPolicy.getName(), + "1.0.0", pdpGroupMap); + } + + for (MicroServicePolicy msPolicy : loop.getMicroServicePolicies()) { + updatePdpGroupMap(msPolicy.getPdpGroup(), msPolicy.getPdpSubgroup(), + msPolicy.getName(), + "1.0.0", pdpGroupMap); + } + + String payload = new GsonBuilder().setPrettyPrinting().create() + .toJson(generateActivatePdpGroupPayload(pdpGroupMap, action)); + logger.info("PdpGroup policy payload: " + payload); + return payload; + } + + private static void updatePdpGroupMap(String pdpGroup, + String pdpSubGroup, + String policyName, + String policyVersion, + Map<String, Map<String, + List<JsonObject>>> pdpGroupMap) { + JsonObject policyJson = new JsonObject(); + policyJson.addProperty("name", policyName); + policyJson.addProperty("version", policyVersion); + Map<String, List<JsonObject>> pdpSubGroupMap; + List<JsonObject> policyList; + if (pdpGroupMap.get(pdpGroup) == null) { + pdpSubGroupMap = new HashMap<>(); + policyList = new LinkedList<>(); + } + else { + pdpSubGroupMap = pdpGroupMap.get(pdpGroup); + if (pdpSubGroupMap.get(pdpSubGroup) == null) { + policyList = new LinkedList<>(); + } + else { + policyList = (List<JsonObject>) pdpSubGroupMap.get(pdpSubGroup); + } + } + policyList.add(policyJson); + pdpSubGroupMap.put(pdpSubGroup, policyList); + pdpGroupMap.put(pdpGroup, pdpSubGroupMap); + } + + private static JsonObject generateActivatePdpGroupPayload( + Map<String, Map<String, List<JsonObject>>> pdpGroupMap, String action) { + JsonArray payloadArray = new JsonArray(); + for (Entry<String, Map<String, List<JsonObject>>> pdpGroupInfo : pdpGroupMap.entrySet()) { + JsonObject pdpGroupNode = new JsonObject(); + JsonArray subPdpArray = new JsonArray(); + pdpGroupNode.addProperty("name", pdpGroupInfo.getKey()); + pdpGroupNode.add("deploymentSubgroups", subPdpArray); + + for (Entry<String, List<JsonObject>> pdpSubGroupInfo : pdpGroupInfo.getValue().entrySet()) { + JsonObject pdpSubGroupNode = new JsonObject(); + subPdpArray.add(pdpSubGroupNode); + pdpSubGroupNode.addProperty("pdpType", pdpSubGroupInfo.getKey()); + pdpSubGroupNode.addProperty("action", action); + + JsonArray policyArray = new JsonArray(); + pdpSubGroupNode.add("policies", policyArray); + + for (JsonObject policy : pdpSubGroupInfo.getValue()) { + policyArray.add(policy); + } + } + payloadArray.add(pdpGroupNode); + } + JsonObject jsonObject = new JsonObject(); + jsonObject.add("groups", payloadArray); + return jsonObject; + } + + private static ExternalComponentState findNewState(boolean found, boolean deployed) { + + ExternalComponentState newState = NOT_SENT; + if (found && deployed) { + newState = SENT_AND_DEPLOYED; + } + else if (found) { + newState = SENT; + } + else if (deployed) { + newState = IN_ERROR; + } + return newState; + } + + private static ExternalComponentState mergeStates(ExternalComponentState oldState, + ExternalComponentState newState) { + return (oldState.compareTo(newState) < 0) ? newState : oldState; + } + + /** + * This is a method that expect the results of the queries getPolicy and + * getPolicyDeployed for a unique policy (op, config, etc ...). It + * re-computes the global policy state for each policy results given. Therefore + * this method is called multiple times from the camel route and must be reset + * for a new global policy state retrieval. The state to compute the global + * policy state is stored in this class. + */ + @Override + public ExternalComponentState computeState(Exchange camelExchange) { + this.setState(mergeStates(this.getState(), + findNewState((boolean) camelExchange.getIn().getExchange().getProperty("policyFound"), + (boolean) camelExchange.getIn().getExchange().getProperty("policyDeployed")))); + return this.getState(); + } +} diff --git a/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java b/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java new file mode 100644 index 000000000..65506a479 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/deploy/DcaeDeployParameters.java @@ -0,0 +1,119 @@ +/*- + * ============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.loop.deploy; + +import com.google.gson.JsonObject; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.components.external.DcaeComponent; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.yaml.snakeyaml.Yaml; + +/** + * To decode the bluprint input parameters. + */ +public class DcaeDeployParameters { + + private static LinkedHashMap<String, JsonObject> init(Loop loop) { + LinkedHashMap<String, JsonObject> deploymentParamMap = new LinkedHashMap<>(); + Set<MicroServicePolicy> microServiceList = loop.getMicroServicePolicies(); + + for (MicroServicePolicy microService : microServiceList) { + deploymentParamMap.put(microService.getName(), + generateDcaeDeployParameter(microService)); + } + return deploymentParamMap; + } + + private static JsonObject generateDcaeDeployParameter(MicroServicePolicy microService) { + return generateDcaeDeployParameter(microService.getLoopElementModel().getBlueprint(), + microService.getName()); + } + + private static JsonObject generateDcaeDeployParameter(String blueprint, String policyId) { + JsonObject deployJsonBody = new JsonObject(); + Yaml yaml = new Yaml(); + Map<String, Object> inputsNodes = ((Map<String, Object>) ((Map<String, Object>) yaml + .load(blueprint)).get("inputs")); + inputsNodes.entrySet().stream().filter(e -> !e.getKey().contains("policy_id")).forEach(elem -> { + Object defaultValue = ((Map<String, Object>) elem.getValue()).get("default"); + if (defaultValue != null) { + addPropertyToNode(deployJsonBody, elem.getKey(), defaultValue); + } + else { + deployJsonBody.addProperty(elem.getKey(), ""); + } + }); + deployJsonBody.addProperty("policy_id", policyId); + return deployJsonBody; + } + + private static void addPropertyToNode(JsonObject node, String key, Object value) { + if (value instanceof String) { + node.addProperty(key, (String) value); + } + else if (value instanceof Number) { + node.addProperty(key, (Number) value); + } + else if (value instanceof Boolean) { + node.addProperty(key, (Boolean) value); + } + else if (value instanceof Character) { + node.addProperty(key, (Character) value); + } + else { + node.addProperty(key, JsonUtils.GSON.toJson(value)); + } + } + + /** + * Convert the object in Json. + * + * @return The deploymentParameters in Json + */ + public static JsonObject getDcaeDeploymentParametersInJson(Loop loop) { + JsonObject globalProperties = new JsonObject(); + JsonObject deployParamJson = new JsonObject(); + if (loop.getLoopTemplate().getUniqueBlueprint()) { + // Normally the unique blueprint could contain multiple microservices but then we can't guess + // the policy id params that will be used, so here we expect only one by default. + deployParamJson.add(DcaeComponent.UNIQUE_BLUEPRINT_PARAMETERS, + generateDcaeDeployParameter(loop.getLoopTemplate().getBlueprint(), + ((MicroServicePolicy) loop.getMicroServicePolicies().toArray()[0]).getName())); + + } + else { + LinkedHashMap<String, JsonObject> deploymentParamMap = init(loop); + for (Map.Entry<String, JsonObject> mapElement : deploymentParamMap.entrySet()) { + deployParamJson.add(mapElement.getKey(), mapElement.getValue()); + } + } + globalProperties.add("dcaeDeployParameters", deployParamJson); + return globalProperties; + } + +} diff --git a/src/main/java/org/onap/clamp/loop/log/LogType.java b/src/main/java/org/onap/clamp/loop/log/LogType.java new file mode 100644 index 000000000..13d9dccf8 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/log/LogType.java @@ -0,0 +1,28 @@ +/*- + * ============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.loop.log; + +public enum LogType { + INFO, WARNING, ERROR; +} diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLog.java b/src/main/java/org/onap/clamp/loop/log/LoopLog.java new file mode 100644 index 000000000..e49598879 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/log/LoopLog.java @@ -0,0 +1,196 @@ +/*- + * ============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.loop.log; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.onap.clamp.loop.Loop; + +/** + * This class holds the logs created by the Clamp Backend. The Instant is always + * rounded to the nearest second as the nano seconds can't be stored in the + * database. The logs can be therefore exposed to the UI or the client doing + * some GET Loop on the backend. + * + */ +@Entity +@Table(name = "loop_logs") +public class LoopLog implements Serializable, Comparable<LoopLog> { + /** + * The serial version ID. + */ + private static final long serialVersionUID = 1988276670074437631L; + + @Expose + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Expose + @Column(name = "log_type", nullable = false) + @Enumerated(EnumType.STRING) + private LogType logType; + + @Expose + @Column(name = "log_component", nullable = false) + private String logComponent; + + @Expose + @Column(name = "message", columnDefinition = "MEDIUMTEXT", nullable = false) + private String message; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "loop_id", nullable = false) + private Loop loop; + + @Expose + @Column(name = "log_instant", nullable = false) + private Instant logInstant = Instant.now().truncatedTo(ChronoUnit.SECONDS); + + public LoopLog() { + } + + /** + * Constructor For LoopLog taking message and logtype, logComponent and loop + * reference. + * + * @param message The message as string + * @param logType Type like INFO, WARN, DEBUG + * @param logComponent A String with DCAE, POLICY, CLAMP ,etc... + * @param loop The loop object that this log is about + */ + public LoopLog(String message, LogType logType, String logComponent, Loop loop) { + this.message = message; + this.logType = logType; + this.loop = loop; + this.logComponent = logComponent; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LogType getLogType() { + return logType; + } + + public void setLogType(LogType logType) { + this.logType = logType; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Loop getLoop() { + return loop; + } + + public void setLoop(Loop loop) { + this.loop = loop; + } + + public Instant getLogInstant() { + return logInstant; + } + + public void setLogInstant(Instant logInstant) { + this.logInstant = logInstant.truncatedTo(ChronoUnit.SECONDS); + } + + public String getLogComponent() { + return logComponent; + } + + public void setLogComponent(String logComponent) { + this.logComponent = logComponent; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LoopLog other = (LoopLog) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + return true; + } + + @Override + public int compareTo(LoopLog arg0) { + // Reverse it, so that by default we have the latest + if (getId() == null) { + return 1; + } + if (arg0.getId() == null) { + return -1; + } + return arg0.getId().compareTo(this.getId()); + } + +} diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java b/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java new file mode 100644 index 000000000..0b3c34ec0 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/log/LoopLogRepository.java @@ -0,0 +1,32 @@ +/*- + * ============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.loop.log; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface LoopLogRepository extends JpaRepository<LoopLog, Long> { + +} diff --git a/src/main/java/org/onap/clamp/loop/log/LoopLogService.java b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java new file mode 100644 index 000000000..d02d0b278 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/log/LoopLogService.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.loop.log; + +import org.onap.clamp.loop.Loop; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class LoopLogService { + + private final LoopLogRepository repository; + + @Autowired + public LoopLogService(LoopLogRepository repository) { + this.repository = repository; + } + + public void addLog(String message, String logType, Loop loop) { + this.addLogForComponent(message, logType, "CLAMP", loop); + } + + public void addLogForComponent(String message, String logType, String component, Loop loop) { + loop.addLog(repository.save(new LoopLog(message, LogType.valueOf(logType), component, loop))); + } + + public boolean isExisting(Long logId) { + return repository.existsById(logId); + } +} diff --git a/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java new file mode 100644 index 000000000..c43f2cb6d --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * 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. + * 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.loop.service; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import java.util.Map.Entry; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.sdc.tosca.parser.api.IEntityDetails; +import org.onap.sdc.tosca.parser.elements.queries.EntityQuery; +import org.onap.sdc.tosca.parser.elements.queries.TopologyTemplateQuery; +import org.onap.sdc.tosca.parser.enums.EntityTemplateType; +import org.onap.sdc.tosca.parser.enums.SdcTypes; +import org.onap.sdc.toscaparser.api.NodeTemplate; +import org.onap.sdc.toscaparser.api.Property; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Qualifier("csarInstaller") +public class CsarServiceInstaller { + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarServiceInstaller.class); + + @Autowired + ServicesRepository serviceRepository; + + /** + * Install the Service from the csar. + * + * @param csar The Csar Handler + * @return The service object + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public Service installTheService(CsarHandler csar) { + logger.info("Start to install the Service from csar"); + JsonObject serviceDetails = JsonUtils.GSON.fromJson( + JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class); + + // Add properties details for each type, VfModule, VF, VFC, .... + JsonObject resourcesProp = createServicePropertiesByType(csar); + resourcesProp.add("VFModule", createVfModuleProperties(csar)); + + Service modelService = new Service(serviceDetails, resourcesProp, + csar.getSdcNotification().getServiceVersion()); + + serviceRepository.save(modelService); + logger.info("Successfully installed the Service"); + return modelService; + } + + private JsonObject createServicePropertiesByType(CsarHandler csar) { + JsonObject resourcesProp = new JsonObject(); + // Iterate on all types defined in the tosca lib + for (SdcTypes type : SdcTypes.values()) { + JsonObject resourcesPropByType = new JsonObject(); + // For each type, get the metadata of each nodetemplate + for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) { + resourcesPropByType.add(nodeTemplate.getName(), + JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties())); + } + resourcesProp.add(type.getValue(), resourcesPropByType); + } + return resourcesProp; + } + + private static JsonObject createVfModuleProperties(CsarHandler csar) { + JsonObject vfModuleProps = new JsonObject(); + // Loop on all Groups defined in the service (VFModule entries type: + // org.openecomp.groups.VfModule) + for (IEntityDetails entity : csar.getSdcCsarHelper().getEntity( + EntityQuery.newBuilder(EntityTemplateType.GROUP).build(), + TopologyTemplateQuery.newBuilder(SdcTypes.SERVICE).build(), false)) { + // Get all metadata info + JsonObject allVfProps = (JsonObject) JsonUtils.GSON.toJsonTree(entity.getMetadata().getAllProperties()); + vfModuleProps.add(entity.getMetadata().getAllProperties().get("vfModuleModelName"), allVfProps); + // now append the properties section so that we can also have isBase, + // volume_group, etc ... fields under the VFmodule name + for (Entry<String, Property> additionalProp : entity.getProperties().entrySet()) { + allVfProps.add(additionalProp.getValue().getName(), + JsonUtils.GSON.toJsonTree(additionalProp.getValue().getValue())); + } + } + return vfModuleProps; + } + + /** + * Verify whether Service in Csar is deployed. + * + * @param csar The Csar Handler + * @return The flag indicating whether Service is deployed + * @throws SdcArtifactInstallerException The SdcArtifactInstallerException + */ + public boolean isServiceAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException { + boolean alreadyInstalled = true; + JsonObject serviceDetails = JsonUtils.GSON.fromJson( + JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class); + alreadyInstalled = serviceRepository.existsById(serviceDetails.get("UUID").getAsString()); + + return alreadyInstalled; + } +} diff --git a/src/main/java/org/onap/clamp/loop/service/Service.java b/src/main/java/org/onap/clamp/loop/service/Service.java new file mode 100644 index 000000000..338032a16 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/service/Service.java @@ -0,0 +1,168 @@ +/*- + * ============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.loop.service; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; + +@Entity +@Table(name = "services") +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public class Service implements Serializable { + + /** + * The serial version id. + */ + private static final long serialVersionUID = 1331119060272760758L; + + @Transient + private static final EELFLogger logger = EELFManager.getInstance().getLogger(Service.class); + + @Id + @Column(name = "service_uuid", unique = true) + private String serviceUuid; + + @Column(nullable = false, name = "name") + private String name; + + @Column(name = "version") + private String version; + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "service_details") + private JsonObject serviceDetails; + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "resource_details") + private JsonObject resourceDetails; + + /** + * Default constructor for serialization. + */ + public Service() { + } + + /** + * Constructor with string. + */ + public Service(String serviceDetails, String resourceDetails) { + JsonObject serviceDetailsJson = JsonUtils.GSON.fromJson(serviceDetails, JsonObject.class); + this.name = serviceDetailsJson.get("name").getAsString(); + this.serviceUuid = serviceDetailsJson.get("UUID").getAsString(); + this.serviceDetails = serviceDetailsJson; + this.resourceDetails = JsonUtils.GSON.fromJson(resourceDetails, JsonObject.class); + } + + /** + * Constructor with Json Object. + */ + public Service(JsonObject serviceDetails, JsonObject resourceDetails, String version) { + this.name = serviceDetails.get("name").getAsString(); + this.serviceUuid = serviceDetails.get("UUID").getAsString(); + this.serviceDetails = serviceDetails; + this.resourceDetails = resourceDetails; + this.version = version; + } + + public String getServiceUuid() { + return serviceUuid; + } + + public JsonObject getServiceDetails() { + return serviceDetails; + } + + public JsonObject getResourceDetails() { + return resourceDetails; + } + + public JsonObject getResourceByType(String type) { + return (JsonObject) resourceDetails.get(type); + } + + /** + * Name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Version getter. + * + * @return the version + */ + public String getVersion() { + return version; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((serviceUuid == null) ? 0 : serviceUuid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Service other = (Service) obj; + if (serviceUuid == null) { + if (other.serviceUuid != null) { + return false; + } + } + else if (!serviceUuid.equals(other.serviceUuid)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java b/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java new file mode 100644 index 000000000..fe5ba8ed0 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/service/ServicesRepository.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.service; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ServicesRepository extends JpaRepository<Service, String> { +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java b/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java new file mode 100644 index 000000000..70cdbe233 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopElementModel.java @@ -0,0 +1,298 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.loop.template; + +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import org.hibernate.annotations.SortNatural; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.common.AuditEntity; +import org.onap.clamp.policy.Policy; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; + +/** + * This class represents a micro service/operational/... model for a loop template. + * So it's an element in the flow (a box shown in the loop). + */ + +@Entity +@Table(name = "loop_element_models") +public class LoopElementModel extends AuditEntity implements Serializable { + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522707701376645L; + + @Id + @Expose + @Column(nullable = false, name = "name", unique = true) + private String name; + + @Expose + @Column(name = "dcae_blueprint_id") + private String dcaeBlueprintId; + + /** + * Here we store the blueprint coming from DCAE, it can be null if this is not a micro service model. + */ + @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml") + private String blueprint; + + public static final String MICRO_SERVICE_TYPE = "MICRO_SERVICE_TYPE"; + public static final String OPERATIONAL_POLICY_TYPE = "OPERATIONAL_POLICY_TYPE"; + /** + * The type of element. + */ + @Expose + @Column(nullable = false, name = "loop_element_type") + private String loopElementType; + + /** + * This variable is used to display the micro-service name in the SVG. + */ + @Expose + @Column(name = "short_name") + private String shortName; + + /** + * This variable is used to store the type mentioned in the micro-service + * blueprint. + */ + @Expose + @ManyToMany( + fetch = FetchType.EAGER, + cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) + @JoinTable( + name = "loopelementmodels_to_policymodels", + joinColumns = @JoinColumn(name = "loop_element_name", referencedColumnName = "name"), + inverseJoinColumns = { + @JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"), + @JoinColumn(name = "policy_model_version", referencedColumnName = "version")}) + @SortNatural + private SortedSet<PolicyModel> policyModels = new TreeSet<>(); + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "loopElementModel", orphanRemoval = true) + private Set<LoopTemplateLoopElementModel> usedByLoopTemplates = new HashSet<>(); + + /** + * policyModels getter. + * + * @return the policyModel + */ + public SortedSet<PolicyModel> getPolicyModels() { + return policyModels; + } + + /** + * Method to add a new policyModel to the list. + * + * @param policyModel The policy model + */ + public void addPolicyModel(PolicyModel policyModel) { + policyModels.add(policyModel); + policyModel.getUsedByElementModels().add(this); + } + + /** + * name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * blueprint getter. + * + * @return the blueprint + */ + public String getBlueprint() { + return blueprint; + } + + /** + * blueprint setter. + * + * @param blueprint the blueprint to set + */ + public void setBlueprint(String blueprint) { + this.blueprint = blueprint; + } + + /** + * dcaeBlueprintId getter. + * + * @return the dcaeBlueprintId + */ + public String getDcaeBlueprintId() { + return dcaeBlueprintId; + } + + /** + * dcaeBlueprintId setter. + * + * @param dcaeBlueprintId the dcaeBlueprintId to set + */ + public void setDcaeBlueprintId(String dcaeBlueprintId) { + this.dcaeBlueprintId = dcaeBlueprintId; + } + + /** + * loopElementType getter. + * + * @return the loopElementType + */ + public String getLoopElementType() { + return loopElementType; + } + + /** + * loopElementType setter. + * + * @param loopElementType the loopElementType to set + */ + public void setLoopElementType(String loopElementType) { + this.loopElementType = loopElementType; + } + + /** + * shortName getter. + * + * @return the shortName + */ + public String getShortName() { + return shortName; + } + + /** + * @param shortName the shortName to set. + */ + public void setShortName(String shortName) { + this.shortName = shortName; + } + + /** + * usedByLoopTemplates getter. + * + * @return the usedByLoopTemplates + */ + public Set<LoopTemplateLoopElementModel> getUsedByLoopTemplates() { + return usedByLoopTemplates; + } + + /** + * Default constructor for serialization. + */ + public LoopElementModel() { + } + + /** + * Constructor. + * + * @param name The name id + * @param loopElementType The type of loop element + * @param blueprint The blueprint defined for dcae that contains the + * policy type to use + */ + public LoopElementModel(String name, String loopElementType, String blueprint) { + this.name = name; + this.loopElementType = loopElementType; + this.blueprint = blueprint; + } + + /** + * Create a policy instance from the current loop element model. + * + * @return A Policy object. + */ + public Policy createPolicyInstance(Loop loop, ToscaConverterWithDictionarySupport toscaConverter) { + if (LoopElementModel.MICRO_SERVICE_TYPE.equals(this.getLoopElementType())) { + return new MicroServicePolicy(loop, loop.getModelService(), this, toscaConverter); + } + else if (LoopElementModel.OPERATIONAL_POLICY_TYPE.equals(this.getLoopElementType())) { + return new OperationalPolicy(loop, loop.getModelService(), this, toscaConverter); + } + else { + return null; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LoopElementModel other = (LoopElementModel) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } + else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java b/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java new file mode 100644 index 000000000..27b82189c --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopElementModelsRepository.java @@ -0,0 +1,31 @@ +/*- + * ============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.loop.template; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface LoopElementModelsRepository extends JpaRepository<LoopElementModel, String> { +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java new file mode 100644 index 000000000..6f896f3d4 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplate.java @@ -0,0 +1,341 @@ +/*- + * ============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.loop.template; + +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import org.hibernate.annotations.SortNatural; +import org.onap.clamp.loop.common.AuditEntity; +import org.onap.clamp.loop.service.Service; + +@Entity +@Table(name = "loop_templates") +public class LoopTemplate extends AuditEntity implements Serializable { + + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522707701388642L; + + @Id + @Expose + @Column(nullable = false, name = "name", unique = true) + private String name; + + @Expose + @Column(name = "dcae_blueprint_id") + private String dcaeBlueprintId; + + /** + * This field is used when we have a blueprint defining all microservices. The + * other option would be to have independent blueprint for each microservices. + * In that case they are stored in each MicroServiceModel + */ + @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml") + private String blueprint; + + @Expose + @OneToMany( + cascade = CascadeType.ALL, + fetch = FetchType.EAGER, + mappedBy = "loopTemplate", + orphanRemoval = true) + @SortNatural + private SortedSet<LoopTemplateLoopElementModel> loopElementModelsUsed = new TreeSet<>(); + + @Expose + @ManyToOne( + fetch = FetchType.EAGER, + cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) + @JoinColumn(name = "service_uuid") + private Service modelService; + + @Expose + @Column(name = "maximum_instances_allowed") + private Integer maximumInstancesAllowed; + + @Expose + @Column(name = "unique_blueprint", columnDefinition = "boolean default false") + private boolean uniqueBlueprint; + + /** + * Type of Loop allowed to be created. + */ + @Expose + @Column(name = "allowed_loop_type") + @Convert(converter = LoopTypeConvertor.class) + private LoopType allowedLoopType = LoopType.CLOSED; + + /** + * name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * blueprint getter. + * + * @return the blueprint + */ + public String getBlueprint() { + return blueprint; + } + + /** + * dcaeBlueprintId getter. + * + * @return the dcaeBlueprintId + */ + public String getDcaeBlueprintId() { + return dcaeBlueprintId; + } + + /** + * dcaeBlueprintId setter. + * + * @param dcaeBlueprintId the dcaeBlueprintId to set + */ + public void setDcaeBlueprintId(String dcaeBlueprintId) { + this.dcaeBlueprintId = dcaeBlueprintId; + } + + /** + * blueprint setter. + * + * @param blueprint the blueprint to set + */ + public void setBlueprint(String blueprint) { + this.blueprint = blueprint; + if (blueprint == null) { + this.uniqueBlueprint = false; + } else { + this.uniqueBlueprint = true; + } + } + + /** + * loopElementModelsUsed getter. + * + * @return the loopElementModelsUsed + */ + public SortedSet<LoopTemplateLoopElementModel> getLoopElementModelsUsed() { + return loopElementModelsUsed; + } + + /** + * maximumInstancesAllowed getter. + * + * @return the maximumInstancesAllowed + */ + public Integer getMaximumInstancesAllowed() { + return maximumInstancesAllowed; + } + + /** + * maximumInstancesAllowed setter. + * + * @param maximumInstancesAllowed the maximumInstancesAllowed to set + */ + public void setMaximumInstancesAllowed(Integer maximumInstancesAllowed) { + this.maximumInstancesAllowed = maximumInstancesAllowed; + } + + /** + * allowedLoopType getter. + * + * @return the allowedLoopType Type of Loop allowed to be created + */ + public LoopType getAllowedLoopType() { + return allowedLoopType; + } + + /** + * allowedLoopType setter. + * + * @param allowedLoopType the allowedLoopType to set + */ + public void setAllowedLoopType(LoopType allowedLoopType) { + this.allowedLoopType = allowedLoopType; + } + + /** + * Add list of loopElements to the current template, each loopElementModel is + * added at the end of the list so the flowOrder is computed automatically. + * + * @param loopElementModels The loopElementModel set to add + */ + public void addLoopElementModels(Set<LoopElementModel> loopElementModels) { + for (LoopElementModel loopElementModel : loopElementModels) { + addLoopElementModel(loopElementModel); + } + } + + /** + * Add a loopElement to the current template, the loopElementModel is added at + * the end of the list so the flowOrder is computed automatically. + * + * @param loopElementModel The loopElementModel to add + */ + public void addLoopElementModel(LoopElementModel loopElementModel) { + this.addLoopElementModel(loopElementModel,this.loopElementModelsUsed.size()); + } + + /** + * Add a loopElement model to the current template, the flow order must be + * specified manually. + * + * @param loopElementModel The loopElementModel to add + * @param listPosition The position in the flow + */ + public void addLoopElementModel(LoopElementModel loopElementModel, Integer listPosition) { + LoopTemplateLoopElementModel jointEntry = + new LoopTemplateLoopElementModel(this, loopElementModel, listPosition); + this.loopElementModelsUsed.add(jointEntry); + loopElementModel.getUsedByLoopTemplates().add(jointEntry); + } + + /** + * modelService getter. + * + * @return the modelService + */ + public Service getModelService() { + return modelService; + } + + /** + * modelService setter. + * + * @param modelService the modelService to set + */ + public void setModelService(Service modelService) { + this.modelService = modelService; + } + + /** + * uniqueBlueprint getter. + * + * @return the uniqueBlueprint + */ + public boolean getUniqueBlueprint() { + return uniqueBlueprint; + } + + /** + * Default constructor for serialization. + */ + public LoopTemplate() { + + } + + /** + * Constructor. + * + * @param name The loop template name id + * @param blueprint The blueprint containing all microservices (legacy + * case) + * @param maxInstancesAllowed The maximum number of instances that can be + * created from that template + * @param service The service associated to that loop template + */ + public LoopTemplate(String name, String blueprint, Integer maxInstancesAllowed, Service service) { + this.name = name; + this.setBlueprint(blueprint); + + this.maximumInstancesAllowed = maxInstancesAllowed; + this.modelService = service; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LoopTemplate other = (LoopTemplate) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + /** + * Generate the loop template name. + * + * @param serviceName The service name + * @param serviceVersion The service version + * @param resourceName The resource name + * @param blueprintFileName The blueprint file name + * @return The generated loop template name + */ + public static String generateLoopTemplateName(String serviceName, String serviceVersion, + String resourceName, String blueprintFileName) { + StringBuilder buffer = new StringBuilder("LOOP_TEMPLATE_").append(serviceName).append("_v") + .append(serviceVersion).append("_").append(resourceName).append("_") + .append(blueprintFileName.replaceAll(".yaml", "")); + return buffer.toString().replace('.', '_').replaceAll(" ", ""); + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java new file mode 100644 index 000000000..aca16bc04 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModel.java @@ -0,0 +1,194 @@ +/*- + * ============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.loop.template; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; +import javax.persistence.Table; + +@Entity +@Table(name = "looptemplates_to_loopelementmodels") +public class LoopTemplateLoopElementModel implements Serializable, Comparable<LoopTemplateLoopElementModel> { + + /** + * Serial ID. + */ + private static final long serialVersionUID = 5924989899078094245L; + + @EmbeddedId + private LoopTemplateLoopElementModelId loopTemplateLoopElementModelId; + + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("loopTemplateName") + @JoinColumn(name = "loop_template_name") + private LoopTemplate loopTemplate; + + @Expose + @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }) + @MapsId("loopElementModelName") + @JoinColumn(name = "loop_element_model_name") + private LoopElementModel loopElementModel; + + @Expose + @Column(nullable = false, name = "flow_order") + private Integer flowOrder; + + /** + * Default constructor for serialization. + */ + public LoopTemplateLoopElementModel() { + + } + + /** + * Constructor. + * + * @param loopTemplate The loop template object + * @param loopElementModel The loopElementModel object + * @param flowOrder The position of the micro service in the flow + */ + public LoopTemplateLoopElementModel(LoopTemplate loopTemplate, LoopElementModel loopElementModel, + Integer flowOrder) { + this.loopTemplate = loopTemplate; + this.loopElementModel = loopElementModel; + this.flowOrder = flowOrder; + this.loopTemplateLoopElementModelId = new LoopTemplateLoopElementModelId(loopTemplate.getName(), + loopElementModel.getName()); + } + + /** + * loopTemplate getter. + * + * @return the loopTemplate + */ + public LoopTemplate getLoopTemplate() { + return loopTemplate; + } + + /** + * loopTemplate setter. + * + * @param loopTemplate the loopTemplate to set + */ + public void setLoopTemplate(LoopTemplate loopTemplate) { + this.loopTemplate = loopTemplate; + } + + /** + * loopElementModel getter. + * + * @return the loopElementModel + */ + public LoopElementModel getLoopElementModel() { + return loopElementModel; + } + + /** + * loopElementModel setter. + * + * @param loopElementModel the loopElementModel to set + */ + public void setLoopElementModel(LoopElementModel loopElementModel) { + this.loopElementModel = loopElementModel; + } + + /** + * flowOrder getter. + * + * @return the flowOrder + */ + public Integer getFlowOrder() { + return flowOrder; + } + + /** + * flowOrder setter. + * + * @param flowOrder the flowOrder to set + */ + public void setFlowOrder(Integer flowOrder) { + this.flowOrder = flowOrder; + } + + @Override + public int compareTo(LoopTemplateLoopElementModel arg0) { + // Reverse it, so that by default we have the latest + if (getFlowOrder() == null) { + return 1; + } + if (arg0.getFlowOrder() == null) { + return -1; + } + return arg0.getFlowOrder().compareTo(this.getFlowOrder()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((loopTemplate == null) ? 0 : loopTemplate.hashCode()); + result = prime * result + ((loopElementModel == null) ? 0 : loopElementModel.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LoopTemplateLoopElementModel other = (LoopTemplateLoopElementModel) obj; + if (loopTemplate == null) { + if (other.loopTemplate != null) { + return false; + } + } else if (!loopTemplate.equals(other.loopTemplate)) { + return false; + } + if (loopElementModel == null) { + if (other.loopElementModel != null) { + return false; + } + } else if (!loopElementModel.equals(other.loopElementModel)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java new file mode 100644 index 000000000..cac5f088a --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplateLoopElementModelId.java @@ -0,0 +1,100 @@ +/*- + * ============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.loop.template; + +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Embeddable; + +@Embeddable +public class LoopTemplateLoopElementModelId implements Serializable { + + /** + * Serial ID. + */ + private static final long serialVersionUID = 4089888115504914773L; + + @Expose + @Column(name = "loop_template_name") + private String loopTemplateName; + + @Expose + @Column(name = "loop_element_model_name") + private String loopElementModelName; + + /** + * Default constructor for serialization. + */ + public LoopTemplateLoopElementModelId() { + + } + + /** + * Constructor. + * + * @param loopTemplateName The loop template name id + * @param microServiceModelName THe micro Service name id + */ + public LoopTemplateLoopElementModelId(String loopTemplateName, String microServiceModelName) { + this.loopTemplateName = loopTemplateName; + this.loopElementModelName = microServiceModelName; + } + + /** + * loopTemplateName getter. + * + * @return the loopTemplateName + */ + public String getLoopTemplateName() { + return loopTemplateName; + } + + /** + * loopTemplateName setter. + * + * @param loopTemplateName the loopTemplateName to set + */ + public void setLoopTemplateName(String loopTemplateName) { + this.loopTemplateName = loopTemplateName; + } + + /** + * microServiceModelName getter. + * + * @return the microServiceModelName + */ + public String getLoopElementModelName() { + return loopElementModelName; + } + + /** + * loopElementModelName setter. + * + * @param loopElementModelName the loopElementModelName to set + */ + public void setLoopElementModelName(String loopElementModelName) { + this.loopElementModelName = loopElementModelName; + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java new file mode 100644 index 000000000..07f304de7 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesRepository.java @@ -0,0 +1,37 @@ +/*- + * ============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.loop.template; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface LoopTemplatesRepository extends JpaRepository<LoopTemplate, String> { + + @Query("SELECT looptemplate.name FROM LoopTemplate as looptemplate") + List<String> getAllLoopTemplateNames(); +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java new file mode 100644 index 000000000..29382137e --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTemplatesService.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.template; + +import java.util.List; +import org.onap.clamp.clds.sdc.controller.installer.ChainGenerator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class LoopTemplatesService { + + private final LoopTemplatesRepository loopTemplatesRepository; + + @Autowired + ChainGenerator chainGenerator; + + /** + * Constructor. + */ + @Autowired + public LoopTemplatesService(LoopTemplatesRepository loopTemplatesRepository) { + this.loopTemplatesRepository = loopTemplatesRepository; + + } + + public LoopTemplate saveOrUpdateLoopTemplate(LoopTemplate loopTemplate) { + return loopTemplatesRepository.save(loopTemplate); + } + + public List<String> getLoopTemplateNames() { + return loopTemplatesRepository.getAllLoopTemplateNames(); + } + + public List<LoopTemplate> getAllLoopTemplates() { + return loopTemplatesRepository.findAll(); + } + + public LoopTemplate getLoopTemplate(String name) { + return loopTemplatesRepository.findById(name).orElse(null); + } + + public void deleteLoopTemplate(String name) { + loopTemplatesRepository.deleteById(name); + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopType.java b/src/main/java/org/onap/clamp/loop/template/LoopType.java new file mode 100644 index 000000000..ccbc62a83 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopType.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.template; + +/** + * Enums for AllowedLoopType in LoopTemplate enity. + * + */ +public enum LoopType { + OPEN("OPEN"), CLOSED("CLOSED"), HYBRID("HYBRID"); + + private String value; + + private LoopType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java b/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java new file mode 100644 index 000000000..0b05613cb --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/LoopTypeConvertor.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.template; + +import java.util.stream.Stream; +import javax.persistence.AttributeConverter; + +/** + * Attribute Converter to allow using LoopType Enum values in DB and Java classes. + * + */ +public class LoopTypeConvertor implements AttributeConverter<LoopType, String> { + + @Override + public String convertToDatabaseColumn(LoopType loopType) { + if (loopType == null) { + return null; + } + return loopType.getValue(); + } + + @Override + public LoopType convertToEntityAttribute(String value) { + if (value == null) { + return null; + } + + return Stream.of(LoopType.values()).filter(c -> c.getValue().equals(value)).findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModel.java b/src/main/java/org/onap/clamp/loop/template/PolicyModel.java new file mode 100644 index 000000000..3f45d0551 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/PolicyModel.java @@ -0,0 +1,282 @@ +/*- + * ============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.loop.template; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; +import org.onap.clamp.loop.common.AuditEntity; +import org.onap.clamp.util.SemanticVersioning; + +/** + * This class represents the policy model tosca revision that we can have to a + * specific microservice. + */ +@Entity +@Table(name = "policy_models") +@IdClass(PolicyModelId.class) +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public class PolicyModel extends AuditEntity implements Serializable, Comparable<PolicyModel> { + + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522705701376645L; + + /** + * This variable is used to store the type mentioned in the micro-service + * blueprint. + */ + @Id + @Expose + @Column(nullable = false, name = "policy_model_type") + private String policyModelType; + + /** + * Semantic versioning on policy side. + */ + @Id + @Expose + @Column(name = "version", nullable = false) + private String version; + + @Column(columnDefinition = "MEDIUMTEXT", name = "policy_tosca") + private String policyModelTosca; + + @Expose + @Column(name = "policy_acronym") + private String policyAcronym; + + @ManyToMany(mappedBy = "policyModels", fetch = FetchType.EAGER) + private Set<LoopElementModel> usedByElementModels = new HashSet<>(); + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "policy_pdp_group") + private JsonObject policyPdpGroup; + + /** + * usedByElementModels getter. + * + * @return the usedByElementModels + */ + public Set<LoopElementModel> getUsedByElementModels() { + return usedByElementModels; + } + + /** + * policyPdpGroup getter. + * + * @return the policyPdpGroup + */ + public JsonObject getPolicyPdpGroup() { + return policyPdpGroup; + } + + /** + * policyPdpGroup setter. + * + * @param policyPdpGroup the policyPdpGroup to set + */ + public void setPolicyPdpGroup(JsonObject policyPdpGroup) { + this.policyPdpGroup = policyPdpGroup; + } + + /** + * policyModelTosca getter. + * + * @return the policyModelTosca + */ + public String getPolicyModelTosca() { + return policyModelTosca; + } + + /** + * policyModelTosca setter. + * + * @param policyModelTosca the policyModelTosca to set + */ + public void setPolicyModelTosca(String policyModelTosca) { + this.policyModelTosca = policyModelTosca; + } + + /** + * policyModelType getter. + * + * @return the modelType + */ + public String getPolicyModelType() { + return policyModelType; + } + + /** + * policyModelType setter. + * + * @param modelType the modelType to set + */ + public void setPolicyModelType(String modelType) { + this.policyModelType = modelType; + } + + /** + * version getter. + * + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * version setter. + * + * @param version the version to set + */ + public void setVersion(String version) { + // Try to convert it before + this.version = version; + } + + /** + * policyAcronym getter. + * + * @return the policyAcronym value + */ + public String getPolicyAcronym() { + return policyAcronym; + } + + /** + * policyAcronym setter. + * + * @param policyAcronym The policyAcronym to set + */ + public void setPolicyAcronym(String policyAcronym) { + this.policyAcronym = policyAcronym; + } + + /** + * Default constructor for serialization. + */ + public PolicyModel() { + } + + /** + * Constructor. + * + * @param policyType The policyType (referenced in the blueprint + * @param policyModelTosca The policy tosca model in yaml + * @param version the version like 1.0.0 + * @param policyAcronym Subtype for policy if it exists (could be used by UI) + */ + public PolicyModel(String policyType, String policyModelTosca, String version, + String policyAcronym) { + this.policyModelType = policyType; + this.policyModelTosca = policyModelTosca; + this.version = version; + this.policyAcronym = policyAcronym; + if (this.policyAcronym == null) { + this.policyAcronym = createDefaultPolicyAcronym(policyType); + } + } + + /** + * Constructor with acronym generated by default from policyType. + * + * @param policyType The policyType (referenced in the blueprint + * @param policyModelTosca The policy tosca model in yaml + * @param version the version like 1.0.0 + */ + public PolicyModel(String policyType, String policyModelTosca, String version) { + this(policyType, policyModelTosca, version, null); + } + + public static String createDefaultPolicyAcronym(String policyType) { + String[] policyNameArray = policyType.split("\\."); + return policyNameArray[policyNameArray.length - 1]; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((policyModelType == null) ? 0 : policyModelType.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PolicyModel other = (PolicyModel) obj; + if (policyModelType == null) { + if (other.policyModelType != null) { + return false; + } + } else if (!policyModelType.equals(other.policyModelType)) { + return false; + } + if (version == null) { + if (other.version != null) { + return false; + } + } else if (!version.equals(other.version)) { + return false; + } + return true; + } + + @Override + public int compareTo(PolicyModel arg0) { + + if (this.getPolicyModelType().equals(arg0.getPolicyModelType())) { + // Reverse it, so that by default we have the latest in they are same model type + return SemanticVersioning.compare(arg0.getVersion(), this.version); + } else { + return this.getPolicyModelType().compareTo(arg0.getPolicyModelType()); + } + + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java new file mode 100644 index 000000000..c4dd1933b --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelId.java @@ -0,0 +1,93 @@ +/*- + * ============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.loop.template; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; + +public class PolicyModelId implements Serializable { + + /** + * Serial Id. + */ + private static final long serialVersionUID = -2846526482064334745L; + + @Expose + private String policyModelType; + + @Expose + private String version; + + /** + * Default constructor for serialization. + */ + public PolicyModelId() { + + } + + /** + * Constructor. + */ + public PolicyModelId(String policyModelType, String version) { + this.policyModelType = policyModelType; + this.version = version; + } + + /** + * policyModelType getter. + * + * @return the policyModelType + */ + public String getPolicyModelType() { + return policyModelType; + } + + /** + * policyModelType setter. + * + * @param policyModelType the policyModelType to set + */ + public void setPolicyModelType(String policyModelType) { + this.policyModelType = policyModelType; + } + + /** + * version getter. + * + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * version setter. + * + * @param version the version to set + */ + public void setVersion(String version) { + this.version = version; + } +} diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java new file mode 100644 index 000000000..a76e386b5 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelsRepository.java @@ -0,0 +1,38 @@ +/*- + * ============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.loop.template; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface PolicyModelsRepository extends JpaRepository<PolicyModel, PolicyModelId> { + @Query("SELECT policymodel.policyModelType FROM PolicyModel as policymodel") + List<String> getAllPolicyModelType(); + + List<PolicyModel> findByPolicyModelType(String policyModelType); +} diff --git a/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java b/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java new file mode 100644 index 000000000..17cf5c1c8 --- /dev/null +++ b/src/main/java/org/onap/clamp/loop/template/PolicyModelsService.java @@ -0,0 +1,173 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop.template; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.onap.clamp.clds.tosca.ToscaSchemaConstants; +import org.onap.clamp.clds.tosca.ToscaYamlToJsonConvertor; +import org.onap.clamp.policy.pdpgroup.PdpGroup; +import org.onap.clamp.util.SemanticVersioning; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PolicyModelsService { + private final PolicyModelsRepository policyModelsRepository; + private ToscaYamlToJsonConvertor toscaYamlToJsonConvertor; + + @Autowired + public PolicyModelsService(PolicyModelsRepository policyModelrepo, + ToscaYamlToJsonConvertor convertor) { + policyModelsRepository = policyModelrepo; + toscaYamlToJsonConvertor = convertor; + } + + /** + * Save or Update Policy Model. + * + * @param policyModel The policyModel + * @return The Policy Model + */ + public PolicyModel saveOrUpdatePolicyModel(PolicyModel policyModel) { + return policyModelsRepository.saveAndFlush(policyModel); + } + + /** + * Verify whether Policy Model exist by ID. + * + * @param policyModelId The policyModel Id + * @return The flag indicates whether Policy Model exist + */ + public boolean existsById(PolicyModelId policyModelId) { + return policyModelsRepository.existsById(policyModelId); + } + + /** + * Creates or updates the Tosca Policy Model. + * + * @param policyModelTosca The Policymodel object + * @return The Policy Model created + */ + public PolicyModel createNewPolicyModelFromTosca(String policyModelTosca) { + JsonObject jsonObject = toscaYamlToJsonConvertor.validateAndConvertToJson(policyModelTosca); + String policyModelTypeFromTosca = toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject, + ToscaSchemaConstants.METADATA_POLICY_MODEL_TYPE); + Iterable<PolicyModel> models = getAllPolicyModelsByType(policyModelTypeFromTosca); + Collections.sort((List<PolicyModel>) models); + PolicyModel newPolicyModel = new PolicyModel(policyModelTypeFromTosca, policyModelTosca, + SemanticVersioning.incrementMajorVersion(((ArrayList) models).isEmpty() ? null + : ((ArrayList<PolicyModel>) models).get(0).getVersion()), + toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject, + ToscaSchemaConstants.METADATA_ACRONYM)); + return saveOrUpdatePolicyModel(newPolicyModel); + } + + /** + * Update an existing Tosca Policy Model. + * + * @param policyModelType The policy Model type in Tosca yaml + * @param policyModelVersion The policy Version to update + * @param policyModelTosca The Policy Model tosca + * @return The Policy Model updated + */ + public PolicyModel updatePolicyModelTosca(String policyModelType, String policyModelVersion, + String policyModelTosca) { + JsonObject jsonObject = toscaYamlToJsonConvertor.validateAndConvertToJson(policyModelTosca); + PolicyModel thePolicyModel = getPolicyModel(policyModelType, policyModelVersion); + thePolicyModel.setPolicyAcronym(toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject, + ToscaSchemaConstants.METADATA_ACRONYM)); + thePolicyModel.setPolicyModelTosca(policyModelTosca); + return saveOrUpdatePolicyModel(thePolicyModel); + } + + public List<String> getAllPolicyModelTypes() { + return policyModelsRepository.getAllPolicyModelType(); + } + + public Iterable<PolicyModel> getAllPolicyModels() { + return policyModelsRepository.findAll(); + } + + public PolicyModel getPolicyModel(String type, String version) { + return policyModelsRepository.findById(new PolicyModelId(type, version)).orElse(null); + } + + public Iterable<PolicyModel> getAllPolicyModelsByType(String type) { + return policyModelsRepository.findByPolicyModelType(type); + } + + /** + * Retrieves the Tosca model Yaml string. + * + * @param type The Policy Model Type + * @param version The policy model version + * @return The Tosca model Yaml string + */ + public String getPolicyModelTosca(String type, String version) { + return policyModelsRepository.findById(new PolicyModelId(type, version)) + .orElse(new PolicyModel()).getPolicyModelTosca(); + } + + /** + * This method creates an PolicyModel in Db if it does not exist. + * + * @param policyModel The policyModel to save + */ + @Transactional(propagation = Propagation.REQUIRES_NEW) + public PolicyModel savePolicyModelInNewTransaction(PolicyModel policyModel) { + return policyModelsRepository.saveAndFlush(policyModel); + } + + /** + * Update the Pdp Group info in Policy Model DB. + * + * @param pdpGroupList The list of Pdp Group info received from Policy Engine + */ + public void updatePdpGroupInfo(List<PdpGroup> pdpGroupList) { + List<PolicyModel> policyModelList = policyModelsRepository.findAll(); + for (PolicyModel policyModel : policyModelList) { + JsonArray supportedPdpGroups = new JsonArray(); + for (PdpGroup pdpGroup : pdpGroupList) { + JsonObject supportedPdpGroup = pdpGroup.getSupportedSubgroups( + policyModel.getPolicyModelType(), policyModel.getVersion()); + if (supportedPdpGroup != null) { + supportedPdpGroups.add(supportedPdpGroup); + } + } + + if (supportedPdpGroups.size() > 0) { + JsonObject supportedPdpJson = new JsonObject(); + supportedPdpJson.add("supportedPdpGroups", supportedPdpGroups); + policyModel.setPolicyPdpGroup(supportedPdpJson); + policyModelsRepository.saveAndFlush(policyModel); + } + } + } +} diff --git a/src/main/java/org/onap/clamp/policy/Policy.java b/src/main/java/org/onap/clamp/policy/Policy.java new file mode 100644 index 000000000..d84f2c8a0 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/Policy.java @@ -0,0 +1,287 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.policy; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.UnsupportedEncodingException; +import java.util.Map; +import javax.persistence.Column; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.JoinColumns; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.json.JSONObject; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; +import org.onap.clamp.loop.common.AuditEntity; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.PolicyModel; +import org.yaml.snakeyaml.Yaml; + +@MappedSuperclass +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public abstract class Policy extends AuditEntity { + + @Transient + private static final EELFLogger logger = EELFManager.getInstance().getLogger(Policy.class); + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "json_representation", nullable = false) + private JsonObject jsonRepresentation; + + @Expose + @Type(type = "json") + @Column(columnDefinition = "json", name = "configurations_json") + private JsonObject configurationsJson; + + /** + * This attribute can be null when the user add a policy on the loop instance, not the template. + * When null, It therefore indicates that this policy is not by default in the loop template. + */ + @Expose + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "loop_element_model_id") + private LoopElementModel loopElementModel; + + @Expose + @Column(name = "pdp_group") + private String pdpGroup; + + @Expose + @Column(name = "pdp_sub_group") + private String pdpSubgroup; + + @Expose + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumns({@JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"), + @JoinColumn(name = "policy_model_version", referencedColumnName = "version")}) + private PolicyModel policyModel; + + private JsonObject createJsonFromPolicyTosca() { + Map<String, Object> map = + new Yaml().load(this.getPolicyModel() != null ? this.getPolicyModel().getPolicyModelTosca() : ""); + JSONObject jsonObject = new JSONObject(map); + return new Gson().fromJson(jsonObject.toString(), JsonObject.class); + } + + /** + * This method create the policy payload that must be sent to PEF. + * + * @return A String containing the payload + * @throws UnsupportedEncodingException In case of failure + */ + public String createPolicyPayload() throws UnsupportedEncodingException { + JsonObject toscaJson = createJsonFromPolicyTosca(); + + JsonObject policyPayloadResult = new JsonObject(); + + policyPayloadResult.add("tosca_definitions_version", toscaJson.get("tosca_definitions_version")); + + JsonObject topologyTemplateNode = new JsonObject(); + policyPayloadResult.add("topology_template", topologyTemplateNode); + + JsonArray policiesArray = new JsonArray(); + topologyTemplateNode.add("policies", policiesArray); + + JsonObject thisPolicy = new JsonObject(); + policiesArray.add(thisPolicy); + + JsonObject policyDetails = new JsonObject(); + thisPolicy.add(this.getName(), policyDetails); + policyDetails.addProperty("type", this.getPolicyModel().getPolicyModelType()); + policyDetails.addProperty("type_version", this.getPolicyModel().getVersion()); + policyDetails.addProperty("version", this.getPolicyModel().getVersion()); + + JsonObject policyMetadata = new JsonObject(); + policyDetails.add("metadata", policyMetadata); + policyMetadata.addProperty("policy-id", this.getName()); + + policyDetails.add("properties", this.getConfigurationsJson()); + + String policyPayload = new GsonBuilder().setPrettyPrinting().create().toJson(policyPayloadResult); + logger.info("Policy payload: " + policyPayload); + return policyPayload; + } + + + /** + * Name getter. + * + * @return the name + */ + public abstract String getName(); + + /** + * Name setter. + */ + public abstract void setName(String name); + + /** + * jsonRepresentation getter. + * + * @return the jsonRepresentation + */ + public JsonObject getJsonRepresentation() { + return jsonRepresentation; + } + + /** + * jsonRepresentation setter. + * + * @param jsonRepresentation The jsonRepresentation to set + */ + public void setJsonRepresentation(JsonObject jsonRepresentation) { + this.jsonRepresentation = jsonRepresentation; + } + + /** + * Regenerate the Policy Json Representation. + * + * @param toscaConverter The tosca converter required to regenerate the json schema + * @param serviceModel The service model associated + */ + public abstract void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, + Service serviceModel); + + /** + * policyModel getter. + * + * @return the policyModel + */ + public PolicyModel getPolicyModel() { + return policyModel; + } + + /** + * policyModel setter. + * + * @param policyModel The new policyModel + */ + public void setPolicyModel(PolicyModel policyModel) { + this.policyModel = policyModel; + } + + /** + * configurationsJson getter. + * + * @return The configurationsJson + */ + public JsonObject getConfigurationsJson() { + return configurationsJson; + } + + /** + * configurationsJson setter. + * + * @param configurationsJson the configurationsJson to set + */ + public void setConfigurationsJson(JsonObject configurationsJson) { + this.configurationsJson = configurationsJson; + } + + /** + * loopElementModel getter. + * + * @return the loopElementModel + */ + public LoopElementModel getLoopElementModel() { + return loopElementModel; + } + + /** + * loopElementModel setter. + * + * @param loopElementModel the loopElementModel to set + */ + public void setLoopElementModel(LoopElementModel loopElementModel) { + this.loopElementModel = loopElementModel; + } + + /** + * pdpGroup getter. + * + * @return the pdpGroup + */ + public String getPdpGroup() { + return pdpGroup; + } + + /** + * pdpGroup setter. + * + * @param pdpGroup the pdpGroup to set + */ + public void setPdpGroup(String pdpGroup) { + this.pdpGroup = pdpGroup; + } + + /** + * pdpSubgroup getter. + * + * @return the pdpSubgroup + */ + public String getPdpSubgroup() { + return pdpSubgroup; + } + + /** + * pdpSubgroup setter. + * + * @param pdpSubgroup the pdpSubgroup to set + */ + public void setPdpSubgroup(String pdpSubgroup) { + this.pdpSubgroup = pdpSubgroup; + } + + /** + * Generate the policy name. + * + * @param policyType The policy type + * @param serviceName The service name + * @param serviceVersion The service version + * @param resourceName The resource name + * @param blueprintFilename The blueprint file name + * @return The generated policy name + */ + public static String generatePolicyName(String policyType, String serviceName, String serviceVersion, + String resourceName, String blueprintFilename) { + StringBuilder buffer = new StringBuilder(policyType).append("_").append(serviceName).append("_v") + .append(serviceVersion).append("_").append(resourceName).append("_") + .append(blueprintFilename.replaceAll(".yaml", "")); + return buffer.toString().replace('.', '_').replaceAll(" ", ""); + } +} diff --git a/src/main/java/org/onap/clamp/policy/PolicyService.java b/src/main/java/org/onap/clamp/policy/PolicyService.java new file mode 100644 index 000000000..ae15f86da --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/PolicyService.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.policy; + +import java.util.List; +import java.util.Set; + +import org.onap.clamp.loop.Loop; + +public interface PolicyService<T extends Policy> { + + Set<T> updatePolicies(Loop loop, List<T> newPolicies); + + boolean isExisting(String policyName); +} diff --git a/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java b/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java new file mode 100644 index 000000000..0c3f677a1 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/downloader/PolicyEngineController.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.downloader; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.time.Instant; + +import org.json.simple.parser.ParseException; +import org.onap.clamp.clds.client.PolicyEngineServices; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.Scheduled; + +/** + * This class implements a periodic job that is done in the background to + * synchronize policy models available on the policy engine and the clamp + * database table PolicyModel. + */ +@Configuration +@Profile("clamp-policy-controller") +public class PolicyEngineController { + + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineController.class); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval"; + public static final String POLICY_RETRY_LIMIT = "policy.retry.limit"; + + private final PolicyEngineServices policyEngineServices; + + private Instant lastInstantExecuted; + + @Autowired + public PolicyEngineController(PolicyEngineServices policyEngineService, + PolicyModelsRepository policyModelsRepository) { + this.policyEngineServices = policyEngineService; + } + + @Scheduled(fixedRate = 300000) + public synchronized void synchronizeAllPolicies() { + policyEngineServices.synchronizeAllPolicies(); + lastInstantExecuted = Instant.now(); + } + + public Instant getLastInstantExecuted() { + return lastInstantExecuted; + } + + @Scheduled(fixedRate = 300000) + public synchronized void downloadPdpGroups() throws ParseException { + policyEngineServices.downloadPdpGroups(); + } +} diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java new file mode 100644 index 000000000..77627a31a --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicy.java @@ -0,0 +1,276 @@ +/*- + * ============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.policy.microservice; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import org.apache.commons.lang3.RandomStringUtils; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.policy.Policy; + +@Entity +@Table(name = "micro_service_policies") +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public class MicroServicePolicy extends Policy implements Serializable { + /** + * The serial version ID. + */ + private static final long serialVersionUID = 6271238288583332616L; + + @Expose + @Id + @Column(nullable = false, name = "name", unique = true) + private String name; + + @Expose + @Column(name = "context") + private String context; + + @Expose + @Column(name = "device_type_scope") + private String deviceTypeScope; + + @Expose + @Column(name = "shared", nullable = false) + private Boolean shared; + + @ManyToMany(mappedBy = "microServicePolicies", fetch = FetchType.EAGER) + private Set<Loop> usedByLoops = new HashSet<>(); + + @Expose + @Column(name = "dcae_deployment_id") + private String dcaeDeploymentId; + + @Expose + @Column(name = "dcae_deployment_status_url") + private String dcaeDeploymentStatusUrl; + + @Expose + @Column(name = "dcae_blueprint_id") + private String dcaeBlueprintId; + + /** + * Constructor for serialization. + */ + public MicroServicePolicy() { + } + + /** + * The constructor that does not make use of ToscaYamlToJsonConvertor but take + * the jsonRepresentation instead. + * + * @param name The name of the MicroService + * @param policyModel The policy model type of the MicroService + * @param shared The flag indicate whether the MicroService is + * shared + * @param jsonRepresentation The UI representation in json format + * @param loopElementModel The loop element model from which this instance should be created + * @param pdpGroup The Pdp Group info + * @param pdpSubgroup The Pdp Subgroup info + */ + public MicroServicePolicy(String name, PolicyModel policyModel, Boolean shared, + JsonObject jsonRepresentation, LoopElementModel loopElementModel, String pdpGroup, + String pdpSubgroup) { + this.name = name; + this.setPolicyModel(policyModel); + this.shared = shared; + this.setJsonRepresentation(jsonRepresentation); + this.setLoopElementModel(loopElementModel); + this.setPdpGroup(pdpGroup); + this.setPdpSubgroup(pdpSubgroup); + } + + /** + * Constructor with tosca converter. + * + * @param loop The loop instance + * @param service The service model object + * @param loopElementModel The loop element model from which this microservice instance is created + * @param toscaConverter The tosca converter that will used to convert the tosca policy model + */ + public MicroServicePolicy(Loop loop, Service service, LoopElementModel loopElementModel, + ToscaConverterWithDictionarySupport toscaConverter) { + this(Policy.generatePolicyName("MICROSERVICE", service.getName(), service.getVersion(), + loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_' + + loopElementModel.getPolicyModels().first().getVersion(), + RandomStringUtils.randomAlphanumeric(3)), + loopElementModel.getPolicyModels().first(), false, new JsonObject(), loopElementModel, null, null); + this.updateJsonRepresentation(toscaConverter, service); + } + + @Override + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) { + this.setJsonRepresentation( + toscaConverter.convertToscaToJsonSchemaObject(this.getPolicyModel().getPolicyModelTosca(), + this.getPolicyModel().getPolicyModelType(), serviceModel)); + } + + public Boolean getShared() { + return shared; + } + + void setShared(Boolean shared) { + this.shared = shared; + } + + public Set<Loop> getUsedByLoops() { + return usedByLoops; + } + + void setUsedByLoops(Set<Loop> usedBy) { + this.usedByLoops = usedBy; + } + + public String getContext() { + return context; + } + + public void setContext(String context) { + this.context = context; + } + + public String getDeviceTypeScope() { + return deviceTypeScope; + } + + public void setDeviceTypeScope(String deviceTypeScope) { + this.deviceTypeScope = deviceTypeScope; + } + + /** + * dcaeDeploymentId getter. + * + * @return the dcaeDeploymentId + */ + public String getDcaeDeploymentId() { + return dcaeDeploymentId; + } + + /** + * dcaeDeploymentId setter. + * + * @param dcaeDeploymentId the dcaeDeploymentId to set + */ + public void setDcaeDeploymentId(String dcaeDeploymentId) { + this.dcaeDeploymentId = dcaeDeploymentId; + } + + /** + * dcaeDeploymentStatusUrl getter. + * + * @return the dcaeDeploymentStatusUrl + */ + public String getDcaeDeploymentStatusUrl() { + return dcaeDeploymentStatusUrl; + } + + /** + * dcaeDeploymentStatusUrl setter. + * + * @param dcaeDeploymentStatusUrl the dcaeDeploymentStatusUrl to set + */ + public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) { + this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl; + } + + /** + * dcaeBlueprintId getter. + * + * @return the dcaeBlueprintId + */ + public String getDcaeBlueprintId() { + return dcaeBlueprintId; + } + + /** + * dcaeBlueprintId setter. + * + * @param dcaeBlueprintId the dcaeBlueprintId to set + */ + void setDcaeBlueprintId(String dcaeBlueprintId) { + this.dcaeBlueprintId = dcaeBlueprintId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MicroServicePolicy other = (MicroServicePolicy) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } + else if (!name.equals(other.name)) { + return false; + } + return true; + } +} diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java new file mode 100644 index 000000000..38b310ce8 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyRepository.java @@ -0,0 +1,32 @@ +/*- + * ============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.policy.microservice; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MicroServicePolicyRepository extends JpaRepository<MicroServicePolicy, String> { + +} diff --git a/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java new file mode 100644 index 000000000..060e79a63 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/microservice/MicroServicePolicyService.java @@ -0,0 +1,112 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.policy.microservice; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.policy.PolicyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MicroServicePolicyService implements PolicyService<MicroServicePolicy> { + + private final MicroServicePolicyRepository microServiceRepository; + + @Autowired + public MicroServicePolicyService(MicroServicePolicyRepository microServiceRepository) { + this.microServiceRepository = microServiceRepository; + } + + @Override + public Set<MicroServicePolicy> updatePolicies(Loop loop, List<MicroServicePolicy> newMicroservicePolicies) { + return newMicroservicePolicies.stream().map(policy -> getAndUpdateMicroServicePolicy(loop, policy)) + .collect(Collectors.toSet()); + } + + @Override + public boolean isExisting(String policyName) { + return microServiceRepository.existsById(policyName); + } + + /** + * Get and update the MicroService policy properties. + * + * @param loop The loop + * @param policy The new MicroService policy + * @return The updated MicroService policy + */ + public MicroServicePolicy getAndUpdateMicroServicePolicy(Loop loop, MicroServicePolicy policy) { + return microServiceRepository.save( + microServiceRepository + .findById(policy.getName()).map(p -> updateMicroservicePolicyProperties(p, policy, loop)) + .orElse(new MicroServicePolicy(policy.getName(), policy.getPolicyModel(), + policy.getShared(), policy.getJsonRepresentation(), null, policy.getPdpGroup(), + policy.getPdpSubgroup()))); + } + + private MicroServicePolicy updateMicroservicePolicyProperties(MicroServicePolicy oldPolicy, + MicroServicePolicy newPolicy, Loop loop) { + oldPolicy.setConfigurationsJson(newPolicy.getConfigurationsJson()); + if (!oldPolicy.getUsedByLoops().contains(loop)) { + oldPolicy.getUsedByLoops().add(loop); + } + oldPolicy.setPdpGroup(newPolicy.getPdpGroup()); + oldPolicy.setPdpSubgroup(newPolicy.getPdpSubgroup()); + return oldPolicy; + } + + /** + * Update the MicroService policy deployment related parameters. + * + * @param microServicePolicy The micro service policy + * @param deploymentId The deployment ID as returned by DCAE + * @param deploymentUrl The Deployment URL as returned by DCAE + */ + public void updateDcaeDeploymentFields(MicroServicePolicy microServicePolicy, String deploymentId, + String deploymentUrl) { + microServicePolicy.setDcaeDeploymentId(deploymentId); + microServicePolicy.setDcaeDeploymentStatusUrl(deploymentUrl); + microServiceRepository.saveAndFlush(microServicePolicy); + } + + + /** + * Api to refresh the MicroService Policy UI window. + * + * @param microServicePolicy The micro Service policy object + * @param toscaConverter The tosca converter required to convert the tosca model to json schema + * @param loop As a microservice object can belong to multiple loops, we need it here + */ + public void refreshMicroServicePolicyJsonRepresentation(MicroServicePolicy microServicePolicy, + ToscaConverterWithDictionarySupport toscaConverter, + Loop loop) { + microServicePolicy.updateJsonRepresentation(toscaConverter, loop.getModelService()); + this.microServiceRepository.saveAndFlush(microServicePolicy); + + } +} diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java new file mode 100644 index 000000000..4b052427f --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java @@ -0,0 +1,218 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * 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. + * 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.policy.operational; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.apache.commons.lang3.RandomStringUtils; +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.dao.model.jsontype.StringJsonUserType; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.policy.Policy; + +@Entity +@Table(name = "operational_policies") +@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)}) +public class OperationalPolicy extends Policy implements Serializable { + /** + * The serial version ID. + */ + private static final long serialVersionUID = 6117076450841538255L; + + @Transient + private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicy.class); + + @Id + @Expose + @Column(nullable = false, name = "name", unique = true) + private String name; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "loop_id", nullable = false) + private Loop loop; + + /** + * Constructor for serialization. + */ + public OperationalPolicy() { + } + + /** + * The constructor. + * + * @param name The name of the operational policy + * @param configurationsJson The operational policy property in the format of + * json + * @param jsonRepresentation The jsonObject defining the json schema + * @param policyModel The policy model associated if any, can be null + * @param loopElementModel The loop element from which this instance is supposed to be created + * @param pdpGroup The Pdp Group info + * @param pdpSubgroup The Pdp Subgroup info + */ + public OperationalPolicy(String name, JsonObject configurationsJson, + JsonObject jsonRepresentation, PolicyModel policyModel, + LoopElementModel loopElementModel, String pdpGroup, String pdpSubgroup) { + this.name = name; + this.setPolicyModel(policyModel); + this.setConfigurationsJson(configurationsJson); + this.setPdpGroup(pdpGroup); + this.setPdpSubgroup(pdpSubgroup); + this.setLoopElementModel(loopElementModel); + this.setJsonRepresentation(jsonRepresentation); + + } + + /** + * Create an operational policy from a loop element model. + * + * @param loop The parent loop + * @param service The loop service + * @param loopElementModel The loop element model + * @param toscaConverter The tosca converter that must be used to create the Json representation + */ + public OperationalPolicy(Loop loop, Service service, LoopElementModel loopElementModel, + ToscaConverterWithDictionarySupport toscaConverter) { + this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(), + loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_' + + loopElementModel.getPolicyModels().first().getVersion(), + RandomStringUtils.randomAlphanumeric(3)), new JsonObject(), + new JsonObject(), loopElementModel.getPolicyModels().first(), loopElementModel, null, null); + this.setLoop(loop); + this.updateJsonRepresentation(toscaConverter, service); + } + + /** + * Create an operational policy from a policy model. + * + * @param loop The parent loop + * @param service The loop service + * @param policyModel The policy model + * @param toscaConverter The tosca converter that must be used to create the Json representation + */ + public OperationalPolicy(Loop loop, Service service, PolicyModel policyModel, + ToscaConverterWithDictionarySupport toscaConverter) { + this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(), + policyModel.getPolicyAcronym() + '_' + policyModel.getVersion(), + RandomStringUtils.randomAlphanumeric(3)), + new JsonObject(), + new JsonObject(), policyModel, null, null, null); + this.setLoop(loop); + this.updateJsonRepresentation(toscaConverter, service); + } + + public void setLoop(Loop loopName) { + this.loop = loopName; + } + + public Loop getLoop() { + return loop; + } + + @Override + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) { + { + this.setJsonRepresentation(new JsonObject()); + if (this.getPolicyModel() == null) { + return; + } + + // Generic Case + this.setJsonRepresentation(toscaConverter.convertToscaToJsonSchemaObject( + this.getPolicyModel().getPolicyModelTosca(), + this.getPolicyModel().getPolicyModelType(), serviceModel)); + + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + OperationalPolicy other = (OperationalPolicy) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else { + if (!name.equals(other.name)) { + return false; + } + } + return true; + } + + @Override + public String createPolicyPayload() throws UnsupportedEncodingException { + return super.createPolicyPayload(); + + } +} diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java new file mode 100644 index 000000000..c0a6e12cd --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepository.java @@ -0,0 +1,32 @@ +/*- + * ============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.policy.operational; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface OperationalPolicyRepository extends JpaRepository<OperationalPolicy, String> { + void deleteByName(String policyName); +} diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java new file mode 100644 index 000000000..0381f0a2a --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java @@ -0,0 +1,352 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * 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. + * 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.policy.operational; + +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.JsonObject; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.service.Service; + +public class OperationalPolicyRepresentationBuilder { + + private static final EELFLogger logger = + EELFManager.getInstance().getLogger(OperationalPolicyRepresentationBuilder.class); + + public static final String PROPERTIES = "properties"; + public static final String ITEMS = "items"; + public static final String ANY_OF = "anyOf"; + public static final String TITLE = "title"; + public static final String RECIPE = "recipe"; + public static final String DEFAULT = "default"; + public static final String STRING = "string"; + public static final String TYPE = "type"; + public static final String TYPE_LIST = "list"; + public static final String TYPE_OBJECT = "object"; + public static final String TYPE_ARRAY = "array"; + + private OperationalPolicyRepresentationBuilder() { + throw new IllegalStateException("This is Utility class, not supposed to be initiated."); + } + + /** + * This method generates the operational policy json representation that will be + * 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 + */ + public static JsonObject generateOperationalPolicySchema(Service modelJson) { + + JsonObject jsonSchema = null; + try { + jsonSchema = JsonUtils.GSON.fromJson( + ResourceFileUtils + .getResourceAsString("clds/json-schema/operational_policies/operational_policy.json"), + JsonObject.class); + jsonSchema.get(PROPERTIES).getAsJsonObject() + .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies") + .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("target") + .getAsJsonObject().get(ANY_OF).getAsJsonArray().addAll(createAnyOfArray(modelJson, true)); + + // update CDS recipe and payload information to schema + JsonArray actors = jsonSchema.get(PROPERTIES).getAsJsonObject() + .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies") + .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("actor") + .getAsJsonObject().get(ANY_OF).getAsJsonArray(); + + for (JsonElement actor : actors) { + if ("CDS".equalsIgnoreCase(actor.getAsJsonObject().get(TITLE).getAsString())) { + actor.getAsJsonObject().get(PROPERTIES).getAsJsonObject().get(RECIPE).getAsJsonObject() + .get(ANY_OF).getAsJsonArray() + .addAll(createAnyOfArrayForCdsRecipe(modelJson)); + } + } + return jsonSchema; + } catch (IOException e) { + logger.error("Unable to generate the json schema because of an exception", e); + return new JsonObject(); + } + } + + private static JsonObject createSchemaProperty(String title, String type, String defaultValue, String readOnlyFlag, + String[] enumArray) { + JsonObject property = new JsonObject(); + property.addProperty(TITLE, title); + property.addProperty(TYPE, type); + property.addProperty(DEFAULT, defaultValue); + property.addProperty("readOnly", readOnlyFlag); + + if (enumArray != null) { + JsonArray jsonArray = new JsonArray(); + property.add("enum", jsonArray); + for (String val : enumArray) { + jsonArray.add(val); + } + } + return property; + } + + private static JsonArray createVnfSchema(Service modelService, boolean generateType) { + JsonArray vnfSchemaArray = new JsonArray(); + JsonObject modelVnfs = modelService.getResourceByType("VF"); + + for (Entry<String, JsonElement> entry : modelVnfs.entrySet()) { + JsonObject vnfOneOfSchema = new JsonObject(); + vnfOneOfSchema.addProperty(TITLE, "VNF" + "-" + entry.getKey()); + JsonObject properties = new JsonObject(); + if (generateType) { + properties.add(TYPE, createSchemaProperty("Type", STRING, "VNF", "True", null)); + } + properties.add("resourceID", createSchemaProperty("Resource ID", STRING, + modelVnfs.get(entry.getKey()).getAsJsonObject().get("invariantUUID").getAsString(), "True", null)); + + vnfOneOfSchema.add(PROPERTIES, properties); + vnfSchemaArray.add(vnfOneOfSchema); + } + return vnfSchemaArray; + } + + private static JsonArray createBlankEntry() { + JsonArray result = new JsonArray(); + JsonObject blankObject = new JsonObject(); + blankObject.addProperty("title", "User defined"); + blankObject.add("properties", new JsonObject()); + result.add(blankObject); + return result; + } + + private static JsonArray createVfModuleSchema(Service modelService, boolean generateType) { + JsonArray vfModuleOneOfSchemaArray = new JsonArray(); + JsonObject modelVfModules = modelService.getResourceByType("VFModule"); + + for (Entry<String, JsonElement> entry : modelVfModules.entrySet()) { + JsonObject vfModuleOneOfSchema = new JsonObject(); + vfModuleOneOfSchema.addProperty(TITLE, "VFMODULE" + "-" + entry.getKey()); + JsonObject properties = new JsonObject(); + if (generateType) { + properties.add(TYPE, createSchemaProperty("Type", STRING, "VFMODULE", "True", null)); + } + properties.add("resourceID", + createSchemaProperty("Resource ID", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(), + "True", null)); + properties.add("modelInvariantId", + createSchemaProperty("Model Invariant Id (ModelInvariantUUID)", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelInvariantUUID") + .getAsString(), + "True", null)); + properties.add("modelVersionId", + createSchemaProperty("Model Version Id (ModelUUID)", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelUUID").getAsString(), + "True", null)); + properties.add("modelName", + createSchemaProperty("Model Name", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(), + "True", null)); + properties.add("modelVersion", createSchemaProperty("Model Version", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelVersion").getAsString(), + "True", null)); + properties + .add("modelCustomizationId", + createSchemaProperty("Customization ID", STRING, + modelVfModules.get(entry.getKey()).getAsJsonObject() + .get("vfModuleModelCustomizationUUID").getAsString(), "True", + null)); + + vfModuleOneOfSchema.add(PROPERTIES, properties); + vfModuleOneOfSchemaArray.add(vfModuleOneOfSchema); + } + return vfModuleOneOfSchemaArray; + } + + /** + * Create an anyOf array of possible structure we may have for Target. + * + * @param modelJson The service object + * @return A JsonArray with everything inside + */ + public static JsonArray createAnyOfArray(Service modelJson, boolean generateType) { + JsonArray targetOneOfStructure = new JsonArray(); + // First entry must be user defined + targetOneOfStructure.addAll(createBlankEntry()); + targetOneOfStructure.addAll(createVnfSchema(modelJson, generateType)); + targetOneOfStructure.addAll(createVfModuleSchema(modelJson, generateType)); + return targetOneOfStructure; + } + + private static JsonArray createAnyOfArrayForCdsRecipe(Service modelJson) { + JsonArray anyOfStructure = new JsonArray(); + anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("VF"))); + anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("PNF"))); + return anyOfStructure; + } + + private static JsonArray createAnyOfCdsRecipe(JsonObject jsonObject) { + JsonArray schemaArray = new JsonArray(); + for (Entry<String, JsonElement> entry : jsonObject.entrySet()) { + JsonObject controllerProperties = entry.getValue().getAsJsonObject() + .getAsJsonObject("controllerProperties"); + + if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) { + JsonObject workflows = controllerProperties.getAsJsonObject("workflows"); + for (Entry<String, JsonElement> workflowsEntry : workflows.entrySet()) { + JsonObject obj = new JsonObject(); + obj.addProperty(TITLE, workflowsEntry.getKey()); + obj.addProperty(TYPE, "object"); + obj.add(PROPERTIES, createPayloadProperty(workflowsEntry.getValue().getAsJsonObject(), + controllerProperties, workflowsEntry.getKey())); + schemaArray.add(obj); + } + + } + } + return schemaArray; + } + + private static JsonObject createPayloadProperty(JsonObject workFlow, + JsonObject controllerProperties, String workFlowName) { + JsonObject payload = new JsonObject(); + payload.addProperty(TITLE, "Payload"); + payload.addProperty(TYPE, "object"); + payload.add(PROPERTIES, createInputPropertiesForPayload(workFlow, controllerProperties, + workFlowName)); + JsonObject properties = new JsonObject(); + properties.add(RECIPE, createRecipeForCdsWorkflow(workFlowName)); + properties.add("payload", payload); + return properties; + } + + private static JsonObject createRecipeForCdsWorkflow(String workflow) { + JsonObject recipe = new JsonObject(); + recipe.addProperty(TITLE, RECIPE); + recipe.addProperty(TYPE, STRING); + recipe.addProperty(DEFAULT, workflow); + JsonObject options = new JsonObject(); + options.addProperty("hidden", true); + recipe.add("options", options); + return recipe; + } + + /** + * Returns the properties of payload based on the cds work flows. + * + * @param workFlow cds work flows to update payload + * @param controllerProperties cds properties to get blueprint name and + * version + * @param workFlowName work flow name + * @return returns the properties of payload + */ + public static JsonObject createInputPropertiesForPayload(JsonObject workFlow, + JsonObject controllerProperties, + String workFlowName) { + String artifactName = controllerProperties.get("sdnc_model_name").getAsString(); + String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString(); + JsonObject inputs = workFlow.getAsJsonObject("inputs"); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("artifact_name", createSchemaProperty( + "artifact name", STRING, artifactName, "True", null)); + jsonObject.add("artifact_version", createSchemaProperty( + "artifact version", STRING, artifactVersion, "True", null)); + jsonObject.add("mode", createCdsInputProperty( + "mode", STRING, "async" ,null)); + jsonObject.add("data", createDataProperty(inputs, workFlowName)); + return jsonObject; + } + + private static JsonObject createDataProperty(JsonObject inputs, String workflowName) { + JsonObject data = new JsonObject(); + data.addProperty(TITLE, "data"); + JsonObject dataObj = new JsonObject(); + addDataFields(inputs, dataObj, workflowName); + data.add(PROPERTIES, dataObj); + return data; + } + + private static void addDataFields(JsonObject inputs, + JsonObject dataObj, + String workFlowName) { + Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet(); + for (Map.Entry<String, JsonElement> entry : entrySet) { + String key = entry.getKey(); + JsonObject inputProperty = inputs.getAsJsonObject(key); + if (key.equalsIgnoreCase(workFlowName + "-properties")) { + addDataFields(entry.getValue().getAsJsonObject().get("properties").getAsJsonObject(), + dataObj, workFlowName); + } else { + dataObj.add(entry.getKey(), + createCdsInputProperty(key, inputProperty.get(TYPE).getAsString(),null, + entry.getValue().getAsJsonObject())); + } + } + } + + private static JsonObject createCdsInputProperty(String title, + String type, + String defaultValue, + JsonObject cdsProperty) { + JsonObject property = new JsonObject(); + property.addProperty(TITLE, title); + + if (TYPE_LIST.equalsIgnoreCase(type)) { + property.addProperty(TYPE, TYPE_ARRAY); + if (cdsProperty != null && cdsProperty.get(PROPERTIES) != null) { + JsonObject listProperties = new JsonObject(); + listProperties.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject())); + property.add(ITEMS, listProperties); + } + } else if (TYPE_OBJECT.equalsIgnoreCase(type)) { + property.addProperty(TYPE, TYPE_OBJECT); + property.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject())); + } else { + property.addProperty(TYPE, type); + } + + if (defaultValue != null) { + property.addProperty(DEFAULT, defaultValue); + } + return property; + } + + private static JsonObject getProperties(JsonObject inputProperties) { + if (inputProperties == null) { + return null; + } + JsonObject dataObject = new JsonObject(); + addDataFields(inputProperties, dataObject, null); + return dataObject; + } +} diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java new file mode 100644 index 000000000..d5442e145 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicyService.java @@ -0,0 +1,94 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.policy.operational; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.onap.clamp.policy.PolicyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class OperationalPolicyService implements PolicyService<OperationalPolicy> { + + private final OperationalPolicyRepository operationalPolicyRepository; + + private final PolicyModelsRepository policyModelsRepository; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyService.class); + + @Autowired + public OperationalPolicyService(OperationalPolicyRepository repository, + PolicyModelsRepository policyModelsRepository) { + this.operationalPolicyRepository = repository; + this.policyModelsRepository = policyModelsRepository; + } + + @Override + public Set<OperationalPolicy> updatePolicies(Loop loop, List<OperationalPolicy> operationalPolicies) { + return operationalPolicies + .parallelStream() + .map(policy -> + operationalPolicyRepository + .findById(policy.getName()) + .map(p -> setConfiguration(p, policy)) + .orElse(initializeMissingFields(loop, policy))) + .collect(Collectors.toSet()); + } + + @Override + public boolean isExisting(String policyName) { + return operationalPolicyRepository.existsById(policyName); + } + + private OperationalPolicy initializeMissingFields(Loop loop, OperationalPolicy policy) { + policy.setLoop(loop); + return policy; + } + + private OperationalPolicy setConfiguration(OperationalPolicy policy, OperationalPolicy newPolicy) { + policy.setConfigurationsJson(newPolicy.getConfigurationsJson()); + policy.setPdpGroup(newPolicy.getPdpGroup()); + policy.setPdpSubgroup(newPolicy.getPdpSubgroup()); + return policy; + } + + /** + * Api to refresh the Operational Policy UI window. + * + * @param operationalPolicy The operational policy object + * @param toscaConverter the tosca converter required to convert the tosca model to json schema + */ + public void refreshOperationalPolicyJsonRepresentation(OperationalPolicy operationalPolicy, + ToscaConverterWithDictionarySupport toscaConverter) { + operationalPolicy.updateJsonRepresentation(toscaConverter, operationalPolicy.getLoop().getModelService()); + this.operationalPolicyRepository.saveAndFlush(operationalPolicy); + } +} diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java new file mode 100644 index 000000000..a3cf4e053 --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpGroup.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.pdpgroup; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; + +import java.util.List; + +/** + * This class maps the get Pdp Group response to a nice pojo. + */ +public class PdpGroup { + + @Expose + private String name; + + @Expose + private String pdpGroupState; + + @Expose + private List<PdpSubgroup> pdpSubgroups; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPdpGroupState() { + return pdpGroupState; + } + + public void setPdpGroupState(String pdpGroupState) { + this.pdpGroupState = pdpGroupState; + } + + public List<PdpSubgroup> getPdpSubgroups() { + return pdpSubgroups; + } + + public void setPdpSubgroups(List<PdpSubgroup> pdpSubgroups) { + this.pdpSubgroups = pdpSubgroups; + } + + /** + * Get supported subGroups based on the defined policy type and version. + * @param policyType The policy type + * @param version The version + * @return The supported subGroup list in Json format + */ + public JsonObject getSupportedSubgroups(String policyType, String version) { + if (!pdpGroupState.equalsIgnoreCase("ACTIVE")) { + return null; + } + JsonArray supportedSubgroups = new JsonArray(); + for (PdpSubgroup subGroup : pdpSubgroups) { + if (subGroup.getSupportedPolicyTypes().contains(new PolicyModelKey(policyType, version))) { + supportedSubgroups.add(subGroup.getPdpType()); + } + } + if (supportedSubgroups.size() > 0) { + JsonObject supportedPdpGroup = new JsonObject(); + supportedPdpGroup.add(this.name, supportedSubgroups); + return supportedPdpGroup; + } + return null; + } +} diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java new file mode 100644 index 000000000..28de79abf --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PdpSubgroup.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.pdpgroup; + +import com.google.gson.annotations.Expose; +import java.util.List; + +/** + * This class maps the Policy get PDP Group response to a nice pojo. + */ +public class PdpSubgroup { + + @Expose + private String pdpType; + + @Expose + private List<PolicyModelKey> supportedPolicyTypes; + + public String getPdpType() { + return pdpType; + } + + public void setPdpType(String pdpType) { + this.pdpType = pdpType; + } + + public List<PolicyModelKey> getSupportedPolicyTypes() { + return supportedPolicyTypes; + } + + public void setSupportedPolicyTypes(List<PolicyModelKey> supportedPolicyTypes) { + this.supportedPolicyTypes = supportedPolicyTypes; + } + +} diff --git a/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java b/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java new file mode 100644 index 000000000..707b3bd2f --- /dev/null +++ b/src/main/java/org/onap/clamp/policy/pdpgroup/PolicyModelKey.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.pdpgroup; + +import com.google.gson.annotations.Expose; + +import java.io.Serializable; + +public class PolicyModelKey implements Serializable { + + /** + * The serial version ID. + */ + private static final long serialVersionUID = 3307410842013230886L; + + @Expose + private String name; + + @Expose + private String version; + + /** + * Constructor. + */ + public PolicyModelKey(String name, String version) { + this.name = name; + this.version = version; + } + + /** + * name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * version getter. + * + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * version setter. + * + * @param version the version to set + */ + public void setVersion(String version) { + this.version = version; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PolicyModelKey other = (PolicyModelKey) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + if (!name.matches(other.name)) { + return false; + } + } + if (version == null) { + if (other.version != null) { + return false; + } + } else if (!version.equals(other.version)) { + return false; + } + return true; + } +} diff --git a/src/main/java/org/onap/clamp/tosca/Dictionary.java b/src/main/java/org/onap/clamp/tosca/Dictionary.java new file mode 100644 index 000000000..cf514c4bd --- /dev/null +++ b/src/main/java/org/onap/clamp/tosca/Dictionary.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.tosca; + +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import org.onap.clamp.loop.common.AuditEntity; + +/** + * Represents Dictionary. + */ + +@Entity +@Table(name = "dictionary") +public class Dictionary extends AuditEntity implements Serializable { + + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522707701388645L; + + @Id + @Expose + @Column(nullable = false, name = "name", unique = true) + private String name; + + @Expose + @Column(name = "dictionary_second_level") + private int secondLevelDictionary = 0; + + @Expose + @Column(name = "dictionary_type") + private String subDictionaryType; + + @Expose + @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) + @JoinTable( + name = "dictionary_to_dictionaryelements", + joinColumns = @JoinColumn(name = "dictionary_name", referencedColumnName = "name"), + inverseJoinColumns = {@JoinColumn( + name = "dictionary_element_short_name", + referencedColumnName = "short_name")}) + private Set<DictionaryElement> dictionaryElements = new HashSet<>(); + + /** + * name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * secondLevelDictionary getter. + * + * @return the secondLevelDictionary + */ + public int getSecondLevelDictionary() { + return secondLevelDictionary; + } + + /** + * secondLevelDictionary setter. + * + * @param secondLevelDictionary the secondLevelDictionary to set + */ + public void setSecondLevelDictionary(int secondLevelDictionary) { + this.secondLevelDictionary = secondLevelDictionary; + } + + /** + * subDictionaryType getter. + * + * @return the subDictionaryType + */ + public String getSubDictionaryType() { + return subDictionaryType; + } + + /** + * subDictionaryType setter. + * + * @param subDictionaryType the subDictionaryType to set + */ + public void setSubDictionaryType(String subDictionaryType) { + this.subDictionaryType = subDictionaryType; + } + + /** + * dictionaryElements getter. + * + * @return the dictionaryElements List of dictionary element + */ + public Set<DictionaryElement> getDictionaryElements() { + return dictionaryElements; + } + + /** + * Method to add a new dictionaryElement to the list. + * + * @param dictionaryElement The dictionary element + */ + public void addDictionaryElements(DictionaryElement dictionaryElement) { + dictionaryElements.add(dictionaryElement); + dictionaryElement.getUsedByDictionaries().add(this); + } + + /** + * Method to set dictionaryElements. + * + * @param dictionaryElements The dictionary elements set + */ + public void setDictionaryElements(Set<DictionaryElement> dictionaryElements) { + this.dictionaryElements = dictionaryElements; + } + + /** + * Method to delete a dictionaryElement from the list. + * + * @param dictionaryElement The dictionary element + */ + public void removeDictionaryElement(DictionaryElement dictionaryElement) { + dictionaryElements.remove(dictionaryElement); + dictionaryElement.getUsedByDictionaries().remove(this); + } + + /** + * Default Constructor. + */ + public Dictionary() { + + } + + /** + * Constructor. + * + * @param name The Dictionary name + * @param secondLevelDictionary defines if dictionary is a secondary level + * @param subDictionaryType defines the type of secondary level dictionary + */ + public Dictionary(String name, int secondLevelDictionary, String subDictionaryType) { + this.name = name; + this.secondLevelDictionary = secondLevelDictionary; + this.subDictionaryType = subDictionaryType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Dictionary other = (Dictionary) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryElement.java b/src/main/java/org/onap/clamp/tosca/DictionaryElement.java new file mode 100644 index 000000000..43a3106f5 --- /dev/null +++ b/src/main/java/org/onap/clamp/tosca/DictionaryElement.java @@ -0,0 +1,254 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.tosca; + +import com.google.gson.annotations.Expose; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import org.onap.clamp.loop.common.AuditEntity; + +/** + * Represents a Dictionary Item. + */ +@Entity +@Table(name = "dictionary_elements") +public class DictionaryElement extends AuditEntity implements Serializable { + + /** + * The serial version id. + */ + private static final long serialVersionUID = -286522707701388644L; + + @Id + @Expose + @Column(nullable = false, name = "short_name") + private String shortName; + + @Expose + @Column(nullable = false, name = "name") + private String name; + + @Expose + @Column(nullable = false, name = "description") + private String description; + + @Expose + @Column(nullable = false, name = "type") + private String type; + + @Expose + @Column(nullable = true, name = "subdictionary_name") + private String subDictionary; + + @ManyToMany(mappedBy = "dictionaryElements", fetch = FetchType.EAGER) + private Set<Dictionary> usedByDictionaries = new HashSet<>(); + + /** + * name getter. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * name setter. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * shortName getter. + * + * @return the shortName + */ + public String getShortName() { + return shortName; + } + + /** + * shortName setter. + * + * @param shortName the shortName to set + */ + public void setShortName(String shortName) { + this.shortName = shortName; + } + + /** + * description getter. + * + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * description setter. + * + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * type getter. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * type setter. + * + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * subDictionary getter. + * + * @return the subDictionary + */ + public String getSubDictionary() { + return subDictionary; + } + + /** + * subDictionary setter. + * + * @param subDictionary the subDictionary to set + */ + public void setSubDictionary(String subDictionary) { + this.subDictionary = subDictionary; + } + + /** + * usedByDictionaries getter. + * + * @return the usedByDictionaries + */ + public Set<Dictionary> getUsedByDictionaries() { + return usedByDictionaries; + } + + /** + * usedByDictionaries setter. + * + * @param usedByDictionaries the usedByDictionaries to set + */ + public void setUsedByDictionaries(Set<Dictionary> usedByDictionaries) { + this.usedByDictionaries = usedByDictionaries; + } + + /** + * Default Constructor. + */ + public DictionaryElement() { + } + + /** + * Constructor. + * + * @param name The Dictionary element name + * @param shortName The short name + * @param description The description + * @param type The type of element + * @param subDictionary The sub type + */ + public DictionaryElement(String name, String shortName, String description, String type, + String subDictionary) { + this.name = name; + this.shortName = shortName; + this.description = description; + this.type = type; + this.subDictionary = subDictionary; + } + + /** + * Constructor. + * + * @param name The Dictionary element name + * @param shortName The short name + * @param description The description + * @param type The type of element + * @param subDictionary The sub type + */ + public DictionaryElement(String name, String shortName, String description, String type, + String subDictionary, Set<Dictionary> usedByDictionaries) { + this.name = name; + this.shortName = shortName; + this.description = description; + this.type = type; + this.subDictionary = subDictionary; + this.usedByDictionaries = usedByDictionaries; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DictionaryElement other = (DictionaryElement) obj; + if (shortName == null) { + if (other.shortName != null) { + return false; + } + } else if (!shortName.equals(other.shortName)) { + return false; + } + return true; + } +} diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java b/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java new file mode 100644 index 000000000..43f6f1d40 --- /dev/null +++ b/src/main/java/org/onap/clamp/tosca/DictionaryElementsRepository.java @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.tosca; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DictionaryElementsRepository extends JpaRepository<DictionaryElement, String> { + +} diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java b/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java new file mode 100644 index 000000000..ae8430d93 --- /dev/null +++ b/src/main/java/org/onap/clamp/tosca/DictionaryRepository.java @@ -0,0 +1,40 @@ +/*- + * ============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.tosca; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface DictionaryRepository extends JpaRepository<Dictionary, String> { + + @Query("SELECT dict.name FROM Dictionary as dict") + List<String> getAllDictionaryNames(); + + @Query("SELECT dict.name FROM Dictionary as dict where dict.secondLevelDictionary = 1") + List<String> getAllSecondaryLevelDictionaryNames(); + +} diff --git a/src/main/java/org/onap/clamp/tosca/DictionaryService.java b/src/main/java/org/onap/clamp/tosca/DictionaryService.java new file mode 100644 index 000000000..6172641a7 --- /dev/null +++ b/src/main/java/org/onap/clamp/tosca/DictionaryService.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.tosca; + +import com.google.common.collect.Sets; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import javax.persistence.EntityNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DictionaryService { + + private final DictionaryRepository dictionaryRepository; + private final DictionaryElementsRepository dictionaryElementsRepository; + + /** + * Constructor. + */ + @Autowired + public DictionaryService(DictionaryRepository dictionaryRepository, + DictionaryElementsRepository dictionaryElementsRepository) { + this.dictionaryRepository = dictionaryRepository; + this.dictionaryElementsRepository = dictionaryElementsRepository; + + } + + public Dictionary saveOrUpdateDictionary(Dictionary dictionary) { + return dictionaryRepository.saveAndFlush(dictionary); + } + + /** + * Creates or Updates Dictionary Element. + * + * @param dictionaryName The Dictionary name + * @param dictionary The Dictionary object with dictionary elements + * @return updated Dictionary object with all dictionary elements + */ + public Dictionary saveOrUpdateDictionaryElement(String dictionaryName, Dictionary dictionary) { + Dictionary dict = getDictionary(dictionaryName); + + Set<DictionaryElement> newDictionaryElements = dictionary.getDictionaryElements(); + + if (newDictionaryElements != null && !newDictionaryElements.isEmpty()) { + Set<DictionaryElement> updatedDictionaryElements = newDictionaryElements.stream() + .map(dictionaryElement -> getAndUpdateDictionaryElement(dict, dictionaryElement)) + .collect(Collectors.toSet()); + + dict.getDictionaryElements().forEach(dictElement -> { + if (!updatedDictionaryElements.contains(dictElement)) { + updatedDictionaryElements.add(dictElement); + } + }); + dict.setDictionaryElements(updatedDictionaryElements); + } + return dictionaryRepository.saveAndFlush(dict); + + } + + private DictionaryElement getAndUpdateDictionaryElement(Dictionary dictionary, + DictionaryElement element) { + return dictionaryElementsRepository + .save(dictionaryElementsRepository.findById(element.getShortName()) + .map(p -> updateDictionaryElement(p, element, dictionary)) + .orElse(new DictionaryElement(element.getName(), element.getShortName(), + element.getDescription(), element.getType(), element.getSubDictionary(), + Sets.newHashSet(dictionary)))); + } + + public void deleteDictionary(Dictionary dictionary) { + dictionaryRepository.delete(dictionary); + } + + public void deleteDictionary(String dictionaryName) { + dictionaryRepository.deleteById(dictionaryName); + } + + public List<Dictionary> getAllDictionaries() { + return dictionaryRepository.findAll(); + } + + public List<String> getAllSecondaryLevelDictionaryNames() { + return dictionaryRepository.getAllSecondaryLevelDictionaryNames(); + } + + public Dictionary getDictionary(String dictionaryName) { + return dictionaryRepository.findById(dictionaryName).orElseThrow( + () -> new EntityNotFoundException("Couldn't find Dictionary named: " + dictionaryName)); + } + + /** + * Deletes a dictionary element from Dictionary by shortName. + * + * @param dictionaryName The dictionary name + * @param dictionaryElementShortName the dictionary Element Short name + */ + public void deleteDictionaryElement(String dictionaryName, String dictionaryElementShortName) { + if (dictionaryRepository.existsById(dictionaryName)) { + DictionaryElement element = + dictionaryElementsRepository.findById(dictionaryElementShortName).orElse(null); + if (element != null) { + Dictionary dict = getDictionary(dictionaryName); + dict.removeDictionaryElement(element); + dictionaryRepository.saveAndFlush(dict); + } + } + } + + private DictionaryElement updateDictionaryElement(DictionaryElement oldDictionaryElement, + DictionaryElement newDictionaryElement, Dictionary dictionary) { + oldDictionaryElement.setName(newDictionaryElement.getName()); + oldDictionaryElement.setDescription(newDictionaryElement.getDescription()); + oldDictionaryElement.setType(newDictionaryElement.getType()); + oldDictionaryElement.setSubDictionary(newDictionaryElement.getSubDictionary()); + oldDictionaryElement.getUsedByDictionaries().add(dictionary); + return oldDictionaryElement; + } +} diff --git a/src/main/java/org/onap/clamp/util/PassDecoder.java b/src/main/java/org/onap/clamp/util/PassDecoder.java new file mode 100644 index 000000000..b2e4ca2c5 --- /dev/null +++ b/src/main/java/org/onap/clamp/util/PassDecoder.java @@ -0,0 +1,65 @@ +/*- + * ============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.util; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.onap.aaf.cadi.Symm; +import org.onap.clamp.clds.util.ResourceFileUtils; + +/** + * PassDecoder for decrypting the truststore and keystore password. + */ +public class PassDecoder { + /** + * Used to log PassDecoder class. + */ + private static final EELFLogger logger = EELFManager.getInstance().getLogger(PassDecoder.class); + + /** + * Decode the password. + * + * @param encryptedPass The encrypted password + * @param keyFileName The key file name in String + */ + public static String decode(String encryptedPass, String keyFileName) { + if (null == keyFileName) { + logger.debug("Key file is not defined, thus password will not be decrypted"); + return encryptedPass; + } + if (null == encryptedPass) { + logger.error("Encrypted password is not defined"); + return null; + } + try { + return Symm.obtain(ResourceFileUtils.getResourceAsStream(keyFileName)).depass(encryptedPass); + } catch (IOException e) { + logger.error("Exception occurred during the key decryption", e); + return null; + } + } +} diff --git a/src/main/java/org/onap/clamp/util/SemanticVersioning.java b/src/main/java/org/onap/clamp/util/SemanticVersioning.java new file mode 100644 index 000000000..8852e2a4f --- /dev/null +++ b/src/main/java/org/onap/clamp/util/SemanticVersioning.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.util; + +/** + * This class is the base class for object that requires semantic versioning. + * ... This class supports also a.b.c.d... etc ... as a version. + */ +public class SemanticVersioning { + public static final int BEFORE = -1; + public static final int EQUAL = 0; + public static final int AFTER = 1; + public static final String DEFAULT_VERSION = "1.0.0"; + + /** + * The compare method that compare arg0 to arg1. + * + * @param arg0 A version in string for semantic versioning (a.b.c.d...) + * @param arg1 A version in string for semantic versioning (a.b.c.d...) + * @return objects (arg0, arg1) given as parameters. It returns the value: 0: if + * (arg0==arg1) -1: if (arg0 < arg1) 1: if (arg0 > arg1) + */ + public static int compare(String arg0, String arg1) { + + if (arg0 == null && arg1 == null) { + return EQUAL; + } + if (arg0 == null) { + return BEFORE; + } + if (arg1 == null) { + return AFTER; + } + String[] arg0Array = arg0.split("\\."); + String[] arg1Array = arg1.split("\\."); + + int smalestStringLength = Math.min(arg0Array.length, arg1Array.length); + + for (int currentVersionIndex = + 0; currentVersionIndex < smalestStringLength; ++currentVersionIndex) { + if (Integer.parseInt(arg0Array[currentVersionIndex]) < Integer + .parseInt(arg1Array[currentVersionIndex])) { + return BEFORE; + } else if (Integer.parseInt(arg0Array[currentVersionIndex]) > Integer + .parseInt(arg1Array[currentVersionIndex])) { + return AFTER; + } + // equals, so do not return anything, continue + } + if (arg0Array.length == arg1Array.length) { + return EQUAL; + } else { + return Integer.compare(arg0Array.length, arg1Array.length); + } + } + + /** + * Method to increment a version from its current version. + * + * @param currentVersion The current Version + * @return the increment version string + */ + public static String incrementMajorVersion(String currentVersion) { + if (currentVersion == null || currentVersion.isEmpty()) { + return DEFAULT_VERSION; + } + String[] versionArray = currentVersion.split("\\."); + return String.valueOf(Integer.parseInt(versionArray[0]) + 1) + ".0.0"; + } +} diff --git a/src/main/resources/META-INF/resources/swagger.html b/src/main/resources/META-INF/resources/swagger.html new file mode 100644 index 000000000..6f6156c32 --- /dev/null +++ b/src/main/resources/META-INF/resources/swagger.html @@ -0,0 +1,4204 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="UTF-8"> +<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<meta name="generator" content="Asciidoctor 1.5.7.1"> +<title>Clamp Rest API</title> +<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> +<style> +/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ +/* Uncomment @import statement below to use as custom stylesheet */ +/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} +audio,canvas,video{display:inline-block} +audio:not([controls]){display:none;height:0} +script{display:none!important} +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} +a{background:transparent} +a:focus{outline:thin dotted} +a:active,a:hover{outline:0} +h1{font-size:2em;margin:.67em 0} +abbr[title]{border-bottom:1px dotted} +b,strong{font-weight:bold} +dfn{font-style:italic} +hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} +mark{background:#ff0;color:#000} +code,kbd,pre,samp{font-family:monospace;font-size:1em} +pre{white-space:pre-wrap} +q{quotes:"\201C" "\201D" "\2018" "\2019"} +small{font-size:80%} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sup{top:-.5em} +sub{bottom:-.25em} +img{border:0} +svg:not(:root){overflow:hidden} +figure{margin:0} +fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} +legend{border:0;padding:0} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} +button,input{line-height:normal} +button,select{text-transform:none} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} +button[disabled],html input[disabled]{cursor:default} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} +textarea{overflow:auto;vertical-align:top} +table{border-collapse:collapse;border-spacing:0} +*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} +html,body{font-size:100%} +body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} +a:hover{cursor:pointer} +img,object,embed{max-width:100%;height:auto} +object,embed{height:100%} +img{-ms-interpolation-mode:bicubic} +.left{float:left!important} +.right{float:right!important} +.text-left{text-align:left!important} +.text-right{text-align:right!important} +.text-center{text-align:center!important} +.text-justify{text-align:justify!important} +.hide{display:none} +img,object,svg{display:inline-block;vertical-align:middle} +textarea{height:auto;min-height:50px} +select{width:100%} +.center{margin-left:auto;margin-right:auto} +.stretch{width:100%} +.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} +div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} +a{color:#2156a5;text-decoration:underline;line-height:inherit} +a:hover,a:focus{color:#1d4b8f} +a img{border:none} +p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} +p aside{font-size:.875em;line-height:1.35;font-style:italic} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} +h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} +h1{font-size:2.125em} +h2{font-size:1.6875em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} +h4,h5{font-size:1.125em} +h6{font-size:1em} +hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} +em,i{font-style:italic;line-height:inherit} +strong,b{font-weight:bold;line-height:inherit} +small{font-size:60%;line-height:inherit} +code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} +ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} +ul,ol{margin-left:1.5em} +ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} +ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} +ul.square{list-style-type:square} +ul.circle{list-style-type:circle} +ul.disc{list-style-type:disc} +ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} +dl dt{margin-bottom:.3125em;font-weight:bold} +dl dd{margin-bottom:1.25em} +abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} +abbr{text-transform:none} +blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} +blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} +blockquote cite::before{content:"\2014 \0020"} +blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} +blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} +@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} +h1{font-size:2.75em} +h2{font-size:2.3125em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} +h4{font-size:1.4375em}} +table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} +table thead,table tfoot{background:#f7f8f7} +table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} +table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} +table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} +table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} +h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} +.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} +.clearfix::after,.float-group::after{clear:both} +*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} +*:not(pre)>code.nobreak{word-wrap:normal} +*:not(pre)>code.nowrap{white-space:nowrap} +pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} +em em{font-style:normal} +strong strong{font-weight:400} +.keyseq{color:rgba(51,51,51,.8)} +kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} +.keyseq kbd:first-child{margin-left:0} +.keyseq kbd:last-child{margin-right:0} +.menuseq,.menuref{color:#000} +.menuseq b:not(.caret),.menuref{font-weight:inherit} +.menuseq{word-spacing:-.02em} +.menuseq b.caret{font-size:1.25em;line-height:.8} +.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} +b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} +b.button::before{content:"[";padding:0 3px 0 2px} +b.button::after{content:"]";padding:0 2px 0 3px} +p a>code:hover{color:rgba(0,0,0,.9)} +#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} +#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} +#header::after,#content::after,#footnotes::after,#footer::after{clear:both} +#content{margin-top:1.25em} +#content::before{content:none} +#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} +#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} +#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} +#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} +#header .details span:first-child{margin-left:-.125em} +#header .details span.email a{color:rgba(0,0,0,.85)} +#header .details br{display:none} +#header .details br+span::before{content:"\00a0\2013\00a0"} +#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} +#header .details br+span#revremark::before{content:"\00a0|\00a0"} +#header #revnumber{text-transform:capitalize} +#header #revnumber::after{content:"\00a0"} +#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} +#toc{border-bottom:1px solid #efefed;padding-bottom:.5em} +#toc>ul{margin-left:.125em} +#toc ul.sectlevel0>li>a{font-style:italic} +#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} +#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} +#toc li{line-height:1.3334;margin-top:.3334em} +#toc a{text-decoration:none} +#toc a:active{text-decoration:underline} +#toctitle{color:#7a2518;font-size:1.2em} +@media screen and (min-width:768px){#toctitle{font-size:1.375em} +body.toc2{padding-left:15em;padding-right:0} +#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} +#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} +#toc.toc2>ul{font-size:.9em;margin-bottom:0} +#toc.toc2 ul ul{margin-left:0;padding-left:1em} +#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} +body.toc2.toc-right{padding-left:0;padding-right:15em} +body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} +@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} +#toc.toc2{width:20em} +#toc.toc2 #toctitle{font-size:1.375em} +#toc.toc2>ul{font-size:.95em} +#toc.toc2 ul ul{padding-left:1.25em} +body.toc2.toc-right{padding-left:0;padding-right:20em}} +#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +#content #toc>:first-child{margin-top:0} +#content #toc>:last-child{margin-bottom:0} +#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} +#footer-text{color:rgba(255,255,255,.8);line-height:1.44} +#content{margin-bottom:.625em} +.sect1{padding-bottom:.625em} +@media screen and (min-width:768px){#content{margin-bottom:1.25em} +.sect1{padding-bottom:1.25em}} +.sect1:last-child{padding-bottom:0} +.sect1+.sect1{border-top:1px solid #efefed} +#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} +#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} +#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} +#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} +#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} +.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} +table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} +.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} +table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} +.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} +.admonitionblock>table td.icon{text-align:center;width:80px} +.admonitionblock>table td.icon img{max-width:none} +.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} +.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} +.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} +.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} +.exampleblock>.content>:first-child{margin-top:0} +.exampleblock>.content>:last-child{margin-bottom:0} +.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +.sidebarblock>:first-child{margin-top:0} +.sidebarblock>:last-child{margin-bottom:0} +.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} +.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} +.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} +.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} +.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} +.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} +@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} +@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} +.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} +.listingblock pre.highlightjs{padding:0} +.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} +.listingblock pre.prettyprint{border-width:0} +.listingblock>.content{position:relative} +.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} +.listingblock:hover code[data-lang]::before{display:block} +.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} +.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} +table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} +table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} +table.pyhltable td.code{padding-left:.75em;padding-right:0} +pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} +pre.pygments .lineno{display:inline-block;margin-right:.25em} +table.pyhltable .linenodiv{background:none!important;padding-right:0!important} +.quoteblock{margin:0 1em 1.25em 1.5em;display:table} +.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} +.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} +.quoteblock blockquote{margin:0;padding:0;border:0} +.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} +.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} +.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} +.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} +.quoteblock .quoteblock blockquote{padding:0 0 0 .75em} +.quoteblock .quoteblock blockquote::before{display:none} +.verseblock{margin:0 1em 1.25em} +.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} +.verseblock pre strong{font-weight:400} +.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} +.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} +.quoteblock .attribution br,.verseblock .attribution br{display:none} +.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} +.quoteblock.abstract{margin:0 1em 1.25em;display:block} +.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} +.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6} +.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none} +table.tableblock{max-width:100%;border-collapse:separate} +p.tableblock:last-child{margin-bottom:0} +td.tableblock>.content{margin-bottom:-1.25em} +table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} +table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} +table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} +table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} +table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} +table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} +table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} +table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} +table.frame-all{border-width:1px} +table.frame-sides{border-width:0 1px} +table.frame-topbot,table.frame-ends{border-width:1px 0} +table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} +table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} +th.halign-left,td.halign-left{text-align:left} +th.halign-right,td.halign-right{text-align:right} +th.halign-center,td.halign-center{text-align:center} +th.valign-top,td.valign-top{vertical-align:top} +th.valign-bottom,td.valign-bottom{vertical-align:bottom} +th.valign-middle,td.valign-middle{vertical-align:middle} +table thead th,table tfoot th{font-weight:bold} +tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} +tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} +p.tableblock>code:only-child{background:none;padding:0} +p.tableblock{font-size:1em} +td>div.verse{white-space:pre} +ol{margin-left:1.75em} +ul li ol{margin-left:1.5em} +dl dd{margin-left:1.125em} +dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} +ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} +ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} +ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} +ul.unstyled,ol.unstyled{margin-left:0} +ul.checklist{margin-left:.625em} +ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} +ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} +ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} +ul.inline>li{margin-left:1.25em} +.unstyled dl dt{font-weight:400;font-style:normal} +ol.arabic{list-style-type:decimal} +ol.decimal{list-style-type:decimal-leading-zero} +ol.loweralpha{list-style-type:lower-alpha} +ol.upperalpha{list-style-type:upper-alpha} +ol.lowerroman{list-style-type:lower-roman} +ol.upperroman{list-style-type:upper-roman} +ol.lowergreek{list-style-type:lower-greek} +.hdlist>table,.colist>table{border:0;background:none} +.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} +td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} +td.hdlist1{font-weight:bold;padding-bottom:1.25em} +.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} +.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} +.colist td:not([class]):first-child img{max-width:none} +.colist td:not([class]):last-child{padding:.25em 0} +.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} +.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} +.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} +.imageblock>.title{margin-bottom:0} +.imageblock.thumb,.imageblock.th{border-width:6px} +.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} +.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} +.image.left{margin-right:.625em} +.image.right{margin-left:.625em} +a.image{text-decoration:none;display:inline-block} +a.image object{pointer-events:none} +sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} +sup.footnote a,sup.footnoteref a{text-decoration:none} +sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} +#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} +#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} +#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} +#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} +#footnotes .footnote:last-of-type{margin-bottom:0} +#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} +.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} +.gist .file-data>table td.line-data{width:99%} +div.unbreakable{page-break-inside:avoid} +.big{font-size:larger} +.small{font-size:smaller} +.underline{text-decoration:underline} +.overline{text-decoration:overline} +.line-through{text-decoration:line-through} +.aqua{color:#00bfbf} +.aqua-background{background-color:#00fafa} +.black{color:#000} +.black-background{background-color:#000} +.blue{color:#0000bf} +.blue-background{background-color:#0000fa} +.fuchsia{color:#bf00bf} +.fuchsia-background{background-color:#fa00fa} +.gray{color:#606060} +.gray-background{background-color:#7d7d7d} +.green{color:#006000} +.green-background{background-color:#007d00} +.lime{color:#00bf00} +.lime-background{background-color:#00fa00} +.maroon{color:#600000} +.maroon-background{background-color:#7d0000} +.navy{color:#000060} +.navy-background{background-color:#00007d} +.olive{color:#606000} +.olive-background{background-color:#7d7d00} +.purple{color:#600060} +.purple-background{background-color:#7d007d} +.red{color:#bf0000} +.red-background{background-color:#fa0000} +.silver{color:#909090} +.silver-background{background-color:#bcbcbc} +.teal{color:#006060} +.teal-background{background-color:#007d7d} +.white{color:#bfbfbf} +.white-background{background-color:#fafafa} +.yellow{color:#bfbf00} +.yellow-background{background-color:#fafa00} +span.icon>.fa{cursor:default} +a span.icon>.fa{cursor:inherit} +.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} +.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} +.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} +.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} +.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} +.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} +.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} +.conum[data-value] *{color:#fff!important} +.conum[data-value]+b{display:none} +.conum[data-value]::after{content:attr(data-value)} +pre .conum[data-value]{position:relative;top:-.125em} +b.conum *{color:inherit!important} +.conum:not([data-value]):empty{display:none} +dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} +h1,h2,p,td.content,span.alt{letter-spacing:-.01em} +p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} +p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} +p{margin-bottom:1.25rem} +.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} +.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} +.print-only{display:none!important} +@page{margin:1.25cm .75cm} +@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} +html{font-size:80%} +a{color:inherit!important;text-decoration:underline!important} +a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} +a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} +abbr[title]::after{content:" (" attr(title) ")"} +pre,blockquote,tr,img,object,svg{page-break-inside:avoid} +thead{display:table-header-group} +svg{max-width:100%} +p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} +h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} +#toc,.sidebarblock,.exampleblock>.content{background:none!important} +#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} +body.book #header{text-align:center} +body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} +body.book #header .details{border:0!important;display:block;padding:0!important} +body.book #header .details span:first-child{margin-left:0!important} +body.book #header .details br{display:block} +body.book #header .details br+span::before{content:none!important} +body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} +body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} +.listingblock code[data-lang]::before{display:block} +#footer{padding:0 .9375em} +.hide-on-print{display:none!important} +.print-only{display:block!important} +.hide-for-print{display:none!important} +.show-for-print{display:inherit!important}} +@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} +.sect1{padding:0!important} +.sect1+.sect1{border:0} +#footer{background:none} +#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} +@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} +</style> +</head> +<body class="book toc2 toc-left"> +<div id="header"> +<h1>Clamp Rest API</h1> +<div id="toc" class="toc2"> +<div id="toctitle">Table of Contents</div> +<ul class="sectlevel1"> +<li><a href="#_overview">1. Overview</a> +<ul class="sectlevel2"> +<li><a href="#_version_information">1.1. Version information</a></li> +<li><a href="#_uri_scheme">1.2. URI scheme</a></li> +</ul> +</li> +<li><a href="#_paths">2. Paths</a> +<ul class="sectlevel2"> +<li><a href="#_route35">2.1. GET /v1/healthcheck</a> +<ul class="sectlevel3"> +<li><a href="#_responses">2.1.1. Responses</a></li> +<li><a href="#_produces">2.1.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route36">2.2. GET /v1/user/getUser</a> +<ul class="sectlevel3"> +<li><a href="#_responses_2">2.2.1. Responses</a></li> +<li><a href="#_produces_2">2.2.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route34">2.3. GET /v2/clampInformation</a> +<ul class="sectlevel3"> +<li><a href="#_responses_3">2.3.1. Responses</a></li> +<li><a href="#_produces_3">2.3.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route19">2.4. GET /v2/dictionary</a> +<ul class="sectlevel3"> +<li><a href="#_responses_4">2.4.1. Responses</a></li> +<li><a href="#_produces_4">2.4.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route22">2.5. PUT /v2/dictionary</a> +<ul class="sectlevel3"> +<li><a href="#_parameters">2.5.1. Parameters</a></li> +<li><a href="#_responses_5">2.5.2. Responses</a></li> +<li><a href="#_consumes">2.5.3. Consumes</a></li> +<li><a href="#_produces_5">2.5.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route20">2.6. GET /v2/dictionary/secondary/names</a> +<ul class="sectlevel3"> +<li><a href="#_responses_6">2.6.1. Responses</a></li> +<li><a href="#_produces_6">2.6.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route21">2.7. GET /v2/dictionary/{dictionaryName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_2">2.7.1. Parameters</a></li> +<li><a href="#_responses_7">2.7.2. Responses</a></li> +<li><a href="#_produces_7">2.7.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route23">2.8. PUT /v2/dictionary/{name}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_3">2.8.1. Parameters</a></li> +<li><a href="#_responses_8">2.8.2. Responses</a></li> +<li><a href="#_consumes_2">2.8.3. Consumes</a></li> +<li><a href="#_produces_8">2.8.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route24">2.9. DELETE /v2/dictionary/{name}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_4">2.9.1. Parameters</a></li> +<li><a href="#_responses_9">2.9.2. Responses</a></li> +<li><a href="#_produces_9">2.9.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route25">2.10. DELETE /v2/dictionary/{name}/elements/{shortName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_5">2.10.1. Parameters</a></li> +<li><a href="#_responses_10">2.10.2. Responses</a></li> +<li><a href="#_produces_10">2.10.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route16">2.11. PUT /v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_6">2.11.1. Parameters</a></li> +<li><a href="#_responses_11">2.11.2. Responses</a></li> +<li><a href="#_produces_11">2.11.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route18">2.12. POST /v2/loop/create/{loopName}?templateName={templateName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_7">2.12.1. Parameters</a></li> +<li><a href="#_responses_12">2.12.2. Responses</a></li> +<li><a href="#_consumes_3">2.12.3. Consumes</a></li> +<li><a href="#_produces_12">2.12.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route14">2.13. PUT /v2/loop/delete/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_8">2.13.1. Parameters</a></li> +<li><a href="#_responses_13">2.13.2. Responses</a></li> +</ul> +</li> +<li><a href="#_route7">2.14. PUT /v2/loop/deploy/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_9">2.14.1. Parameters</a></li> +<li><a href="#_responses_14">2.14.2. Responses</a></li> +<li><a href="#_produces_13">2.14.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route2">2.15. GET /v2/loop/getAllNames</a> +<ul class="sectlevel3"> +<li><a href="#_responses_15">2.15.1. Responses</a></li> +<li><a href="#_produces_14">2.15.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route15">2.16. GET /v2/loop/getstatus/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_10">2.16.1. Parameters</a></li> +<li><a href="#_responses_16">2.16.2. Responses</a></li> +<li><a href="#_produces_15">2.16.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route8">2.17. PUT /v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_11">2.17.1. Parameters</a></li> +<li><a href="#_responses_17">2.17.2. Responses</a></li> +<li><a href="#_produces_16">2.17.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route9">2.18. PUT /v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_12">2.18.1. Parameters</a></li> +<li><a href="#_responses_18">2.18.2. Responses</a></li> +<li><a href="#_produces_17">2.18.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route17">2.19. PUT /v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_13">2.19.1. Parameters</a></li> +<li><a href="#_responses_19">2.19.2. Responses</a></li> +<li><a href="#_produces_18">2.19.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route12">2.20. PUT /v2/loop/restart/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_14">2.20.1. Parameters</a></li> +<li><a href="#_responses_20">2.20.2. Responses</a></li> +<li><a href="#_produces_19">2.20.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route11">2.21. PUT /v2/loop/stop/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_15">2.21.1. Parameters</a></li> +<li><a href="#_responses_21">2.21.2. Responses</a></li> +<li><a href="#_produces_20">2.21.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route13">2.22. PUT /v2/loop/submit/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_16">2.22.1. Parameters</a></li> +<li><a href="#_responses_22">2.22.2. Responses</a></li> +<li><a href="#_produces_21">2.22.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route10">2.23. PUT /v2/loop/undeploy/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_17">2.23.1. Parameters</a></li> +<li><a href="#_responses_23">2.23.2. Responses</a></li> +<li><a href="#_produces_22">2.23.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route4">2.24. POST /v2/loop/updateGlobalProperties/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_18">2.24.1. Parameters</a></li> +<li><a href="#_responses_24">2.24.2. Responses</a></li> +<li><a href="#_consumes_4">2.24.3. Consumes</a></li> +<li><a href="#_produces_23">2.24.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route6">2.25. POST /v2/loop/updateMicroservicePolicy/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_19">2.25.1. Parameters</a></li> +<li><a href="#_responses_25">2.25.2. Responses</a></li> +<li><a href="#_consumes_5">2.25.3. Consumes</a></li> +<li><a href="#_produces_24">2.25.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route5">2.26. POST /v2/loop/updateOperationalPolicies/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_20">2.26.1. Parameters</a></li> +<li><a href="#_responses_26">2.26.2. Responses</a></li> +<li><a href="#_consumes_6">2.26.3. Consumes</a></li> +<li><a href="#_produces_25">2.26.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route3">2.27. GET /v2/loop/{loopName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_21">2.27.1. Parameters</a></li> +<li><a href="#_responses_27">2.27.2. Responses</a></li> +<li><a href="#_produces_26">2.27.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route29">2.28. POST /v2/policyToscaModels</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_22">2.28.1. Parameters</a></li> +<li><a href="#_responses_28">2.28.2. Responses</a></li> +<li><a href="#_consumes_7">2.28.3. Consumes</a></li> +<li><a href="#_produces_27">2.28.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route26">2.29. GET /v2/policyToscaModels</a> +<ul class="sectlevel3"> +<li><a href="#_responses_29">2.29.1. Responses</a></li> +<li><a href="#_produces_28">2.29.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route28">2.30. GET /v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_23">2.30.1. Parameters</a></li> +<li><a href="#_responses_30">2.30.2. Responses</a></li> +<li><a href="#_produces_29">2.30.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route27">2.31. GET /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_24">2.31.1. Parameters</a></li> +<li><a href="#_responses_31">2.31.2. Responses</a></li> +<li><a href="#_produces_30">2.31.3. Produces</a></li> +</ul> +</li> +<li><a href="#_route30">2.32. PUT /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_25">2.32.1. Parameters</a></li> +<li><a href="#_responses_32">2.32.2. Responses</a></li> +<li><a href="#_consumes_8">2.32.3. Consumes</a></li> +<li><a href="#_produces_31">2.32.4. Produces</a></li> +</ul> +</li> +<li><a href="#_route31">2.33. GET /v2/templates</a> +<ul class="sectlevel3"> +<li><a href="#_responses_33">2.33.1. Responses</a></li> +<li><a href="#_produces_32">2.33.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route33">2.34. GET /v2/templates/names</a> +<ul class="sectlevel3"> +<li><a href="#_responses_34">2.34.1. Responses</a></li> +<li><a href="#_produces_33">2.34.2. Produces</a></li> +</ul> +</li> +<li><a href="#_route32">2.35. GET /v2/templates/{templateName}</a> +<ul class="sectlevel3"> +<li><a href="#_parameters_26">2.35.1. Parameters</a></li> +<li><a href="#_responses_35">2.35.2. Responses</a></li> +<li><a href="#_produces_34">2.35.3. Produces</a></li> +</ul> +</li> +</ul> +</li> +<li><a href="#_definitions">3. Definitions</a> +<ul class="sectlevel2"> +<li><a href="#_clampinformation">3.1. ClampInformation</a></li> +<li><a href="#_cldshealthcheck">3.2. CldsHealthCheck</a></li> +<li><a href="#_dictionary">3.3. Dictionary</a></li> +<li><a href="#_dictionaryelement">3.4. DictionaryElement</a></li> +<li><a href="#_externalcomponent">3.5. ExternalComponent</a></li> +<li><a href="#_externalcomponentstate">3.6. ExternalComponentState</a></li> +<li><a href="#_jsonarray">3.7. JsonArray</a></li> +<li><a href="#_jsonnull">3.8. JsonNull</a></li> +<li><a href="#_jsonobject">3.9. JsonObject</a></li> +<li><a href="#_jsonprimitive">3.10. JsonPrimitive</a></li> +<li><a href="#_loop">3.11. Loop</a></li> +<li><a href="#_loopelementmodel">3.12. LoopElementModel</a></li> +<li><a href="#_looplog">3.13. LoopLog</a></li> +<li><a href="#_looptemplate">3.14. LoopTemplate</a></li> +<li><a href="#_looptemplateloopelementmodel">3.15. LoopTemplateLoopElementModel</a></li> +<li><a href="#_microservicepolicy">3.16. MicroServicePolicy</a></li> +<li><a href="#_number">3.17. Number</a></li> +<li><a href="#_operationalpolicy">3.18. OperationalPolicy</a></li> +<li><a href="#_policymodel">3.19. PolicyModel</a></li> +<li><a href="#_service">3.20. Service</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div id="content"> +<div class="sect1"> +<h2 id="_overview"><a class="anchor" href="#_overview"></a><a class="link" href="#_overview">1. Overview</a></h2> +<div class="sectionbody"> +<div class="sect2"> +<h3 id="_version_information"><a class="anchor" href="#_version_information"></a><a class="link" href="#_version_information">1.1. Version information</a></h3> +<div class="paragraph"> +<p><em>Version</em> : 5.1.3-SNAPSHOT</p> +</div> +</div> +<div class="sect2"> +<h3 id="_uri_scheme"><a class="anchor" href="#_uri_scheme"></a><a class="link" href="#_uri_scheme">1.2. URI scheme</a></h3> +<div class="paragraph"> +<p><em>Host</em> : localhost:8443<br> +<em>BasePath</em> : /restservices/clds/<br> +<em>Schemes</em> : HTTP</p> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_paths"><a class="anchor" href="#_paths"></a><a class="link" href="#_paths">2. Paths</a></h2> +<div class="sectionbody"> +<div class="sect2"> +<h3 id="_route35"><a class="anchor" href="#_route35"></a><a class="link" href="#_route35">2.1. GET /v1/healthcheck</a></h3> +<div class="sect3"> +<h4 id="_responses"><a class="anchor" href="#_responses"></a><a class="link" href="#_responses">2.1.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_cldshealthcheck">CldsHealthCheck</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces"><a class="anchor" href="#_produces"></a><a class="link" href="#_produces">2.1.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route36"><a class="anchor" href="#_route36"></a><a class="link" href="#_route36">2.2. GET /v1/user/getUser</a></h3> +<div class="sect3"> +<h4 id="_responses_2"><a class="anchor" href="#_responses_2"></a><a class="link" href="#_responses_2">2.2.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 33.3333%;"> +<col style="width: 66.6667%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_2"><a class="anchor" href="#_produces_2"></a><a class="link" href="#_produces_2">2.2.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>text/plain</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route34"><a class="anchor" href="#_route34"></a><a class="link" href="#_route34">2.3. GET /v2/clampInformation</a></h3> +<div class="sect3"> +<h4 id="_responses_3"><a class="anchor" href="#_responses_3"></a><a class="link" href="#_responses_3">2.3.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_clampinformation">ClampInformation</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_3"><a class="anchor" href="#_produces_3"></a><a class="link" href="#_produces_3">2.3.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route19"><a class="anchor" href="#_route19"></a><a class="link" href="#_route19">2.4. GET /v2/dictionary</a></h3> +<div class="sect3"> +<h4 id="_responses_4"><a class="anchor" href="#_responses_4"></a><a class="link" href="#_responses_4">2.4.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_4"><a class="anchor" href="#_produces_4"></a><a class="link" href="#_produces_4">2.4.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route22"><a class="anchor" href="#_route22"></a><a class="link" href="#_route22">2.5. PUT /v2/dictionary</a></h3> +<div class="sect3"> +<h4 id="_parameters"><a class="anchor" href="#_parameters"></a><a class="link" href="#_parameters">2.5.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_5"><a class="anchor" href="#_responses_5"></a><a class="link" href="#_responses_5">2.5.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes"><a class="anchor" href="#_consumes"></a><a class="link" href="#_consumes">2.5.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_5"><a class="anchor" href="#_produces_5"></a><a class="link" href="#_produces_5">2.5.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route20"><a class="anchor" href="#_route20"></a><a class="link" href="#_route20">2.6. GET /v2/dictionary/secondary/names</a></h3> +<div class="sect3"> +<h4 id="_responses_6"><a class="anchor" href="#_responses_6"></a><a class="link" href="#_responses_6">2.6.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< string > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_6"><a class="anchor" href="#_produces_6"></a><a class="link" href="#_produces_6">2.6.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route21"><a class="anchor" href="#_route21"></a><a class="link" href="#_route21">2.7. GET /v2/dictionary/{dictionaryName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_2"><a class="anchor" href="#_parameters_2"></a><a class="link" href="#_parameters_2">2.7.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dictionaryName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_7"><a class="anchor" href="#_responses_7"></a><a class="link" href="#_responses_7">2.7.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_7"><a class="anchor" href="#_produces_7"></a><a class="link" href="#_produces_7">2.7.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route23"><a class="anchor" href="#_route23"></a><a class="link" href="#_route23">2.8. PUT /v2/dictionary/{name}</a></h3> +<div class="sect3"> +<h4 id="_parameters_3"><a class="anchor" href="#_parameters_3"></a><a class="link" href="#_parameters_3">2.8.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_8"><a class="anchor" href="#_responses_8"></a><a class="link" href="#_responses_8">2.8.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_2"><a class="anchor" href="#_consumes_2"></a><a class="link" href="#_consumes_2">2.8.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_8"><a class="anchor" href="#_produces_8"></a><a class="link" href="#_produces_8">2.8.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route24"><a class="anchor" href="#_route24"></a><a class="link" href="#_route24">2.9. DELETE /v2/dictionary/{name}</a></h3> +<div class="sect3"> +<h4 id="_parameters_4"><a class="anchor" href="#_parameters_4"></a><a class="link" href="#_parameters_4">2.9.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_9"><a class="anchor" href="#_responses_9"></a><a class="link" href="#_responses_9">2.9.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 33.3333%;"> +<col style="width: 66.6667%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_9"><a class="anchor" href="#_produces_9"></a><a class="link" href="#_produces_9">2.9.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route25"><a class="anchor" href="#_route25"></a><a class="link" href="#_route25">2.10. DELETE /v2/dictionary/{name}/elements/{shortName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_5"><a class="anchor" href="#_parameters_5"></a><a class="link" href="#_parameters_5">2.10.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_10"><a class="anchor" href="#_responses_10"></a><a class="link" href="#_responses_10">2.10.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 33.3333%;"> +<col style="width: 66.6667%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_10"><a class="anchor" href="#_produces_10"></a><a class="link" href="#_produces_10">2.10.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route16"><a class="anchor" href="#_route16"></a><a class="link" href="#_route16">2.11. PUT /v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}</a></h3> +<div class="sect3"> +<h4 id="_parameters_6"><a class="anchor" href="#_parameters_6"></a><a class="link" href="#_parameters_6">2.11.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyType</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_11"><a class="anchor" href="#_responses_11"></a><a class="link" href="#_responses_11">2.11.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_11"><a class="anchor" href="#_produces_11"></a><a class="link" href="#_produces_11">2.11.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route18"><a class="anchor" href="#_route18"></a><a class="link" href="#_route18">2.12. POST /v2/loop/create/{loopName}?templateName={templateName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_7"><a class="anchor" href="#_parameters_7"></a><a class="link" href="#_parameters_7">2.12.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName}?templateName={templateName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_12"><a class="anchor" href="#_responses_12"></a><a class="link" href="#_responses_12">2.12.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_3"><a class="anchor" href="#_consumes_3"></a><a class="link" href="#_consumes_3">2.12.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_12"><a class="anchor" href="#_produces_12"></a><a class="link" href="#_produces_12">2.12.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route14"><a class="anchor" href="#_route14"></a><a class="link" href="#_route14">2.13. PUT /v2/loop/delete/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_8"><a class="anchor" href="#_parameters_8"></a><a class="link" href="#_parameters_8">2.13.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_13"><a class="anchor" href="#_responses_13"></a><a class="link" href="#_responses_13">2.13.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 33.3333%;"> +<col style="width: 66.6667%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td> +</tr> +</tbody> +</table> +</div> +</div> +<div class="sect2"> +<h3 id="_route7"><a class="anchor" href="#_route7"></a><a class="link" href="#_route7">2.14. PUT /v2/loop/deploy/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_9"><a class="anchor" href="#_parameters_9"></a><a class="link" href="#_parameters_9">2.14.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_14"><a class="anchor" href="#_responses_14"></a><a class="link" href="#_responses_14">2.14.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_13"><a class="anchor" href="#_produces_13"></a><a class="link" href="#_produces_13">2.14.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route2"><a class="anchor" href="#_route2"></a><a class="link" href="#_route2">2.15. GET /v2/loop/getAllNames</a></h3> +<div class="sect3"> +<h4 id="_responses_15"><a class="anchor" href="#_responses_15"></a><a class="link" href="#_responses_15">2.15.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< string > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_14"><a class="anchor" href="#_produces_14"></a><a class="link" href="#_produces_14">2.15.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route15"><a class="anchor" href="#_route15"></a><a class="link" href="#_route15">2.16. GET /v2/loop/getstatus/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_10"><a class="anchor" href="#_parameters_10"></a><a class="link" href="#_parameters_10">2.16.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_16"><a class="anchor" href="#_responses_16"></a><a class="link" href="#_responses_16">2.16.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_15"><a class="anchor" href="#_produces_15"></a><a class="link" href="#_produces_15">2.16.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route8"><a class="anchor" href="#_route8"></a><a class="link" href="#_route8">2.17. PUT /v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_11"><a class="anchor" href="#_parameters_11"></a><a class="link" href="#_parameters_11">2.17.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>microServicePolicyName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_17"><a class="anchor" href="#_responses_17"></a><a class="link" href="#_responses_17">2.17.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_16"><a class="anchor" href="#_produces_16"></a><a class="link" href="#_produces_16">2.17.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route9"><a class="anchor" href="#_route9"></a><a class="link" href="#_route9">2.18. PUT /v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_12"><a class="anchor" href="#_parameters_12"></a><a class="link" href="#_parameters_12">2.18.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>operationalPolicyName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_18"><a class="anchor" href="#_responses_18"></a><a class="link" href="#_responses_18">2.18.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_17"><a class="anchor" href="#_produces_17"></a><a class="link" href="#_produces_17">2.18.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route17"><a class="anchor" href="#_route17"></a><a class="link" href="#_route17">2.19. PUT /v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_13"><a class="anchor" href="#_parameters_13"></a><a class="link" href="#_parameters_13">2.19.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyType</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_19"><a class="anchor" href="#_responses_19"></a><a class="link" href="#_responses_19">2.19.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_18"><a class="anchor" href="#_produces_18"></a><a class="link" href="#_produces_18">2.19.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route12"><a class="anchor" href="#_route12"></a><a class="link" href="#_route12">2.20. PUT /v2/loop/restart/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_14"><a class="anchor" href="#_parameters_14"></a><a class="link" href="#_parameters_14">2.20.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_20"><a class="anchor" href="#_responses_20"></a><a class="link" href="#_responses_20">2.20.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_19"><a class="anchor" href="#_produces_19"></a><a class="link" href="#_produces_19">2.20.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route11"><a class="anchor" href="#_route11"></a><a class="link" href="#_route11">2.21. PUT /v2/loop/stop/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_15"><a class="anchor" href="#_parameters_15"></a><a class="link" href="#_parameters_15">2.21.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_21"><a class="anchor" href="#_responses_21"></a><a class="link" href="#_responses_21">2.21.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_20"><a class="anchor" href="#_produces_20"></a><a class="link" href="#_produces_20">2.21.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route13"><a class="anchor" href="#_route13"></a><a class="link" href="#_route13">2.22. PUT /v2/loop/submit/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_16"><a class="anchor" href="#_parameters_16"></a><a class="link" href="#_parameters_16">2.22.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_22"><a class="anchor" href="#_responses_22"></a><a class="link" href="#_responses_22">2.22.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_21"><a class="anchor" href="#_produces_21"></a><a class="link" href="#_produces_21">2.22.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route10"><a class="anchor" href="#_route10"></a><a class="link" href="#_route10">2.23. PUT /v2/loop/undeploy/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_17"><a class="anchor" href="#_parameters_17"></a><a class="link" href="#_parameters_17">2.23.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_23"><a class="anchor" href="#_responses_23"></a><a class="link" href="#_responses_23">2.23.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_22"><a class="anchor" href="#_produces_22"></a><a class="link" href="#_produces_22">2.23.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route4"><a class="anchor" href="#_route4"></a><a class="link" href="#_route4">2.24. POST /v2/loop/updateGlobalProperties/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_18"><a class="anchor" href="#_parameters_18"></a><a class="link" href="#_parameters_18">2.24.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_24"><a class="anchor" href="#_responses_24"></a><a class="link" href="#_responses_24">2.24.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_4"><a class="anchor" href="#_consumes_4"></a><a class="link" href="#_consumes_4">2.24.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_23"><a class="anchor" href="#_produces_23"></a><a class="link" href="#_produces_23">2.24.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route6"><a class="anchor" href="#_route6"></a><a class="link" href="#_route6">2.25. POST /v2/loop/updateMicroservicePolicy/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_19"><a class="anchor" href="#_parameters_19"></a><a class="link" href="#_parameters_19">2.25.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_microservicepolicy">MicroServicePolicy</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_25"><a class="anchor" href="#_responses_25"></a><a class="link" href="#_responses_25">2.25.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_microservicepolicy">MicroServicePolicy</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_5"><a class="anchor" href="#_consumes_5"></a><a class="link" href="#_consumes_5">2.25.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_24"><a class="anchor" href="#_produces_24"></a><a class="link" href="#_produces_24">2.25.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route5"><a class="anchor" href="#_route5"></a><a class="link" href="#_route5">2.26. POST /v2/loop/updateOperationalPolicies/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_20"><a class="anchor" href="#_parameters_20"></a><a class="link" href="#_parameters_20">2.26.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_26"><a class="anchor" href="#_responses_26"></a><a class="link" href="#_responses_26">2.26.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_6"><a class="anchor" href="#_consumes_6"></a><a class="link" href="#_consumes_6">2.26.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_25"><a class="anchor" href="#_produces_25"></a><a class="link" href="#_produces_25">2.26.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route3"><a class="anchor" href="#_route3"></a><a class="link" href="#_route3">2.27. GET /v2/loop/{loopName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_21"><a class="anchor" href="#_parameters_21"></a><a class="link" href="#_parameters_21">2.27.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_27"><a class="anchor" href="#_responses_27"></a><a class="link" href="#_responses_27">2.27.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_26"><a class="anchor" href="#_produces_26"></a><a class="link" href="#_produces_26">2.27.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route29"><a class="anchor" href="#_route29"></a><a class="link" href="#_route29">2.28. POST /v2/policyToscaModels</a></h3> +<div class="sect3"> +<h4 id="_parameters_22"><a class="anchor" href="#_parameters_22"></a><a class="link" href="#_parameters_22">2.28.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_28"><a class="anchor" href="#_responses_28"></a><a class="link" href="#_responses_28">2.28.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_7"><a class="anchor" href="#_consumes_7"></a><a class="link" href="#_consumes_7">2.28.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>plain/text</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_27"><a class="anchor" href="#_produces_27"></a><a class="link" href="#_produces_27">2.28.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route26"><a class="anchor" href="#_route26"></a><a class="link" href="#_route26">2.29. GET /v2/policyToscaModels</a></h3> +<div class="sect3"> +<h4 id="_responses_29"><a class="anchor" href="#_responses_29"></a><a class="link" href="#_responses_29">2.29.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_28"><a class="anchor" href="#_produces_28"></a><a class="link" href="#_produces_28">2.29.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route28"><a class="anchor" href="#_route28"></a><a class="link" href="#_route28">2.30. GET /v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}</a></h3> +<div class="sect3"> +<h4 id="_parameters_23"><a class="anchor" href="#_parameters_23"></a><a class="link" href="#_parameters_23">2.30.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_30"><a class="anchor" href="#_responses_30"></a><a class="link" href="#_responses_30">2.30.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_29"><a class="anchor" href="#_produces_29"></a><a class="link" href="#_produces_29">2.30.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route27"><a class="anchor" href="#_route27"></a><a class="link" href="#_route27">2.31. GET /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a></h3> +<div class="sect3"> +<h4 id="_parameters_24"><a class="anchor" href="#_parameters_24"></a><a class="link" href="#_parameters_24">2.31.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_31"><a class="anchor" href="#_responses_31"></a><a class="link" href="#_responses_31">2.31.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_30"><a class="anchor" href="#_produces_30"></a><a class="link" href="#_produces_30">2.31.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route30"><a class="anchor" href="#_route30"></a><a class="link" href="#_route30">2.32. PUT /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a></h3> +<div class="sect3"> +<h4 id="_parameters_25"><a class="anchor" href="#_parameters_25"></a><a class="link" href="#_parameters_25">2.32.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_32"><a class="anchor" href="#_responses_32"></a><a class="link" href="#_responses_32">2.32.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_consumes_8"><a class="anchor" href="#_consumes_8"></a><a class="link" href="#_consumes_8">2.32.3. Consumes</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>plain/text</code></p> +</li> +</ul> +</div> +</div> +<div class="sect3"> +<h4 id="_produces_31"><a class="anchor" href="#_produces_31"></a><a class="link" href="#_produces_31">2.32.4. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route31"><a class="anchor" href="#_route31"></a><a class="link" href="#_route31">2.33. GET /v2/templates</a></h3> +<div class="sect3"> +<h4 id="_responses_33"><a class="anchor" href="#_responses_33"></a><a class="link" href="#_responses_33">2.33.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_32"><a class="anchor" href="#_produces_32"></a><a class="link" href="#_produces_32">2.33.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route33"><a class="anchor" href="#_route33"></a><a class="link" href="#_route33">2.34. GET /v2/templates/names</a></h3> +<div class="sect3"> +<h4 id="_responses_34"><a class="anchor" href="#_responses_34"></a><a class="link" href="#_responses_34">2.34.1. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< string > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_33"><a class="anchor" href="#_produces_33"></a><a class="link" href="#_produces_33">2.34.2. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_route32"><a class="anchor" href="#_route32"></a><a class="link" href="#_route32">2.35. GET /v2/templates/{templateName}</a></h3> +<div class="sect3"> +<h4 id="_parameters_26"><a class="anchor" href="#_parameters_26"></a><a class="link" href="#_parameters_26">2.35.1. Parameters</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 22.2222%;"> +<col style="width: 33.3333%;"> +<col style="width: 44.4445%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Type</th> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>templateName</strong><br> +<em>required</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_responses_35"><a class="anchor" href="#_responses_35"></a><a class="link" href="#_responses_35">2.35.2. Responses</a></h4> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 10%;"> +<col style="width: 70%;"> +<col style="width: 20%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">HTTP Code</th> +<th class="tableblock halign-left valign-middle">Description</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect3"> +<h4 id="_produces_34"><a class="anchor" href="#_produces_34"></a><a class="link" href="#_produces_34">2.35.3. Produces</a></h4> +<div class="ulist"> +<ul> +<li> +<p><code>application/json</code></p> +</li> +</ul> +</div> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_definitions"><a class="anchor" href="#_definitions"></a><a class="link" href="#_definitions">3. Definitions</a></h2> +<div class="sectionbody"> +<div class="sect2"> +<h3 id="_clampinformation"><a class="anchor" href="#_clampinformation"></a><a class="link" href="#_clampinformation">3.1. ClampInformation</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>allPermissions</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< string > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>cldsVersion</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>userName</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_cldshealthcheck"><a class="anchor" href="#_cldshealthcheck"></a><a class="link" href="#_cldshealthcheck">3.2. CldsHealthCheck</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>healthCheckComponent</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>healthCheckStatus</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_dictionary"><a class="anchor" href="#_dictionary"></a><a class="link" href="#_dictionary">3.3. Dictionary</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dictionaryElements</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_dictionaryelement">DictionaryElement</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>secondLevelDictionary</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>subDictionaryType</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_dictionaryelement"><a class="anchor" href="#_dictionaryelement"></a><a class="link" href="#_dictionaryelement">3.4. DictionaryElement</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>subDictionary</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>type</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByDictionaries</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_dictionary">Dictionary</a> > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_externalcomponent"><a class="anchor" href="#_externalcomponent"></a><a class="link" href="#_externalcomponent">3.5. ExternalComponent</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>componentName</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>state</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_externalcomponentstate">ExternalComponentState</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_externalcomponentstate"><a class="anchor" href="#_externalcomponentstate"></a><a class="link" href="#_externalcomponentstate">3.6. ExternalComponentState</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>level</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>stateName</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_jsonarray"><a class="anchor" href="#_jsonarray"></a><a class="link" href="#_jsonarray">3.7. JsonArray</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_jsonnull"><a class="anchor" href="#_jsonnull"></a><a class="link" href="#_jsonnull">3.8. JsonNull</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_jsonobject"><a class="anchor" href="#_jsonobject"></a><a class="link" href="#_jsonobject">3.9. JsonObject</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_jsonprimitive"><a class="anchor" href="#_jsonprimitive"></a><a class="link" href="#_jsonprimitive">3.10. JsonPrimitive</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>boolean</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>number</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>string</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_loop"><a class="anchor" href="#_loop"></a><a class="link" href="#_loop">3.11. Loop</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>components</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< string, <a href="#_externalcomponent">ExternalComponent</a> > map</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentId</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentStatusUrl</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>globalPropertiesJson</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>lastComputedState</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopLogs</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_looplog">LoopLog</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopTemplate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>microServicePolicies</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_microservicepolicy">MicroServicePolicy</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>modelService</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_service">Service</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>operationalPolicies</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_operationalpolicy">OperationalPolicy</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_loopelementmodel"><a class="anchor" href="#_loopelementmodel"></a><a class="link" href="#_loopelementmodel">3.12. LoopElementModel</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>blueprint</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementType</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModels</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_policymodel">PolicyModel</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByLoopTemplates</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_looptemplateloopelementmodel">LoopTemplateLoopElementModel</a> > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_looplog"><a class="anchor" href="#_looplog"></a><a class="link" href="#_looplog">3.13. LoopLog</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>id</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logComponent</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logInstant</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logType</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (INFO, WARNING, ERROR)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loop</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>message</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_looptemplate"><a class="anchor" href="#_looptemplate"></a><a class="link" href="#_looptemplate">3.14. LoopTemplate</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>allowedLoopType</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (OPEN, CLOSED, HYBRID)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>blueprint</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModelsUsed</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_looptemplateloopelementmodel">LoopTemplateLoopElementModel</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>maximumInstancesAllowed</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>modelService</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_service">Service</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniqueBlueprint</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_looptemplateloopelementmodel"><a class="anchor" href="#_looptemplateloopelementmodel"></a><a class="link" href="#_looptemplateloopelementmodel">3.15. LoopTemplateLoopElementModel</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>flowOrder</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopTemplate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_microservicepolicy"><a class="anchor" href="#_microservicepolicy"></a><a class="link" href="#_microservicepolicy">3.16. MicroServicePolicy</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>configurationsJson</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>context</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentId</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentStatusUrl</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>deviceTypeScope</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonRepresentation</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpGroup</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpSubgroup</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModel</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shared</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByLoops</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_loop">Loop</a> > array</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_number"><a class="anchor" href="#_number"></a><a class="link" href="#_number">3.17. Number</a></h3> +<div class="paragraph"> +<p><em>Type</em> : object</p> +</div> +</div> +<div class="sect2"> +<h3 id="_operationalpolicy"><a class="anchor" href="#_operationalpolicy"></a><a class="link" href="#_operationalpolicy">3.18. OperationalPolicy</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>configurationsJson</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonRepresentation</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loop</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpGroup</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpSubgroup</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModel</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_policymodel"><a class="anchor" href="#_policymodel"></a><a class="link" href="#_policymodel">3.19. PolicyModel</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyAcronym</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelTosca</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyPdpGroup</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByElementModels</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">< <a href="#_loopelementmodel">LoopElementModel</a> > array</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>version</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +<div class="sect2"> +<h3 id="_service"><a class="anchor" href="#_service"></a><a class="link" href="#_service">3.20. Service</a></h3> +<table class="tableblock frame-all grid-all stretch"> +<colgroup> +<col style="width: 42.8571%;"> +<col style="width: 57.1429%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-middle">Name</th> +<th class="tableblock halign-left valign-middle">Schema</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>resourceDetails</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>serviceDetails</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>serviceUuid</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>version</strong><br> +<em>optional</em></p></td> +<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td> +</tr> +</tbody> +</table> +</div> +</div> +</div> +</div> +<div id="footer"> +<div id="footer-text"> +Last updated 2020-08-13 14:06:50 CEST +</div> +</div> +</body> +</html>
\ No newline at end of file diff --git a/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson b/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson new file mode 100644 index 000000000..3fa78e040 --- /dev/null +++ b/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson @@ -0,0 +1,23 @@ +/*- + * ============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============================================ + * =================================================================== + */ + +class=org.onap.clamp.configuration.ClampGsonDataFormat
\ No newline at end of file diff --git a/src/main/resources/application-noaaf.properties b/src/main/resources/application-noaaf.properties new file mode 100644 index 000000000..6b28cf7ef --- /dev/null +++ b/src/main/resources/application-noaaf.properties @@ -0,0 +1,186 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-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============================================ +# =================================================================== +# +### + +### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time). +### (See below for the parameter 'server.http.port' if you want to have both enabled) +### To have only HTTP, keep the lines server.ssl.* commented +### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location +### server.port=8080 +### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port') +#server.ssl.key-store=file:/tmp/mykey.jks +#server.ssl.key-store-password=pass +#server.ssl.key-password=pass + +### In order to be user friendly when HTTPS is enabled, +### you can add another HTTP port that will be automatically redirected to HTTPS +### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...) +#server.http-to-https-redirection.port=8090 + +### HTTP Example: +###-------------- +### server.port=8080 + +### HTTPS Example: +### -------------- +### server.port=8443 +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass +server.port=8443 +## Config part for Server certificates +# Can be a classpath parameter instead of file:/ +server.ssl.key-store=classpath:/clds/aaf/org.onap.clamp.p12 +server.ssl.key-store-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-store-type=PKCS12 +server.ssl.key-alias=clamp@clamp.onap.org + +## Config part for Client certificates +server.ssl.client-auth=want +server.ssl.trust-store=classpath:/clds/aaf/truststoreONAPall.jks +server.ssl.trust-store-password=enc:iDnPBBLq_EMidXlMa1FEuBR8TZzYxrCg66vq_XfLHdJ + +# The key file used to decode the key store and trust store password +# If not defined, the key store and trust store password will not be decrypted +clamp.config.keyFile=classpath:/clds/aaf/org.onap.clamp.keyfile + +#server.http-to-https-redirection.port=8080 + +server.servlet.context-path=/ +#Modified engine-rest applicationpath +spring.profiles.active=clamp-default,clamp-default-user,clamp-sdc-controller,clamp-ssl-config,clamp-policy-controller,default-dictionary-elements +spring.http.converters.preferred-json-mapper=gson + +#The max number of active threads in this pool +server.tomcat.max-threads=200 +#The minimum number of threads always kept alive +server.tomcat.min-Spare-Threads=25 +#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads +server.tomcat.max-idle-time=60000 + +#Servlet context parameters +server.context_parameters.p-name=value #context parameter with p-name as key and value as value. + +camel.springboot.tracing=true +camel.springboot.consumer-template-cache-size=1000 +camel.springboot.producer-template-cache-size=1000 +camel.springboot.jmx-enabled=true +camel.defaultthreadpool.poolsize=10 +camel.defaultthreadpool.maxpoolsize=20 +camel.defaultthreadpool.maxqueuesize=1000 +camel.defaultthreadpool.keepaliveTime=60 +camel.defaultthreadpool.rejectpolicy=CallerRuns +#camel.springboot.xmlRoutes = false +camel.springboot.xmlRoutes=classpath:/clds/camel/routes/*.xml +camel.springboot.xmlRests=classpath:/clds/camel/rest/*.xml +#camel.springboot.typeConversion = false + +#clds datasource connection details +spring.datasource.driverClassName=org.mariadb.jdbc.Driver +spring.datasource.url=jdbc:mariadb:sequential://localhost:3306/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3 +spring.datasource.username=clds +spring.datasource.password=sidnnd83K +spring.datasource.validationQuery=SELECT 1 +spring.datasource.validationQueryTimeout=20000 +spring.datasource.validationInterval=30000 +spring.datasource.testWhileIdle = true +spring.datasource.minIdle = 0 +spring.datasource.initialSize=0 +# Automatically test whether a connection provided is good or not +spring.datasource.testOnBorrow=true +spring.datasource.ignoreExceptionOnPreLoad=true +# control the sql db initialization (from schema.sql and data.sql) +spring.datasource..initialize=false + +spring.jpa.properties.javax.persistence.schema-generation.database.action=none +s#pring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +# disable Hibernate DDL generation because the schema will be generated from a sql script +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.ddl-auto=validate +spring.jpa.properties.hibernate.hbm2ddl.delimiter=; +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.use-new-id-generator-mappings=true + +# Whether to enable logging of SQL statements. +#spring.jpa.show-sql=true + +#Async Executor default Parameters +async.core.pool.size=10 +async.max.pool.size=20 +async.queue.capacity=500 + +#For EELF logback file +#clamp.config.logback.path= +clamp.config.logback.filename=logback-default.xml +#The log folder that will be used in logback.xml file +clamp.config.log.path=/var/log/onap/clamp +clamp.config.files.systemProperties=classpath:/system.properties +clamp.config.files.cldsUsers=classpath:/clds/clds-users.json +clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json +clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json + +# +# Configuration Settings for Policy Engine Components +clamp.config.policy.api.url=http4://localhost:8085 +clamp.config.policy.api.userName=healthcheck +clamp.config.policy.api.password=zb!XztG34 +clamp.config.policy.pap.url=http4://localhost:8085 +clamp.config.policy.pap.userName=healthcheck +clamp.config.policy.pap.password=zb!XztG34 + +# +# Sdc service properties +clamp.config.sdc.csarFolder = /tmp/sdc-controllers + +#DCAE Inventory Url Properties +clamp.config.dcae.inventory.url=http4://localhost:8085 +clamp.config.dcae.intentory.retry.interval=10000 +clamp.config.dcae.intentory.retry.limit=5 + +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://localhost:8085 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + +#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! +clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl +clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage +clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event +clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf +clamp.config.security.permission.type.template=org.onap.clamp.clds.template +clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca +#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties +clamp.config.security.permission.instance=dev +clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal + +## Tosca converter +clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json +clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml +clamp.config.tosca.converter.dictionary.support.enabled=true + +# Configuration settings for CDS +clamp.config.cds.url=http4://cds-blueprints-processor-http:8080 +clamp.config.cds.userName=ccsdkapps +clamp.config.cds.password=ccsdkapps
\ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 000000000..1b5a26d0a --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,200 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-2019 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Modifications copyright (c) 2019 Nokia +# ================================================================================\ +# 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============================================ +# =================================================================== +# +### + +### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time). +### (See below for the parameter 'server.http.port' if you want to have both enabled) +### To have only HTTP, keep the lines server.ssl.* commented +### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location +### server.port=8080 +### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port') +#server.ssl.key-store=file:/tmp/mykey.jks +#server.ssl.key-store-password=pass +#server.ssl.key-password=pass + +### In order to be user friendly when HTTPS is enabled, +### you can add another HTTP port that will be automatically redirected to HTTPS +### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...) +#server.http-to-https-redirection.port=8090 + +### HTTP Example: +###-------------- +### server.port=8080 + +### HTTPS Example: +### -------------- +### server.port=8443 +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass + +### HTTP (Redirected to HTTPS) and HTTPS Example: +### -------------------------------------------- +server.port=8443 +## Config part for Server certificates +# Can be a classpath parameter instead of file:/ +server.ssl.key-store=classpath:/clds/aaf/org.onap.clamp.p12 +server.ssl.key-store-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-store-type=PKCS12 +server.ssl.key-alias=clamp@clamp.onap.org + +# The key file used to decode the key store and trust store password +# If not defined, the key store and trust store password will not be decrypted +clamp.config.keyFile=classpath:/clds/aaf/org.onap.clamp.keyfile +clamp.config.caCerts=classpath:/clds/aaf/ssl/ca-certs.pem + +## Config part for Client certificates +server.ssl.client-auth=want +server.ssl.trust-store=classpath:/clds/aaf/truststoreONAPall.jks +server.ssl.trust-store-password=enc:iDnPBBLq_EMidXlMa1FEuBR8TZzYxrCg66vq_XfLHdJ + +#server.http-to-https-redirection.port=8080 + +server.servlet.context-path=/ +#Modified engine-rest applicationpath +spring.profiles.active=clamp-default,clamp-aaf-authentication,clamp-sdc-controller,clamp-ssl-config,clamp-policy-controller,default-dictionary-elements +spring.http.converters.preferred-json-mapper=gson + +#The max number of active threads in this pool +server.tomcat.max-threads=200 +#The minimum number of threads always kept alive +server.tomcat.min-Spare-Threads=25 +#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads +server.tomcat.max-idle-time=60000 + +#Servlet context parameters +server.context_parameters.p-name=value #context parameter with p-name as key and value as value. +camel.springboot.tracing=true +camel.springboot.consumer-template-cache-size=1000 +camel.springboot.producer-template-cache-size=1000 +camel.springboot.jmx-enabled=true +camel.defaultthreadpool.poolsize=10 +camel.defaultthreadpool.maxpoolsize=20 +camel.defaultthreadpool.maxqueuesize=1000 +camel.defaultthreadpool.keepaliveTime=60 +camel.defaultthreadpool.rejectpolicy=CallerRuns +#camel.springboot.xmlRoutes = false +camel.springboot.xmlRoutes=classpath:/clds/camel/routes/*.xml +camel.springboot.xmlRests=classpath:/clds/camel/rest/*.xml +#camel.springboot.typeConversion = false + +#clds datasource connection details +spring.datasource.driverClassName=org.mariadb.jdbc.Driver +spring.datasource.url=jdbc:mariadb:sequential://localhost:3306/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3 +spring.datasource.username=clds +spring.datasource.password=sidnnd83K +spring.datasource.validationQuery=SELECT 1 +spring.datasource.validationQueryTimeout=20000 +spring.datasource.validationInterval=30000 +spring.datasource.testWhileIdle = true +spring.datasource.minIdle = 0 +spring.datasource.initialSize=0 +# Automatically test whether a connection provided is good or not +spring.datasource.testOnBorrow=true +spring.datasource.ignoreExceptionOnPreLoad=true + +spring.jpa.properties.javax.persistence.schema-generation.database.action=none +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +# disable Hibernate DDL generation because the schema will be generated from a sql script +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.ddl-auto=validate +spring.jpa.properties.hibernate.hbm2ddl.delimiter=; +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.use-new-id-generator-mappings=true + +# Whether to enable logging of SQL statements. +#spring.jpa.show-sql=true + +#Async Executor default Parameters +async.core.pool.size=10 +async.max.pool.size=20 +async.queue.capacity=500 + +#For EELF logback file +#clamp.config.logback.path= +clamp.config.logback.filename=logback-default.xml +#The log folder that will be used in logback.xml file +clamp.config.log.path=/var/log/onap/clamp +clamp.config.files.systemProperties=classpath:/system.properties +clamp.config.files.cldsUsers=classpath:/clds/clds-users.json +clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json +clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json + +# +# Configuration Settings for Policy Engine Components +clamp.config.policy.api.url=http4://policy.api.simpledemo.onap.org:6969 +clamp.config.policy.api.userName=healthcheck +clamp.config.policy.api.password=zb!XztG34 +clamp.config.policy.pap.url=http4://policy.api.simpledemo.onap.org:6969 +clamp.config.policy.pap.userName=healthcheck +clamp.config.policy.pap.password=zb!XztG34 + +# +# Sdc service properties +clamp.config.sdc.csarFolder=/tmp/sdc-controllers + +#DCAE Inventory Url Properties +clamp.config.dcae.inventory.url=http4://dcae.api.simpledemo.onap.org:8080 +clamp.config.dcae.intentory.retry.interval=10000 +clamp.config.dcae.intentory.retry.limit=5 + +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://dcae.api.simpledemo.onap.org:8188 +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + +#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! +clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl +clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage +clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event +clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf +clamp.config.security.permission.type.template=org.onap.clamp.clds.template +clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca +#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties +clamp.config.security.permission.instance=dev +clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal + +#AAF related parameters +clamp.config.cadi.cadiLoglevel=DEBUG +clamp.config.cadi.cadiLatitude=10 +clamp.config.cadi.cadiLongitude=10 +clamp.config.cadi.aafLocateUrl=https://aaf-locate:30251 +clamp.config.cadi.oauthTokenUrl= https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.token:2.1/token +clamp.config.cadi.oauthIntrospectUrll=https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.introspect:2.1/introspect +clamp.config.cadi.aafEnv=DEV +clamp.config.cadi.aafUrl=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.service:2.1 +clamp.config.cadi.cadiX509Issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US + +## Tosca converter +clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json +clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml +clamp.config.tosca.converter.dictionary.support.enabled=true + +# Configuration settings for CDS +clamp.config.cds.url=http4://cds-blueprints-processor-http:8080 +clamp.config.cds.userName=ccsdkapps +clamp.config.cds.password=ccsdkapps
\ No newline at end of file diff --git a/src/main/resources/asciidoc/swagger.adoc b/src/main/resources/asciidoc/swagger.adoc new file mode 100644 index 000000000..6896747fd --- /dev/null +++ b/src/main/resources/asciidoc/swagger.adoc @@ -0,0 +1,4 @@ +include::{generated}/overview.adoc[] +include::{generated}/paths.adoc[] +include::{generated}/security.adoc[] +include::{generated}/definitions.adoc[]
\ No newline at end of file diff --git a/src/main/resources/boot-message.txt b/src/main/resources/boot-message.txt new file mode 100644 index 000000000..ef1478b93 --- /dev/null +++ b/src/main/resources/boot-message.txt @@ -0,0 +1,12 @@ + + ____ ____ ____ ____ _________ ____ ____ ____ ____ ____ ____ +||O |||N |||A |||P ||| |||G |||u |||i |||l |||i |||n || +||__|||__|||__|||__|||_______|||__|||__|||__|||__|||__|||__|| +|/__\|/__\|/__\|/__\|/_______\|/__\|/__\|/__\|/__\|/__\|/__\| + _________ ____ ____ ____ ____ ____ + || |||C |||L |||A |||M |||P || + ||_______|||__|||__|||__|||__|||__|| + |/_______\|/__\|/__\|/__\|/__\|/__\| + + + :: Starting ::
\ No newline at end of file diff --git a/src/main/resources/clds-version.properties b/src/main/resources/clds-version.properties new file mode 100644 index 000000000..a0dbcdead --- /dev/null +++ b/src/main/resources/clds-version.properties @@ -0,0 +1,24 @@ +### +# ============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============================================ +# =================================================================== +# +### + +clds.version=${project.version}
\ No newline at end of file diff --git a/src/main/resources/clds/aaf/org.onap.clamp.keyfile b/src/main/resources/clds/aaf/org.onap.clamp.keyfile new file mode 100644 index 000000000..c2521fc81 --- /dev/null +++ b/src/main/resources/clds/aaf/org.onap.clamp.keyfile @@ -0,0 +1,27 @@ +kzJMxgphAoBxJz1_vYjxx-V87fahDQdYUqBIyWhZp8ojXdNpmB-96T9CvgJScJynbLcqw2Cj2CYx +wd97vFOYhlyz5zK3tSyIuydOkVGJsJ1S4PviTtjhiJvNourJNDHgtas1Y1y2fQ5_8aVxj-s4W72N +MNYhkeTinaQx_d_5hkBPABJlgCxKLnmxHo2jAJktnZYa5t5h48m7KiUx_RVEkQVtEvux-7vgXaC4 +ymTXj6zI9XoMTVxM0OAl4y7kBiUoOUaxS4tVKV34RJYNNqBjiUTQa_ag-KeUacRABk1ozfwzpvE5 +Sjz8WCy0L-LtCQnapkhKLt04ndCZtw8LDJ-Zz0ZgR2PVIPpTgs9VnVuOi5jf4LzTrtUatvOWkKB9 +drXKzp6cNXnZ0jkD3vV1BzqzhynKnZR2o_ilZv5CTTdpGUt906N_DwZuX6LfcV_7yvjX42bTfeIR +ycPtodFPXlqqn9VUyh5nOauJlnOHAQmSDzjMEgjy17nQX3Ad7s4BfvujzUl-d0MqB_HCKbaW32UT +xcY-0JfI1Y-2IdYfIkUdhVmxop6sSg0jAobWzgCRoRQkP3a2iIlKdfMyskshoWKIDVtlr-3fkDEb +x_b_o1rRoUfzUzxEdphaUAq80Sc0i77ZLT3KF9vJOhyU_pBnApYFxVk7Hkk3VRxJKS7jyL4H7k1x +2m5-2G8fB9XbYZT82xmAquNx4oBdpwj3_ncGF9YRF94K6NZgqemT5iWhpXMoelSU1blASgT3qlTm +B6YgbD5owExNHwRVd8KeRsYrOnBWUiktsIhXFhNZmDUNWMFGQ2KxEcOt1tJwsQDehJFgY_l1JQ0d +643wJ7rTJkGkYX309cydRQUX4Z0ckSQS9LhMd9stxF5XOHlvHdbW0pXNS7SaLbzKCVldUgncvI6z +KWkwrWbftrZK2RT1UZKNngQDMGOk9OhbHAs7YzhFNFARZoRNobIv5tZVDomy-YgJb9-mD1UTkRBL +WXOyoryDlgKrgFsgHclGDI1UFO5N-JfebPKxbP505f4924hxF2r8bspvVW8ZtHQo_SJmhauOX8n_ +eN_LK43LB9k53WAHZ_utvs0s6wGf7I73oj_N7DIFaHTDSm_MhDsFDLVG_wUzCpZ5FP2uL3nnqMkF +Ob-l1fywfmfOmrz1BY6g4sRPPeWXuclYTnRnDRu5VQyc7_aBEVkyt3zw0JEex0vJNFUJl3pYjS55 +GplAB6p7VbS9ceZEtc5Z3qFIVHEzKWZxT190E23t_LlMuEoQ1zaqdHynNaMs61-q_A2aHRiTqlRm +7FahVB3RX4AVLl23mu4u3A9ZDXc40nzjs9mwOVsuKlPvQ2rteDUG1njr2R1_V_MyQuoJjdfbIkPG +4eF0QzlSMdbkeprdQxSfV5YT-yPpkBxSsCMMM43sKm4Hy7_CUdvp4Iayrp3vtK3oYMuCGi6qTadz +KzxfTf8meKan3eMZW4RLByyniH5nQnX_KGfBly05AmFyVH_j0fyOg-48kDhtEKeqmDnP4C01jOID +Ip_AKaB6e0GwsHzVTLZOklHwu_qzsaTzchBOG_dJJju7bxY7qv78Pa92wZIP311gSCVbc-gxxbsR +qI555twmYEoasFm4xz10OYDOkvM1E1Rtxu3ymRLZpe6AoyFBVzEW7Dncdw7O98dKcgrp8ZlQ_8Wg +5zZH0Cic7xnIZ0bNZyQXw56CSUiXVWuwVY3e0djXP3F-FO5gP8VTxbpW4C0t6McXAOlvSEfFKxN7 +u6OBeOKwjrtHaJk2ghF8MUcpDXanhbAgHez9larGlscCkgvoRLNaRH9GIdSVgY3HtNhJRaJIq01S +OGeBjC5J4o-nTrqRFkwyDAYcPL373eYX1dBFFVHR-4q50H9m_zMxZHXETafxzV4DT3Qi8Sxh3uaS +ZX7mRaNaOE0uC1n87_IZ9WhrwIQaZng2lnd9yZ-4rx8fB8WA8KQzifzvHAcMb_HV10JWGaz5A2Rm +EXDsfexQC6CqYg5rdzzlNWDPNlHy5ubyz7fRXZ99uIwBY9aJcvCXCiEXJkC6utj3NcXQrJmk
\ No newline at end of file diff --git a/src/main/resources/clds/aaf/org.onap.clamp.p12 b/src/main/resources/clds/aaf/org.onap.clamp.p12 Binary files differnew file mode 100644 index 000000000..268aa1a3c --- /dev/null +++ b/src/main/resources/clds/aaf/org.onap.clamp.p12 diff --git a/src/main/resources/clds/aaf/ssl/ca-certs.pem b/src/main/resources/clds/aaf/ssl/ca-certs.pem new file mode 100644 index 000000000..70bb844b7 --- /dev/null +++ b/src/main/resources/clds/aaf/ssl/ca-certs.pem @@ -0,0 +1,32 @@ +Bag Attributes + friendlyName: CN=intermediateCA_9,OU=OSAAF,O=ONAP,C=US +subject=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9 + +issuer=OU = OSAAF, O = ONAP, C = US + +-----BEGIN CERTIFICATE----- +MIIEdTCCAl2gAwIBAgIBBzANBgkqhkiG9w0BAQsFADAsMQ4wDAYDVQQLDAVPU0FB +RjENMAsGA1UECgwET05BUDELMAkGA1UEBhMCVVMwHhcNMTgwODE3MTg1MTM3WhcN +MjMwODE3MTg1MTM3WjBHMQswCQYDVQQGEwJVUzENMAsGA1UECgwET05BUDEOMAwG +A1UECwwFT1NBQUYxGTAXBgNVBAMMEGludGVybWVkaWF0ZUNBXzkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv0HHUkba3uNtNI3jPKimUcd6RNwmhSCJL +neMWpnjqp5/A+HCKyNsEaT4y177hNLmCm/aMm1u2JIfikc+8wEqLCSBBPz+P0h+d +o+sZ7U+4oeQizdYYpEdzHJ2SieHHa8vtu80rU3nO2NEIkuYC20HcKSEtl8fFKsk3 +nqlhY+tGfYJPTXcDOQAO40BTcgat3C3uIJHkWJJ4RivunE4LEuRv9QyKgAw7rkJV +v+f7guqpZlXy6dzAkuU7XULWcgo55MkZlssoiErMvEZJad5aWKvRY3g7qUjaQ6wO +15wOAUoRBW96eeZZbytgn8kybcBy++Ue49gPtgm1MF/KlAsp0MD5AgMBAAGjgYYw +gYMwHQYDVR0OBBYEFIH3mVsQuciM3vNSXupOaaBDPqzdMB8GA1UdIwQYMBaAFFNV +M/JL69BRscF4msEoMXvv6u1JMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B +AQsFAAOCAgEADxNymiCNr2e37iLReoaxKmZvwox0cTiNAaj7iafRzmwIoY3VXO8Q +ix5IYcp4FaQ7fV1jyp/AmaSnyHf6Osl0sx8PxsQkO7ALttxKUrjfbvNSVUA2C/vl +u5m7UVJLIUtFDZBWanzUSmkTsYLHpiANFQKd2c/cU1qXcyzgJVFEFVyyHNkF7Is+ ++pjG9M1hwQHOoTnEuU013P7X1mHek+RXEfhJWwe7UsZnBKZaZKbQZu7hEtqKWYp/ +QsHgnjoLYXsh0WD5rz/mBxdTdDLGpFqWDzDqb8rsYnqBzoowvsasV8X8OSkov0Ht +8Yka0ckFH9yf8j1Cwmbl6ttuonOhky3N/gwLEozuhy7TPcZGVyzevF70kXy7g1CX +kpFGJyEHXoprlNi8FR4I+NFzbDe6a2cFow1JN19AJ9Z5Rk5m7M0mQPaQ4RcikjB3 +aoLsASCJTm1OpOFHfxEKiBW4Lsp3Uc5/Rb9ZNbfLrwqWZRM7buW1e3ekLqntgbky +uKKISHqVJuw/vXHl1jNibEo9+JuQ88VNuAcm7WpGUogeCa2iAlPTckPZei+MwZ8w +tpvxTyYlZEC8DWzY1VC29+W2N5cvh01e2E3Ql08W1zL63dqrgdEZ3VWjzooYi4ep +BmMXTvouW+Flyvcw/0oTcfN0biDIt0mCkZ5CQVjfGL9DTOYteR5hw+k= +-----END CERTIFICATE----- diff --git a/src/main/resources/clds/aaf/ssl/clamp.key b/src/main/resources/clds/aaf/ssl/clamp.key new file mode 100644 index 000000000..bcbb9f17e --- /dev/null +++ b/src/main/resources/clds/aaf/ssl/clamp.key @@ -0,0 +1,32 @@ +Bag Attributes + friendlyName: clamp@clamp.onap.org + localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39 +Key Attributes: <No Attributes> +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCTB30nMh0hczIk +vWJo7Omg7cAHhz50NBhLB7u+60oXRGCya4SqssqqxNnNqNQQP9MmflW2q/bZepWn +8Rk23X6CLmoIUlrj8BMPkUCRqzgvlaWPSNAK5QcOp6GUvXTuX4EsaWxJhbs9Ujz2 ++qi137iNOqfAx1sUygah1kjALrqHkXDqJGvIfxU5ES0akBi/lB7A3WpE52KTioSF +JS5Kbnpj1ogffGNKyAiNqU61LcF1FjWmINat2z3ZMk/3Xm+HCDg/GLPnbh4E1KoE +10O22AMys6YGEyPvgRfrTF13DsDX52PmmUHbkSB6kwS/CeV5Uu++8b6T2IWpPyZ2 ++5ptmL+tAgMBAAECggEBAIUplzRUswWEq7mSvPqC9+YE7pLi7rGYLRhnXKdBuszv +5RQzROjFHcEkoI8fhVFiPP70FPVpMh0uZTTBrDCA0v9cwjPfQuqGmPzUdUJ5bF3M +jzICpEn5vDaNpE5ueOUcIoXyxVyhfj+/p++YfgybHy7qHN0AsYFWqEMTLLjCmbYF +pZozbAcGQoAR8PSfwuvgusuEezrhYertHsdFwlfZhDtJvnm/4YKRUVEBzuaaA7B9 +sUhnQFS8ScqiUbkAGdjfY9wOYRHnQgjtqiP8poIzLkqCNSoVctgh5Pdv4jp4HO90 +J5QC+f7m7rOoWUw8EYbRo/4C4Mckh0GQQ+oP4xzrtZECgYEA3DYALFgOEY+0RR1K +61HAKqdNy1YbeuidpCBEJEwmIbzdgO1DcJdNznbfdRlmS7VB9orwRfNbf7Hxm2w/ +/xn9USENXWx7fvDoISqSDegvEsBSq5hSEMVl3f7CfQZrYl1f6gxfe7L/jtmbn0eQ +avsr9RaUCWP794DEXKuA9pC8hVsCgYEAquy5I4hO4jNBQ6v5+omjsEgk4513/RNs +f47Md8bsDHKJMbCMKCdqM1D3J1xbgV3DgSv0yNlKdU2wenWdgQAyBtz18NBgno85 +YNanFhp1CymgLFHdLJHSOqAkzutSuCNnGTT6AKspOQvy+cuj7XsnbsxtYK3Cgw5h +Mom3RnUy9ZcCgYAnForHVEYDBgAYuI9g39z9dT8Q1dMA6SN6S6Ps0Xt/R5gF15e9 +941/FYiqr3yB+cWgrp7hu8XFD9/0F63waTuW2AgYSjZNnROHN5g/UbRxXqQOA3al +tXRUiHEbYjVTe4GX+ORF/8rvH19JUZmn87ekxII4fH/wOfIhBOxaV+yuuwKBgHtz +5Tizz/3y9TWSdkgtt6uwP+yipLKGn/v1wNrWM1G+PDdGg8TQyxTrasfkHjdu6LFY +dUHIJ85X4ZphbvRolrl8SKq5Zr+/RLsb7qy5SUZZt1Wrfysc25H6bvuA3ksfTuzW +5acr+Oc6KTGgkvMI229cebe1aONNtIhTDav3JGpbAoGAX5DQvNreqnP8qSAvUN2I +TAHXIzawR3f6vgGgVIdkHkiS2eKzs/fgP3VAK80TbrGSR8HvBcPEcR/icOn1u/e6 +tDp0j6mGt5aPKK9VQkBn94bW35T12FUbdB+L8FWWTUrfiVWJtEW8tEsKil5ac8U4 +Bn3vC5WUeKhW6v6kD4AigqE= +-----END PRIVATE KEY----- diff --git a/src/main/resources/clds/aaf/ssl/clamp.pem b/src/main/resources/clds/aaf/ssl/clamp.pem new file mode 100644 index 000000000..a01b587a5 --- /dev/null +++ b/src/main/resources/clds/aaf/ssl/clamp.pem @@ -0,0 +1,33 @@ +Bag Attributes + friendlyName: clamp@clamp.onap.org + localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39 +subject=CN = clamp, emailAddress = mark.d.manager@people.osaaf.com, OU = clamp@clamp.onap.org:DEV, OU = OSAAF, O = ONAP, C = US + +issuer=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9 + +-----BEGIN CERTIFICATE----- +MIIEWDCCA0CgAwIBAgIILw1zyDGqB5IwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UE +BhMCVVMxDTALBgNVBAoMBE9OQVAxDjAMBgNVBAsMBU9TQUFGMRkwFwYDVQQDDBBp +bnRlcm1lZGlhdGVDQV85MB4XDTIwMDIwNDEyMjM1MloXDTIxMDIwNDEyMjM1Mlow +gY8xDjAMBgNVBAMMBWNsYW1wMS4wLAYJKoZIhvcNAQkBFh9tYXJrLmQubWFuYWdl +ckBwZW9wbGUub3NhYWYuY29tMSEwHwYDVQQLDBhjbGFtcEBjbGFtcC5vbmFwLm9y +ZzpERVYxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJV +UzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJMHfScyHSFzMiS9Ymjs +6aDtwAeHPnQ0GEsHu77rShdEYLJrhKqyyqrE2c2o1BA/0yZ+Vbar9tl6lafxGTbd +foIuaghSWuPwEw+RQJGrOC+VpY9I0ArlBw6noZS9dO5fgSxpbEmFuz1SPPb6qLXf +uI06p8DHWxTKBqHWSMAuuoeRcOoka8h/FTkRLRqQGL+UHsDdakTnYpOKhIUlLkpu +emPWiB98Y0rICI2pTrUtwXUWNaYg1q3bPdkyT/deb4cIOD8Ys+duHgTUqgTXQ7bY +AzKzpgYTI++BF+tMXXcOwNfnY+aZQduRIHqTBL8J5XlS777xvpPYhak/Jnb7mm2Y +v60CAwEAAaOB/jCB+zAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF4DAgBgNVHSUB +Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwVAYDVR0jBE0wS4AUgfeZWxC5yIze +81Je6k5poEM+rN2hMKQuMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQ +MQswCQYDVQQGEwJVU4IBBzAdBgNVHQ4EFgQUzfIed+18wgFs7E6q0b6BbMICtfsw +RwYDVR0RBEAwPoIFY2xhbXCCCmNsYW1wLW9uYXCCHWNsYW1wLmFwaS5zaW1wbGVk +ZW1vLm9uYXAub3JnggpjbGFtcC5vbmFwMA0GCSqGSIb3DQEBCwUAA4IBAQBizhsW +XrJ9wQy3PrBxgh90sOF15tayXPRZSFYPoQb5LhRh3IY/PvXLaSHlkgPHlCLLx36S +0/DiVf86/83ABvyaq9gJIyg/m4ntNae23OKH1AkA1aN+JCKA8yhsAzDBcRF6Aj7E +VJ+vQlSzz5oh+efP1e/8DUMd1/WwbTXvRd0Iqv/fyZunbjb82qNMrsK1mQ2q+87A +0jx9u1EdeMihP6vWiuKzlwy4mKoNT573SPpvaOkjX3yDlmf2CTQZ9vdAvjmFmVsH +1wyrNZOIgW4VjluiZfAk3mOEskrZiP/7aUXnxmNnYTpgZMbhiouLbRrTc4lLEyhx +G7A61/KGTsLZlvxb +-----END CERTIFICATE----- diff --git a/src/main/resources/clds/aaf/truststoreONAPall.jks b/src/main/resources/clds/aaf/truststoreONAPall.jks Binary files differnew file mode 100644 index 000000000..ff844b109 --- /dev/null +++ b/src/main/resources/clds/aaf/truststoreONAPall.jks diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml new file mode 100644 index 000000000..505ea30d9 --- /dev/null +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -0,0 +1,1322 @@ +<rests xmlns="http://camel.apache.org/schema/spring"> + <rest> + <get uri="/v2/loop/getAllNames" outType="java.lang.String[]" + produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=getLoopNames()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET All Loop names FAILED: ${exception.stacktrace}" /> + + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET All Loop names FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/loop/{loopName}" outType="org.onap.clamp.loop.Loop" + produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Loop')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=getLoop(${header.loopName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Loop request failed for loop: ${header.loopName}, ${exception.stacktrace}" /> + + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Loop FAILED</simple> + </setBody> + </doCatch> + </doTry> + </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"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update the global properties')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <setHeader headerName="GlobalPropertiesJson"> + <simple>${body}</simple> + </setHeader> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=updateGlobalPropertiesJson(${header.loopName},${header.GlobalPropertiesJson})" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Global Properties UPDATED','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="UPDATE Global properties FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>UPDATE Global properties FAILED </simple> + </setBody> + </doCatch> + </doTry> + </route> + </post> + <post uri="/v2/loop/updateOperationalPolicies/{loopName}" + type="com.google.gson.JsonArray" consumes="application/json" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update operational policies')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <setHeader headerName="OperationalPoliciesArray"> + <simple>${body}</simple> + </setHeader> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=updateOperationalPolicies(${header.loopName},${header.OperationalPoliciesArray})" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Operational policies UPDATED','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="UPDATE Operational policies FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('UPDATE Operational policies request FAILED, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})" /> + + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>UPDATE Operational policies FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </post> + <post uri="/v2/loop/updateMicroservicePolicy/{loopName}" + type="org.onap.clamp.policy.microservice.MicroServicePolicy" + consumes="application/json" + outType="org.onap.clamp.policy.microservice.MicroServicePolicy" + produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update Microservice policies')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <setProperty propertyName="MicroServicePolicyObject"> + <simple>${body}</simple> + </setProperty> + + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=updateMicroservicePolicy(${header.loopName},${exchangeProperty[MicroServicePolicyObject]})" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Micro Service policies UPDATED','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="UPDATE MicroService policy FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('UPDATE MicroService policy request FAILED, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>UPDATE MicroService policy FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </post> + <put uri="/v2/loop/deploy/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="DCAE DEPLOY request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'DCAE DEPLOY request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DCAE DEPLOY request','INFO',${exchangeProperty[loopObject]})" /> + + <to uri="direct:deploy-loop" /> + + <log loggingLevel="INFO" + message="DEPLOY request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DEPLOY request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="DEPLOY request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DEPLOY request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>DEPLOY request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName|microServicePolicyName" /> + <doTry> + <log loggingLevel="INFO" + message="Refresh Micro Service Policy UI for loop: ${header.loopName} and ${header.microServicePolicyName}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REFRESH Micro Service Policy UI request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.cds.CdsDataInstaller?method=updateCdsServiceProperties(${exchangeProperty[loopObject].getModelService()})" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=refreshMicroServicePolicyJsonRepresentation(${exchangeProperty[loopObject]},${header.microServicePolicyName})" /> + <log loggingLevel="INFO" + message="REFRESH Micro Service policy request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REFRESH Micro Service policy request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="REFRESH json schema request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REFRESH Json schema request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>REFRESH json schema request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName|operationalPolicyName" /> + <doTry> + <log loggingLevel="INFO" + message="Refresh Operational Policy UI for loop: ${header.loopName} and ${header.operationalPolicyName}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REFRESH Operational Policy UI request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.cds.CdsDataInstaller?method=updateCdsServiceProperties(${exchangeProperty[loopObject].getModelService()})" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=refreshOperationalPolicyJsonRepresentation(${exchangeProperty[loopObject]},${header.operationalPolicyName})" /> + <log loggingLevel="INFO" + message="REFRESH operational policy request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REFRESH operational policy request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="REFRESH json schema request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REFRESH Json schema request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>REFRESH json schema request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/undeploy/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="DCAE UNDEPLOY request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'DCAE UNDEPLOY request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DCAE UNDEPLOY request','INFO',${exchangeProperty[loopObject]})" /> + <to uri="direct:undeploy-loop" /> + + <log loggingLevel="INFO" + message="UNDEPLOY request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('UNDEPLOY request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="UNDEPLOY request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('UNDEPLOY request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>UNDEPLOY request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/stop/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="STOP request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*,'STOP request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('STOP request','INFO',${exchangeProperty[loopObject]})" /> + + <to uri="direct:remove-all-policy-from-active-pdp-group" /> + <log loggingLevel="INFO" + message="STOP request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('STOP request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="STOP request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('STOP request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>STOP request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/restart/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="RESTART request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*,'RESTART request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('RESTART request','INFO',${exchangeProperty[loopObject]})" /> + + <to uri="direct:add-all-to-active-pdp-group" /> + <log loggingLevel="INFO" + message="RESTART request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('RESTART request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="RESTART request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('RESTART request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>RESTART request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/submit/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="POLICY SUBMIT request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'POLICY SUBMIT request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('POLICY SUBMIT request','INFO',${exchangeProperty[loopObject]})" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:remove-all-policy-from-active-pdp-group" /> + <log loggingLevel="INFO" + message="Processing all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="policy"> + <simple>${body}</simple> + </setProperty> + <log loggingLevel="INFO" + message="Processing Micro Service Policy: ${exchangeProperty[policy].getName()}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:delete-policy" /> + <to uri="direct:create-policy" /> + </split> + <log loggingLevel="INFO" + message="Processing all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getOperationalPolicies()} + </simple> + <setProperty propertyName="policy"> + <simple>${body}</simple> + </setProperty> + <log loggingLevel="INFO" + message="Processing Operational Policy: ${exchangeProperty[policy].getName()}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + + <to uri="direct:delete-policy" /> + <to uri="direct:create-policy" /> + </split> + + <delay> + <constant>3000</constant> + </delay> + + <to uri="direct:add-all-to-active-pdp-group" /> + + <log loggingLevel="INFO" + message="SUBMIT request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('SUBMIT request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="SUBMIT request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('SUBMIT request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>SUBMIT request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/delete/{loopName}"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="DELETE request for loop: ${header.loopName}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*,'DELETE request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DELETE request','INFO',${exchangeProperty[loopObject]})" /> + <to uri="direct:undeploy-loop" /> + <to uri="direct:remove-all-policy-from-active-pdp-group" /> + <log loggingLevel="INFO" + message="Deleting all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="policy"> + <simple>${body}</simple> + </setProperty> + <log loggingLevel="INFO" + message="Deleting Micro Service Policy: ${exchangeProperty[policy].getName()}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:delete-policy" /> + </split> + <log loggingLevel="INFO" + message="Deleting all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getOperationalPolicies()} + </simple> + <setProperty propertyName="policy"> + <simple>${body}</simple> + </setProperty> + <log loggingLevel="INFO" + message="Deleting Operational Policy: ${exchangeProperty[policy].getName()}" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:delete-policy" /> + </split> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=deleteLoop(${header.loopName})" /> + <log loggingLevel="INFO" + message="DELETE request successfully executed for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="DELETE request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('DELETE request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>DELETE request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <get uri="/v2/loop/getstatus/{loopName}" + outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName" /> + <doTry> + <log loggingLevel="INFO" + message="GET STATUS request for loop: ${header.loopName}" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET STATUS request')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request','INFO',${exchangeProperty[loopObject]})" /> + <to uri="direct:update-policy-status-for-loop" /> + <to uri="direct:update-dcae-status-for-loop" /> + <to uri="direct:update-loop-state" /> + + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET STATUS request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})" /> + </doCatch> + <doFinally> + <setBody> + <simple>${exchangeProperty[loopObject]}</simple> + </setBody> + <setHeader headerName="CamelHttpResponseCode"> + <constant>200</constant> + </setHeader> + </doFinally> + </doTry> + </route> + </get> + + <put uri="/v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}" outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName|policyType|policyVersion" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add operational Policy')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=addOperationalPolicy(${header.loopName},${header.policyType},${header.policyVersion})" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('ADD OperationalPolicy request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="ADD operational policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('ADD OperationalPolicy request failed','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>ADD Operational policy request FAILED for loop: ${header.loopName}, ${exception.message}"</simple> + </setBody> + + </doCatch> + </doTry> + </route> + </put> + <put uri="/v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}" outType="org.onap.clamp.loop.Loop" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="loopName|policyType|policyVersion|policyName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REMOVE operational Policy')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to uri="direct:load-loop" /> + <setProperty propertyName="policyName"> + <simple>${header.policyName}</simple> + </setProperty> + <setProperty propertyName="policy"> + <simple>${exchangeProperty[loopObject].getOperationalPolicy(header.policyName)}</simple> + </setProperty> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:remove-one-policy-from-active-pdp-group" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:delete-policy" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=removeOperationalPolicy(${header.loopName},${header.policyType},${header.policyVersion})" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REMOVE OperationalPolicy request successfully executed','INFO',${exchangeProperty[loopObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="REMOVE operational policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('REMOVE OperationalPolicy request failed','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>REMOVE Operational policy request FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + <post + uri="/v2/loop/create/{loopName}?templateName={templateName}" + outType="org.onap.clamp.loop.Loop" consumes="application/json" + produces="application/json"> + <route> + <removeHeaders + pattern="*" + excludePattern="loopName|templateName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Create Loop')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')" /> + <to + uri="bean:org.onap.clamp.loop.LoopController?method=createLoop(${header.loopName}, ${header.templateName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="CREATE Loop from Template request failed for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('CREATE Loop from template request failed','ERROR',${exchangeProperty[loopObject]})" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>CREATE Loop from template FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </post> + <get uri="/v2/dictionary" + outType="org.onap.clamp.tosca.Dictionary" produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Dictionaries')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=getAllDictionaries()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Dictionary request failed: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + + <get uri="/v2/dictionary/secondary/names" + outType="java.lang.String[]" produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Secondary Dictionary Level Names')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=getAllSecondaryLevelDictionaryNames()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Dictionary request failed: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/dictionary/{dictionaryName}" + outType="org.onap.clamp.tosca.Dictionary" produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="dictionaryName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Dictionary Elements for a Dictionary Name')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=getDictionary(${header.dictionaryName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Dictionary request failed for: ${header.dictionaryName}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <put uri="/v2/dictionary" type="org.onap.clamp.tosca.Dictionary" + outType="org.onap.clamp.tosca.Dictionary" consumes="application/json" + produces="application/json"> + <route> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add New or Update Dictionary')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <setProperty propertyName="DictionaryObject"> + <simple>${body}</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=saveOrUpdateDictionary(${exchangeProperty[DictionaryObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="PUT Dictionary request failed for: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>PUT Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + + <put uri="/v2/dictionary/{name}" + type="org.onap.clamp.tosca.Dictionary" + outType="org.onap.clamp.tosca.Dictionary" consumes="application/json" + produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="name" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add New or Update Dictionary Element')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <setProperty propertyName="DictionaryObject"> + <simple>${body}</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=saveOrUpdateDictionaryElement(${header.name}, ${exchangeProperty[DictionaryObject]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="PUT Dictionary request failed for: ${header.name}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>PUT Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + + <delete uri="/v2/dictionary/{name}" produces="application/json"> + <route> + <removeHeaders pattern="*" excludePattern="name" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Delete Dictionary')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=deleteDictionary(${header.name})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="DELETE Dictionary request failed for: ${header.name}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>DELETE Dictionary FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </delete> + + <delete uri="/v2/dictionary/{name}/elements/{shortName}" + produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="name|shortName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Delete Dictionary Element')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <to + uri="bean:org.onap.clamp.tosca.DictionaryService?method=deleteDictionaryElement(${header.name}, ${header.shortName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="DELETE Dictionary element request failed for: ${header.name}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>DELETE Dictionary element FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </delete> + + <get uri="/v2/policyToscaModels" + outType="org.onap.clamp.loop.template.PolicyModel" + produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Tosca Policy Models')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.PolicyModelsService?method=getAllPolicyModels()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Policy Models request failed for: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Policy models FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/policyToscaModels/{policyModelType}/{policyModelVersion}" + outType="org.onap.clamp.loop.template.PolicyModel" + produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="policyModelType|policyModelVersion" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Tosca Policy Model by Name/Version')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.PolicyModelsService?method=getPolicyModelByType(${header.policyModelType},${header.policyModelVersion})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Policy Model request failed for type: ${header.policyModelType}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Policy model FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}" + outType="java.lang.String" produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="policyModelType|policyModelVersion" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Tosca Policy Model Yaml String by Name/Version')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.PolicyModelsService?method=getPolicyModelTosca(${header.policyModelType},${header.policyModelVersion})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Policy Model YAML request failed for type: ${header.policyModelType}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Policy model YAML FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + + <post uri="/v2/policyToscaModels" + type="java.lang.String" + outType="org.onap.clamp.loop.template.PolicyModel" + consumes="plain/text" produces="application/json"> + <route> + <removeHeaders pattern="*"/> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Upload New or Update Tosca Policy Model')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <setProperty propertyName="PolicyModelTosca"> + <simple>${body}</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.loop.template.PolicyModelsService?method=createNewPolicyModelFromTosca(${exchangeProperty[PolicyModelTosca]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="POST Policy Model YAML request failed: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>POST Policy model YAML FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </post> + <put uri="/v2/policyToscaModels/{policyModelType}/{policyModelVersion}" + type="java.lang.String" + outType="org.onap.clamp.loop.template.PolicyModel" + consumes="plain/text" produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="policyModelType|policyModelVersion" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Upload New or Update Tosca Policy Model')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')" /> + <setProperty propertyName="PolicyModelTosca"> + <simple>${body}</simple> + </setProperty> + <to + uri="bean:org.onap.clamp.loop.template.PolicyModelsService?method=updatePolicyModelTosca(${header.policyModelType},${policyModelVersion},${exchangeProperty[PolicyModelTosca]})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="MODIFY Policy Model YAML request failed: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>MODIFY Policy model YAML FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </put> + + <get uri="/v2/templates" + outType="org.onap.clamp.loop.template.LoopTemplate" + produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Templates')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.LoopTemplatesService?method=getAllLoopTemplates()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET ALL templates request failed: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET ALL templates FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/templates/{templateName}" + outType="org.onap.clamp.loop.template.LoopTemplate" + produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="templateName" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET a Template by NAME')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.LoopTemplatesService?method=getLoopTemplate(${header.templateName})" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET Template request failed for template: ${header.templateName}, ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Template FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/templates/names" outType="java.lang.String[]" + produces="application/json"> + <route> + <removeHeaders pattern="*" /> + <doTry> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop Template Names')" /> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')" /> + <to + uri="bean:org.onap.clamp.loop.template.LoopTemplatesService?method=getLoopTemplateNames()" /> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=endLog()" /> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=errorLog()" /> + <log loggingLevel="ERROR" + message="GET All Template names request failed for template: ${exception.stacktrace}" /> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET All Template names FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/clampInformation" outType="org.onap.clamp.clds.model.ClampInformation" + produces="application/json"> + <to + uri="bean:org.onap.clamp.authorization.AuthorizationController?method=getClampInformation()" /> + </get> + </rest> +</rests> diff --git a/src/main/resources/clds/camel/rest/clds-services.xml b/src/main/resources/clds/camel/rest/clds-services.xml new file mode 100644 index 000000000..ce52f31d6 --- /dev/null +++ b/src/main/resources/clds/camel/rest/clds-services.xml @@ -0,0 +1,24 @@ +<rests xmlns="http://camel.apache.org/schema/spring"> + <rest> + <get uri="/v1/healthcheck" produces="application/json" + outType="org.onap.clamp.clds.model.CldsHealthCheck"> + <route> + <setBody> + <method ref="org.onap.clamp.clds.service.CldsHealthcheckService" + method="gethealthcheck()" /> + </setBody> + <when> + <simple> ${body} == 'NOT-OK'</simple> + <setHeader headerName="CamelHttpResponseCode"> + <constant>404</constant> + </setHeader> + <log loggingLevel="ERROR" message="HealthCheck failed" /> + </when> + </route> + </get> + + <get uri="/v1/user/getUser" produces="text/plain"> + <to uri="bean:org.onap.clamp.authorization.UserService?method=getUser()" /> + </get> + </rest> +</rests> diff --git a/src/main/resources/clds/camel/routes/cds-flows.xml b/src/main/resources/clds/camel/routes/cds-flows.xml new file mode 100644 index 000000000..0e56970c2 --- /dev/null +++ b/src/main/resources/clds/camel/routes/cds-flows.xml @@ -0,0 +1,64 @@ +<routes xmlns="http://camel.apache.org/schema/spring"> + <route id="get-blueprint-workflow-list"> + <from uri="direct:get-blueprint-workflow-list"/> + <log loggingLevel="INFO" + message="Getting blueprint workflow list from CDS"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting workflow list from CDS')"/> + <doTry> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to query workflows from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}"></log> + <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.cds.userName}}&authPassword={{clamp.config.cds.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=30000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + + <log loggingLevel="ERROR" + message="GET CDS request FAILED: ${exception.stacktrace}" /> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="get-blueprint-workflow-input-properties"> + <from uri="direct:get-blueprint-workflow-input-properties"/> + <log loggingLevel="INFO" + message="Getting blueprint input properties for workflow"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting input properties for workflow')"/> + <doTry> + <setHeader headerName="CamelHttpMethod"> + <constant>POST</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to query input properties for workflow from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec"></log> + <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.cds.userName}}&authPassword={{clamp.config.cds.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=30000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + + <log loggingLevel="ERROR" + message="GET CDS workflow input request FAILED: ${exception.stacktrace}" /> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> +</routes>
\ No newline at end of file diff --git a/src/main/resources/clds/camel/routes/dcae-flows.xml b/src/main/resources/clds/camel/routes/dcae-flows.xml new file mode 100644 index 000000000..65849e9ae --- /dev/null +++ b/src/main/resources/clds/camel/routes/dcae-flows.xml @@ -0,0 +1,491 @@ +<routes xmlns="http://camel.apache.org/schema/spring"> + <route id="deploy-loop"> + <from uri="direct:deploy-loop"/> + <choice> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true + </simple> + <to uri="direct:deploy-loop-single-blueprint"/> + </when> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false + </simple> + <to uri="direct:deploy-loop-multi-blueprint"/> + </when> + </choice> + </route> + <route id="deploy-loop-multi-blueprint"> + <from uri="direct:deploy-loop-multi-blueprint"/> + <doTry> + <log loggingLevel="INFO" + message="Deploying the blueprints for loop: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Deploying the loop with multiple blueprints')"/> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="microServicePolicy"> + <simple>${body}</simple> + </setProperty> + <log + loggingLevel="INFO" + message="Processing Micro Service Policy: ${exchangeProperty[microServicePolicy].getName()}"/> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <setBody> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getDeployPayload(${exchangeProperty[loopObject]},${exchangeProperty[microServicePolicy]})"/> + </setBody> + <setProperty propertyName="dcaeDeploymentId"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="generateDeploymentId()"/> + </setProperty> + <setHeader headerName="CamelHttpMethod"> + <constant>PUT</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to deploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=300000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})"/> + </setProperty> + <setProperty propertyName="dcaeStatusUrl"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/> + </setProperty> + <to + uri="bean:org.onap.clamp.policy.microservice.MicroServicePolicyService?method=updateDcaeDeploymentFields(${exchangeProperty[microServicePolicy]},${exchangeProperty[dcaeDeploymentId]},${exchangeProperty[dcaeStatusUrl]})"/> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('Deploy for the micro service: ${exchangeProperty[microServicePolicy].getName()} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','DCAE',${exchangeProperty[loopObject]})"/> + </split> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>false</constant> + </handled> + <setProperty propertyName="logMessage"> + <simple>DEPLOY micro service failed + (MicroService name:${exchangeProperty[microServicePolicy].getName()}), + Dep-id:${exchangeProperty[dcaeDeploymentId]}, + StatusUrl:${exchangeProperty[dcaeStatusUrl]}) + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>DCAE</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="deploy-loop-single-blueprint"> + <from uri="direct:deploy-loop-single-blueprint"/> + <doTry> + <log loggingLevel="INFO" + message="Deploying the loop: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Deploying the loop')"/> + <setBody> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getDeployPayload(${exchangeProperty[loopObject]})"/> + </setBody> + <setProperty propertyName="dcaeDeploymentId"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="generateDeploymentId()"/> + </setProperty> + <setHeader headerName="CamelHttpMethod"> + <constant>PUT</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to deploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=300000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})"/> + </setProperty> + + + <setProperty propertyName="dcaeStatusUrl"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/> + </setProperty> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateDcaeDeploymentFields(${exchangeProperty[loopObject]},${exchangeProperty[dcaeDeploymentId]},${exchangeProperty[dcaeStatusUrl]})"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>DEPLOY loop status + (Dep-id:${exchangeProperty[dcaeDeploymentId]}, + StatusUrl:${exchangeProperty[dcaeStatusUrl]}) + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>DCAE</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + <route id="undeploy-loop"> + <from uri="direct:undeploy-loop"/> + <choice> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true + </simple> + <to uri="direct:undeploy-loop-single-blueprint"/> + </when> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false + </simple> + <to uri="direct:undeploy-loop-multi-blueprint"/> + </when> + </choice> + </route> + <route id="undeploy-loop-multi-blueprint"> + <from uri="direct:undeploy-loop-multi-blueprint"/> + <doTry> + <log loggingLevel="INFO" + message="Undeploying the blueprints for loop: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Undeploying the loop with multiple blueprints')"/> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="microServicePolicy"> + <simple>${body}</simple> + </setProperty> + <log + loggingLevel="INFO" + message="Processing Micro Service Policy: ${exchangeProperty[microServicePolicy].getName()}"/> + <choice> + <when> + <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentId()} != null + </simple> + <setBody> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getUndeployPayload(${exchangeProperty[microServicePolicy]})"/> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>DELETE</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to undeploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[microServicePolicy].getDcaeDeploymentId()}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[microServicePolicy].getDcaeDeploymentId()}?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=300000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})"/> + </setProperty> + <setProperty propertyName="dcaeStatusUrl"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/> + </setProperty> + <to + uri="bean:org.onap.clamp.policy.microservice.MicroServicePolicyService?method=updateDcaeDeploymentFields(${exchangeProperty[microServicePolicy]},null,${exchangeProperty[dcaeStatusUrl]})"/> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','DCAE',${exchangeProperty[loopObject]})"/> + </when> + <otherwise> + <log loggingLevel="WARNING" + message="Cannot Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()}, the Deployment ID does not exist !"/> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('Cannot Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()}, the Deployment ID does not exist !','WARNING','DCAE',${exchangeProperty[loopObject]})"/> + </otherwise> + </choice> + </split> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>false</constant> + </handled> + <setProperty propertyName="logMessage"> + <simple>UNDEPLOY micro service failed + (MicroService name:${exchangeProperty[microServicePolicy].getName()}) + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>DCAE</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="undeploy-loop-single-blueprint"> + <from uri="direct:undeploy-loop-single-blueprint"/> + <log loggingLevel="INFO" + message="Undeploying the loop: ${exchangeProperty[loopObject].getName()} : ${exchangeProperty[loopObject].getDcaeDeploymentId()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Undeploying the loop')"/> + <choice> + <when> + <simple>${exchangeProperty[loopObject].getDcaeDeploymentId()} + != null + </simple> + <doTry> + <setBody> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getUndeployPayload(${exchangeProperty[loopObject]})"/> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>DELETE</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to undeploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}"></log> + <toD + uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=300000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})"/> + </setProperty> + <setProperty propertyName="dcaeStatusUrl"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/> + </setProperty> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateDcaeDeploymentFields(${exchangeProperty[loopObject]},null,${exchangeProperty[dcaeStatusUrl]})"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>UNDEPLOY loop status</simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>DCAE</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </when> + <otherwise> + <log loggingLevel="WARNING" + message="Cannot Undeploy for the loop: ${exchangeProperty[loopObject].getName()}, the Deployment ID does not exist !"/> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('Cannot Undeploy for the loop: ${exchangeProperty[loopObject].getName()}, the Deployment ID does not exist !','WARNING',${exchangeProperty[loopObject]})"/> + </otherwise> + </choice> + </route> + <route id="get-dcae-deployment-status"> + <from uri="direct:get-dcae-deployment-status"/> + <log loggingLevel="INFO" + message="Getting DCAE deployment status for loop: ${exchangeProperty[loopObject].getName()} - ${exchangeProperty[dcaeComponent].getComponentName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting Deployment status')"/> + <doTry> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to query microservice deployment status: ${exchangeProperty[getStatusUrlModified]}"></log> + <choice> + <when> + <simple>${exchangeProperty[getStatusUrl].contains("?")} == true + </simple> + <setProperty propertyName="uriSeparator"> + <simple>&</simple> + </setProperty> + </when> + <otherwise> + <setProperty propertyName="uriSeparator"> + <simple>?</simple> + </setProperty> + </otherwise> + </choice> + <toD + uri="${exchangeProperty[getStatusUrl]}${exchangeProperty[uriSeparator]}bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=30000&authenticationPreemptive=true&connectionClose=true"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + + <log loggingLevel="ERROR" + message="GET DCAE deployment request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET DCAE deployment request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>DCAE deployment status</simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>DCAE</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + <route id="get-dcae-blueprint-inventory"> + <from uri="direct:get-dcae-blueprint-inventory"/> + <log loggingLevel="INFO" + message="Getting DCAE blueprint id in inventory"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting blueprint id in inventory')"/> + <doTry> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to query Dcae inventory Loop status: {{clamp.config.dcae.inventory.url}}/dcae-service-types?${header[CamelHttpQuery]}"></log> + <toD + uri="{{clamp.config.dcae.inventory.url}}/dcae-service-types?asdcResourceId=${exchangeProperty[blueprintResourceId]}&asdcServiceId=${exchangeProperty[blueprintServiceId]}&typeName=${exchangeProperty[blueprintName]}&bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=30000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + + </route> + <route id="get-all-dcae-blueprint-inventory"> + <from uri="direct:get-all-dcae-blueprint-inventory"/> + <log loggingLevel="INFO" + message="Getting all DCAE blueprint from inventory"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting all blueprint from inventory')"/> + <doTry> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to query Blueprints from DCAE inventory: {{clamp.config.dcae.inventory.url}}/dcae-service-types?${header[CamelHttpQuery]}"></log> + <toD uri="{{clamp.config.dcae.inventory.url}}/dcae-service-types;bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.dcae.deployment.userName}}&authPassword={{clamp.config.dcae.deployment.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=30000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <setProperty propertyName="dcaeResponseList"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertToDcaeInventoryResponse(${body})"/> + </setProperty> + <split> + <simple>${exchangeProperty[dcaeResponseList]}</simple> + <convertBodyTo type="org.onap.clamp.clds.model.dcae.DcaeInventoryResponse"/> + <setProperty propertyName="dcaeResponse"> + <simple>${body}</simple> + </setProperty> + <to uri="bean:org.onap.clamp.clds.model.dcae.DcaeInventoryCache?method=addDcaeInventoryResponse(${exchangeProperty[dcaeResponse]})"/> + </split> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> +</routes>
\ No newline at end of file diff --git a/src/main/resources/clds/camel/routes/loop-flows.xml b/src/main/resources/clds/camel/routes/loop-flows.xml new file mode 100644 index 000000000..d0d552568 --- /dev/null +++ b/src/main/resources/clds/camel/routes/loop-flows.xml @@ -0,0 +1,253 @@ +<routes xmlns="http://camel.apache.org/schema/spring"> + <route id="load-loop"> + <from uri="direct:load-loop" /> + <setBody> + <simple>${header.loopName}</simple> + </setBody> + <setProperty propertyName="loopObject"> + <method ref="org.onap.clamp.loop.LoopService" method="getLoop" /> + </setProperty> + + <when> + <simple>${exchangeProperty[loopObject]} == null</simple> + <setHeader headerName="CamelHttpResponseCode"> + <constant>404</constant> + </setHeader> + <log loggingLevel="WARN" message="Loop not found in database: ${body}" /> + <stop /> + </when> + </route> + <route id="update-policy-status-for-loop"> + <from uri="direct:update-policy-status-for-loop" /> + <setProperty propertyName="policyComponent"> + <simple>${exchangeProperty[loopObject].getComponent('POLICY')} + </simple> + </setProperty> + <setProperty propertyName="policyFound"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <setProperty propertyName="policyDeployed"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + <log loggingLevel="INFO" + message="Processing all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="policyName"> + <simple>${body.getName()}</simple> + </setProperty> + <setProperty propertyName="policyType"> + <simple>${body.getPolicyModel().getPolicyModelType()}</simple> + </setProperty> + <setProperty propertyName="policyTypeVersion"> + <simple>${body.getPolicyModel().getVersion()}</simple> + </setProperty> + <setProperty propertyName="policyVersion"> + <simple>1.0.0</simple> + </setProperty> + <setBody> + <constant>null</constant> + </setBody> + <log loggingLevel="INFO" + message="Processing Micro Service Policy: ${exchangeProperty[policyName]} of type ${exchangeProperty[policyType]}" /> + <to uri="direct:verify-one-policy" /> + </split> + <log loggingLevel="INFO" + message="Processing all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}" /> + <split> + <simple>${exchangeProperty[loopObject].getOperationalPolicies()} + </simple> + <setProperty propertyName="policyName"> + <simple>${body.getName()}</simple> + </setProperty> + <setProperty propertyName="policyType"> + <simple>${body.getPolicyModel().getPolicyModelType()}</simple> + </setProperty> + <setProperty propertyName="policyTypeVersion"> + <simple>${body.getPolicyModel().getVersion()}</simple> + </setProperty> + <setProperty propertyName="policyVersion"> + <simple>1.0.0</simple> + </setProperty> + <setProperty propertyName="operationalPolicy"> + <simple>${body}</simple> + </setProperty> + <setBody> + <constant>null</constant> + </setBody> + <log loggingLevel="INFO" + message="Processing Operational Policy: ${exchangeProperty[policyName]} of type ${exchangeProperty[policyType]}" /> + <to uri="direct:verify-one-policy" /> + </split> + <setProperty propertyName="policyState"> + <simple> ${exchangeProperty[policyComponent].getState()} + </simple> + </setProperty> + <log loggingLevel="INFO" + message="Policy state set to: ${exchangeProperty[policyState].getStateName()}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('Policy state set to: ${exchangeProperty[policyState].getStateName()}','INFO','POLICY',${exchangeProperty[loopObject]})" /> + </route> + <route id="update-dcae-status-for-loop"> + <from uri="direct:update-dcae-status-for-loop" /> + <log loggingLevel="INFO" + message="Updating DCAE status for loop: ${exchangeProperty[loopObject].getName()}" /> + <choice> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true + </simple> + <setProperty propertyName="dcaeComponent"> + <simple>${exchangeProperty[loopObject].getComponent('DCAE')}</simple> + </setProperty> + <when> + <simple>${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()} != null + </simple> + <setProperty propertyName="getStatusUrl"> + <simple>${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()}</simple> + </setProperty> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:get-dcae-deployment-status" /> + <when> + <simple> ${header.CamelHttpResponseCode} == 200 </simple> + <convertBodyTo type="java.lang.String" /> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})" /> + </setProperty> + </when> + </when> + <setProperty propertyName="dcaeState"> + <simple> ${exchangeProperty[dcaeComponent].computeState(*)} + </simple> + </setProperty> + <log loggingLevel="INFO" + message="DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - DCAE message: ${exchangeProperty[dcaeResponse].getError()}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - message: ${exchangeProperty[dcaeResponse].getError()}','INFO','DCAE',${exchangeProperty[loopObject]})" /> + </when> + <when> + <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false + </simple> + <split> + <simple>${exchangeProperty[loopObject].getMicroServicePolicies()} + </simple> + <setProperty propertyName="microServicePolicy"> + <simple>${body}</simple> + </setProperty> + <setProperty propertyName="dcaeComponent"> + <simple>${exchangeProperty[loopObject].getComponent('DCAE_' + ${exchangeProperty[microServicePolicy].getName()})}</simple> + </setProperty> + <when> + <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentStatusUrl()} != null + </simple> + <setProperty propertyName="getStatusUrl"> + <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentStatusUrl()}</simple> + </setProperty> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:get-dcae-deployment-status" /> + <when> + <simple> ${header.CamelHttpResponseCode} == 200 </simple> + <convertBodyTo type="java.lang.String" /> + <setProperty propertyName="dcaeResponse"> + <method ref="org.onap.clamp.loop.components.external.DcaeComponent" + method="convertDcaeResponse(${body})" /> + </setProperty> + </when> + </when> + <setProperty propertyName="dcaeState"> + <simple> ${exchangeProperty[dcaeComponent].computeState(*)} + </simple> + </setProperty> + <log loggingLevel="INFO" + message="DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - DCAE message: ${exchangeProperty[dcaeResponse].getError()}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - message: ${exchangeProperty[dcaeResponse].getError()}','INFO','DCAE',${exchangeProperty[microServicePolicy]})" /> + </split>> + </when> + </choice> + </route> + <route id="direct:update-loop-state"> + <from uri="direct:update-loop-state" /> + <log loggingLevel="INFO" + message="Updating status for loop: ${exchangeProperty[loopObject].getName()}" /> + <choice> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'BLUEPRINT_DEPLOYED' and ${exchangeProperty['policyState'].getStateName()} + == 'NOT_SENT' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'DESIGN')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == 'IN_ERROR' or + ${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_INSTALLATION_FAILED' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'IN_ERROR')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_UNINSTALLATION_FAILED' or + ${exchangeProperty['policyState'].getStateName()} == 'IN_ERROR' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'IN_ERROR')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_INSTALLED_SUCCESSFULLY' and + ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'RUNNING')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_INSTALLED_SUCCESSFULLY' and + ${exchangeProperty['policyState'].getStateName()} == 'SENT' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'STOPPED')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'BLUEPRINT_DEPLOYED' or ${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_UNINSTALLED_SUCCESSFULLY' and + ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'SUBMITTED')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'PROCESSING_MICROSERVICE_INSTALLATION' or + ${exchangeProperty['dcaeState'].getStateName()} == + 'PROCESSING_MICROSERVICE_UNINSTALLATION' and + ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'WAITING')" /> + </when> + <when> + <simple>${exchangeProperty['dcaeState'].getStateName()} == + 'MICROSERVICE_INSTALLED_SUCCESSFULLY' and + ${exchangeProperty['policyState'].getStateName()} != 'NOT_SENT' + </simple> + <to + uri="bean:org.onap.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'DEPLOYED')" /> + </when> + </choice> + <log loggingLevel="INFO" + message="New loop state is: ${exchangeProperty[loopObject].getLastComputedState().toString()}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('New loop state is: ${exchangeProperty[loopObject].getLastComputedState().toString()}','INFO',${exchangeProperty[loopObject]})" /> + + </route> +</routes>
\ No newline at end of file diff --git a/src/main/resources/clds/camel/routes/policy-flows.xml b/src/main/resources/clds/camel/routes/policy-flows.xml new file mode 100644 index 000000000..9328ceb00 --- /dev/null +++ b/src/main/resources/clds/camel/routes/policy-flows.xml @@ -0,0 +1,496 @@ +<routes xmlns="http://camel.apache.org/schema/spring"> + <route id="verify-one-policy"> + <from uri="direct:verify-one-policy"/> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:get-policy"/> + <when> + <simple>${header.CamelHttpResponseCode} != 200</simple> + <setProperty propertyName="policyFound"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <log loggingLevel="WARN" + message="At least one policy has not been found on policy engine: ${exchangeProperty[policyName]}"/> + </when> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <to uri="direct:get-deployment-policy"/> + <when> + <simple>${header.CamelHttpResponseCode} != 200</simple> + <setProperty propertyName="policyDeployed"> + <simple resultType="java.lang.Boolean">false</simple> + </setProperty> + <log loggingLevel="WARN" + message="At least one policy has not been deployed on policy engine: ${exchangeProperty[policyName]}"/> + </when> + <setProperty propertyName="newPolicyState"> + <simple>${exchangeProperty[policyComponent].computeState(*)}</simple> + </setProperty> + </route> + + <route id="get-policy"> + <from uri="direct:get-policy"/> + <doTry> + <log loggingLevel="INFO" + message="Getting Policy: ${exchangeProperty[policyName]}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Get Policy')"/> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to get policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyType]}/versions/${exchangeProperty[policyTypeVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}"></log> + <toD + uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyType]}/versions/${exchangeProperty[policyTypeVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + + <log loggingLevel="ERROR" + message="GET policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET policy request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})" /> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>${exchangeProperty[policyName]} GET + Policy status + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + + <route id="get-deployment-policy"> + <from uri="direct:get-deployment-policy"/> + <doTry> + <log loggingLevel="INFO" + message="Getting the policy deployment in PDP: ${exchangeProperty[policyName]}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the policy deployment in PDP')"/> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to get policy deployment status: {{clamp.config.policy.pap.url}}/policy/pap/v1/policies/deployed/${exchangeProperty[policyName]}/1.0.0"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/policies/deployed/${exchangeProperty[policyName]}/1.0.0?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + + <log loggingLevel="ERROR" + message="GET policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}" /> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('GET policy request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})" /> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>${exchangeProperty[policyName]} GET Policy deployment + status + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + <route id="get-all-policy-models"> + <from uri="direct:get-all-policy-models"/> + <doTry> + <log loggingLevel="INFO" message="Getting all the policy models"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting all the policy models')"/> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to get all policy models: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes"></log> + <toD + uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="get-policy-model"> + <from uri="direct:get-policy-model"/> + <doTry> + <log loggingLevel="INFO" + message="Getting the policy model: ${exchangeProperty[policyModelName]}/${exchangeProperty[policyModelVersion]}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the policy model')"/> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to get policy model: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelName]}/versions/${exchangeProperty[policyModelVersion]}"></log> + <toD + uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelName]}/versions/${exchangeProperty[policyModelVersion]}?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="create-policy"> + <from uri="direct:create-policy"/> + <doTry> + <log loggingLevel="INFO" + message="Creating Policy: ${exchangeProperty[policy].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Create Policy')"/> + <setBody> + <simple>${exchangeProperty[policy].createPolicyPayload()} + </simple> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>POST</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to create policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}/versions/${exchangeProperty[policy].getPolicyModel().getVersion()}/policies"></log> + <toD + uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}/versions/${exchangeProperty[policy].getPolicyModel().getVersion()}/policies?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>${exchangeProperty[policy].getName()} creation + status + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + + <route id="delete-policy"> + <from uri="direct:delete-policy"/> + <doTry> + <log loggingLevel="INFO" + message="Deleting Policy: ${exchangeProperty[policy].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Delete Policy')"/> + <setBody> + <constant>null</constant> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>DELETE</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <setProperty propertyName="policyVersion"> + <simple>1.0.0</simple> + </setProperty> + <log loggingLevel="INFO" + message="Endpoint to delete policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}/versions/${exchangeProperty[policy].getPolicyModel().getVersion()}/policies/${exchangeProperty[policy].getName()}/versions/${exchangeProperty[policyVersion]}"></log> + <toD + uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}/versions/${exchangeProperty[policy].getPolicyModel().getVersion()}/policies/${exchangeProperty[policy].getName()}/versions/${exchangeProperty[policyVersion]}?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&deleteWithBody=false&mapHttpMessageBody=false&mapHttpMessageFormUrlEncodedBody=false&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>${exchangeProperty[policy].getName()} removal + status + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + <route id="add-all-to-active-pdp-group"> + <from uri="direct:add-all-to-active-pdp-group"/> + <doTry> + <log loggingLevel="INFO" + message="Adding loop policies to PDP Group: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Add policies to PDP group')"/> + <setBody> + <simple> + ${exchangeProperty[loopObject].getComponent("POLICY").createPoliciesPayloadPdpGroup(exchangeProperty[loopObject],"POST")} + </simple> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>POST</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to add policies to PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&useSystemProperties=true&authUsername={{clamp.config.policy.pap.userName}}&authPassword={{clamp.config.policy.pap.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>PDP Group push ALL status</simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + + <route id="remove-all-policy-from-active-pdp-group"> + <from uri="direct:remove-all-policy-from-active-pdp-group"/> + <doTry> + <log loggingLevel="INFO" + message="Removing loop policies from PDP Group: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Remove policies from PDP group')"/> + <setBody> + <simple> + ${exchangeProperty[loopObject].getComponent("POLICY").createPoliciesPayloadPdpGroup(exchangeProperty[loopObject],"DELETE")} + </simple> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>POST</constant> + </setHeader> + <setHeader headerName="Content-Type"> + <constant>application/json</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to remove policies from PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&useSystemProperties=true&authUsername={{clamp.config.policy.pap.userName}}&authPassword={{clamp.config.policy.pap.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + <setProperty propertyName="logMessage"> + <simple>PDP Group remove ALL status</simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doFinally> + </doTry> + </route> + <route id="get-all-pdp-groups"> + <from uri="direct:get-all-pdp-groups"/> + <doTry> + <log loggingLevel="INFO" + message="Getting the list of PDP Groups"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the PDP Group list')"/> + <setHeader headerName="CamelHttpMethod"> + <constant>GET</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to get policy model: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.policy.api.userName}}&authPassword={{clamp.config.policy.api.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <convertBodyTo type="java.lang.String"/> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> + <route id="remove-one-policy-from-active-pdp-group"> + <from uri="direct:remove-one-policy-from-active-pdp-group"/> + <doTry> + <log loggingLevel="INFO" + message="Removing policy from active PDP group for loop: ${exchangeProperty[loopObject].getName()}"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Removing one policy PDP group')"/> + <setBody> + <constant>null</constant> + </setBody> + <setHeader headerName="CamelHttpMethod"> + <constant>DELETE</constant> + </setHeader> + <setHeader headerName="X-ONAP-RequestID"> + <simple>${exchangeProperty[X-ONAP-RequestID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-InvocationID"> + <simple>${exchangeProperty[X-ONAP-InvocationID]} + </simple> + </setHeader> + <setHeader headerName="X-ONAP-PartnerName"> + <simple>${exchangeProperty[X-ONAP-PartnerName]} + </simple> + </setHeader> + <log loggingLevel="INFO" + message="Endpoint to delete policy from PDP Group: {{clamp.config.policy.pap.url}}/pdps/policies/${exchangeProperty[policyName]}/versions/1.0.0"></log> + <toD + uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/policies/${exchangeProperty[policyName]}/versions/1.0.0?bridgeEndpoint=true&useSystemProperties=true&mapHttpMessageHeaders=false&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authUsername={{clamp.config.policy.pap.userName}}&authPassword={{clamp.config.policy.pap.password}}&httpClient.connectTimeout=10000&httpClient.socketTimeout=20000&authenticationPreemptive=true&connectionClose=true"/> + <setProperty propertyName="logMessage"> + <simple>${exchangeProperty[policyName]} PDP Group removal status + </simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>false</constant> + </handled> + <setProperty propertyName="logMessage"> + <simple>PDP Group removal, Error reported: ${exception}</simple> + </setProperty> + <setProperty propertyName="logComponent"> + <simple>POLICY</simple> + </setProperty> + <to uri="direct:dump-loop-log-http-response"/> + </doCatch> + <doFinally> + <to uri="direct:reset-raise-http-exception-flag"/> + <to + uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/> + </doFinally> + </doTry> + </route> +</routes>
\ No newline at end of file diff --git a/src/main/resources/clds/camel/routes/utils-flows.xml b/src/main/resources/clds/camel/routes/utils-flows.xml new file mode 100644 index 000000000..bbbc46a20 --- /dev/null +++ b/src/main/resources/clds/camel/routes/utils-flows.xml @@ -0,0 +1,28 @@ +<routes xmlns="http://camel.apache.org/schema/spring"> + <route id="reset-raise-http-exception-flag"> + <from uri="direct:reset-raise-http-exception-flag" /> + <setProperty propertyName="raiseHttpExceptionFlag"> + <simple resultType="java.lang.Boolean">true</simple> + </setProperty> + </route> + + <route id="dump-loop-log-http-response"> + <from uri="direct:dump-loop-log-http-response" /> + <log loggingLevel="INFO" + message="${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}" /> + <choice> + <when> + <simple>${exchangeProperty[logComponent]} == null</simple> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLog('${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO',${exchangeProperty[loopObject]})" /> + </when> + <otherwise> + <to + uri="bean:org.onap.clamp.loop.log.LoopLogService?method=addLogForComponent('${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','${exchangeProperty[logComponent]}',${exchangeProperty[loopObject]})" /> + <setProperty propertyName="logComponent"> + <constant>null</constant> + </setProperty> + </otherwise> + </choice> + </route> +</routes>
\ No newline at end of file diff --git a/src/main/resources/clds/clds-users.json b/src/main/resources/clds/clds-users.json new file mode 100644 index 000000000..fe305980b --- /dev/null +++ b/src/main/resources/clds/clds-users.json @@ -0,0 +1,32 @@ + [{ + "user":"admin", + "password":"$2a$10$H/e21kl04Dw9C978CHuM7OewyMGUN5WGzAAx7SgIaR4ix8.wTcssi", + "permissions": + [ + "org.onap.clamp.clds.cl|dev|read", + "org.onap.clamp.clds.cl|dev|update", + "org.onap.clamp.clds.cl.manage|dev|*", + "org.onap.clamp.clds.cl.event|dev|*", + "org.onap.clamp.clds.filter.vf|dev|*", + "org.onap.clamp.clds.template|dev|read", + "org.onap.clamp.clds.template|dev|update", + "org.onap.clamp.clds.tosca|dev|read", + "org.onap.clamp.clds.tosca|dev|update" + ] + }, + { + "user":"cs0008", + "password":"$2a$10$H/e21kl04Dw9C978CHuM7OewyMGUN5WGzAAx7SgIaR4ix8.wTcssi", + "permissions": + [ + "org.onap.clamp.clds.cl|dev|read", + "org.onap.clamp.clds.cl|dev|update", + "org.onap.clamp.clds.cl.manage|dev|*", + "org.onap.clamp.clds.filter.vf|dev|*", + "org.onap.clamp.clds.template|dev|read", + "org.onap.clamp.clds.template|dev|update", + "org.onap.clamp.clds.tosca|dev|read", + "org.onap.clamp.clds.tosca|dev|update" + ] + } +] diff --git a/src/main/resources/clds/json-schema/operational_policies/operational_policy.json b/src/main/resources/clds/json-schema/operational_policies/operational_policy.json new file mode 100644 index 000000000..973028316 --- /dev/null +++ b/src/main/resources/clds/json-schema/operational_policies/operational_policy.json @@ -0,0 +1,320 @@ +{ + "type": "object", + "title": "Configuration", + "required": [ + "operational_policy" + ], + "properties": { + "operational_policy": { + "type": "object", + "title": "Related Parameters", + "required": [ + "controlLoop", + "policies" + ], + "properties": { + "controlLoop": { + "type": "object", + "title": "Control Loop details", + "required": [ + "timeout", + "abatement", + "trigger_policy", + "controlLoopName" + ], + "properties": { + "timeout": { + "type": "string", + "title": "Overall Time Limit", + "default": "0", + "format": "number" + }, + "abatement": { + "type": "string", + "title": "Abatement", + "enum": [ + "True", + "False" + ] + }, + "trigger_policy": { + "type": "string", + "title": "Policy Decision Entry" + }, + "controlLoopName": { + "type": "string", + "title": "Control loop name", + "readOnly": "True" + } + } + }, + "policies": { + "uniqueItems": "true", + "id": "policies_array", + "type": "array", + "title": "Policy Decision Tree", + "format": "tabs-top", + "items": { + "title": "Policy Decision", + "type": "object", + "id": "policy_item", + "headerTemplate": "{{self.id}} - {{self.recipe}}", + "format": "categories", + "basicCategoryTitle": "recipe", + "required": [ + "id", + "retry", + "timeout", + "actor", + "success", + "failure", + "failure_timeout", + "failure_retries", + "failure_exception", + "failure_guard", + "target" + ], + "properties": { + "id": { + "default": "Policy 1", + "title": "Policy ID", + "type": "string" + }, + "retry": { + "default": "0", + "title": "Number of Retry", + "type": "string", + "format": "number" + }, + "timeout": { + "default": "0", + "title": "Timeout", + "type": "string", + "format": "number" + }, + "actor": { + "type": "object", + "title": "Actor", + "anyOf": [ + { + "title": "APPC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "APPC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Restart", + "Rebuild", + "Migrate", + "Health-Check", + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SO", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SO", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "VF Module Create", + "VF Module Delete" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SDNC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SDNC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Reroute", + "BandwidthOnDemand" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "VFC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "VFC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "CDS", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "CDS", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "object", + "anyOf": [ + { + "title": "user-defined", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "user-defined", + "format": "textarea" + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "default": "", + "format": "textarea" + } + } + } + ] + } + } + } + ] + }, + "success": { + "default": "final_success", + "title": "When Success", + "type": "string" + }, + "failure": { + "default": "final_failure", + "title": "When Failure", + "type": "string" + }, + "failure_timeout": { + "default": "final_failure_timeout", + "title": "When Failure Timeout", + "type": "string" + }, + "failure_retries": { + "default": "final_failure_retries", + "title": "When Failure Retries", + "type": "string" + }, + "failure_exception": { + "default": "final_failure_exception", + "title": "When Failure Exception", + "type": "string" + }, + "failure_guard": { + "default": "final_failure_guard", + "title": "When Failure Guard", + "type": "string" + }, + "target": { + "type": "object", + "required": [ + "type", + "resourceID" + ], + "anyOf": [ + { + "title": "User Defined", + "additionalProperties": "True", + "properties": { + "type": { + "title": "Target type", + "type": "string", + "default": "", + "enum": [ + "VNF", + "VFMODULE", + "VM" + ] + }, + "resourceID": { + "title": "Target type", + "type": "string", + "default": "" + } + } + } + ] + } + } + } + } + } + } + } +} + diff --git a/src/main/resources/clds/key.properties b/src/main/resources/clds/key.properties new file mode 100644 index 000000000..dda811040 --- /dev/null +++ b/src/main/resources/clds/key.properties @@ -0,0 +1 @@ +org.onap.clamp.encryption.aes.key=aa3871669d893c7fb8abbcda31b88b4f
\ No newline at end of file diff --git a/src/main/resources/clds/sdc-controllers-config.json b/src/main/resources/clds/sdc-controllers-config.json new file mode 100644 index 000000000..b86732ec7 --- /dev/null +++ b/src/main/resources/clds/sdc-controllers-config.json @@ -0,0 +1,18 @@ +{ + "sdc-connections":{ + "sdc-controller":{ + "user": "clamp", + "consumerGroup": "clamp", + "consumerId": "clamp", + "environmentName": "AUTO", + "sdcAddress": "sdc.api.simpledemo.onap.org:8443", + "password": "b7acccda32b98c5bb7acccda32b98c5b05D511BD6D93626E90D18E9D24D9B78CD34C7EE8012F0A189A28763E82271E50A5D4EC10C7D93E06E0A2D27CAE66B981", + "pollingInterval":30, + "pollingTimeout":30, + "activateServerTLSAuth":"false", + "keyStorePassword":"", + "keyStorePath":"", + "messageBusAddresses":["ueb.api.simpledemo.onap.org"] + } + } +} diff --git a/src/main/resources/clds/tosca-converter/default-tosca-types.yaml b/src/main/resources/clds/tosca-converter/default-tosca-types.yaml new file mode 100644 index 000000000..a11a73698 --- /dev/null +++ b/src/main/resources/clds/tosca-converter/default-tosca-types.yaml @@ -0,0 +1,87 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +data_types: + tosca.datatypes.Root: + description: The TOSCA root Data Type all other TOSCA base Data Types derive from + tosca.datatypes.Credential: + derived_from: tosca.datatypes.Root + properties: + protocol: + type: string + required: false + token_type: + type: string + default: password + token: + type: string + keys: + type: map + required: false + entry_schema: + type: string + user: + type: string + required: false + tosca.datatypes.TimeInterval: + derived_from: tosca.datatypes.Root + properties: + start_time: + type: timestamp + required: true + end_time: + type: timestamp + required: true + tosca.datatypes.network.NetworkInfo: + derived_from: tosca.datatypes.Root + properties: + network_name: + type: string + network_id: + type: string + addresses: + type: list + entry_schema: + type: string + tosca.datatypes.network.PortInfo: + derived_from: tosca.datatypes.Root + properties: + port_name: + type: string + port_id: + type: string + network_id: + type: string + mac_address: + type: string + addresses: + type: list + entry_schema: + type: string + # tosca.datatypes.network.PortDef: + # derived_from: integer + # constraints: + # - in_range: [ 1, 65535 ] + # tosca.datatypes.network.PortSpec: + # derived_from: tosca.datatypes.Root + # properties: + # protocol: + # type: string + # required: true + # default: tcp + # constraints: + # - valid_values: [ udp, tcp, igmp ] + # target: + # type: PortDef + # required: false + # target_range: + # type: range + # required: false + # constraints: + # - in_range: [ 1, 65535 ] + # source: + # type: PortDef + # required: false + # source_range: + # type: range + # required: false + # constraints: + # - in_range: [ 1, 65535 ]
\ No newline at end of file diff --git a/src/main/resources/clds/tosca-converter/templates.json b/src/main/resources/clds/tosca-converter/templates.json new file mode 100644 index 000000000..f709e2f6d --- /dev/null +++ b/src/main/resources/clds/tosca-converter/templates.json @@ -0,0 +1,398 @@ +{ + "integer":{ + "type":{ + "defaultValue":"integer", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "enum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "multipleOf":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maximum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "exclusiveMaximum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minimum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "exclusiveMinimum":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "number":{ + "type":{ + "defaultValue":"number", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "enum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "multipleOf":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maximum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "exclusiveMaximum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minimum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "exclusiveMinimum":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "boolean":{ + "type":{ + "defaultValue":"boolean", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "string":{ + "type":{ + "defaultValue":"string", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "enum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "length":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minLength":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maxLength":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "pattern":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "format":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "timestamp":{ + "type":{ + "defaultValue":"string", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "enum":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "length":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minLength":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maxLength":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "pattern":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "format":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "array":{ + "type":{ + "defaultValue":"array", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "deprecated":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "default":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "const":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "uniqueItems":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "properties":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minContains":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maxContains":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minItems":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maxItems":{ + "defaultValue":"", + "visible":true, + "static":false + } + }, + "object":{ + "type":{ + "defaultValue":"object", + "visible":true, + "static":false + }, + "description":{ + "defaultValue":"", + "visible":true, + "static":true + }, + "title":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "format":{ + "defaultValue":"tabs", + "visible":true, + "static":true + }, + "required":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "minProperties":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "maxProperties":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "properties":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "dependentRequired":{ + "defaultValue":"", + "visible":true, + "static":false + }, + "dependencies":{ + "defaultValue":"", + "visible":true, + "static":false + } + } +}
\ No newline at end of file diff --git a/src/main/resources/logback-default.xml b/src/main/resources/logback-default.xml new file mode 100644 index 000000000..e263a13fc --- /dev/null +++ b/src/main/resources/logback-default.xml @@ -0,0 +1,329 @@ +<included> + <jmxConfigurator /> + <!-- Example evaluator filter applied against console appender --> + <property + name="p_tim" + value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}" /> + <property + name="p_lvl" + value="%level" /> + <property + name="p_log" + value="%logger" /> + <property + name="p_mdc" + value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}" /> + <property + name="p_msg" + value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_exc" + value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_mak" + value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_thr" + value="%thread" /> + <property + name="defaultPattern" + value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n" /> + <property + name="debugPattern" + value="%nopexception${p_tim}|${p_lvl}|${p_mdc}|${p_exc}|%msg%n" /> + + <property + name="errorPattern" + value="%X{EntryTimestamp}|%X{RequestID}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}||||%msg%n" /> + + <property + name="auditPattern" + value="%X{EntryTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDesc}|%X{InstanceUUID}|%.-5level|%X{Severity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}||||%marker|%mdc|||%msg%n" /> + + <property + name="metricPattern" + value="%X{InvokeTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDesc}|%X{InstanceUUID}|%.-5level|%X{Severity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}||||%X{TargetVirtualEntity}|%marker|%mdc|||%msg%n" /> + + + <!-- Example evaluator filter applied against console appender --> + <appender + name="STDOUT" + class="ch.qos.logback.core.ConsoleAppender"> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + </pattern> + </encoder> + </appender> + + <appender + name="ERROR" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>ERROR</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>${logDirectory}/error.log</file> + <append>true</append> + <encoder> + <pattern>${errorPattern}</pattern> + </encoder> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/error.%d{yyyy-MM-dd}.%i.log.zip + </fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + </appender> + + <appender + name="DEBUG" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/debug.log</file> + <append>true</append> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + </pattern> + </encoder> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/debug.%d{yyyy-MM-dd}.%i.log.zip + </fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + </appender> + + + <appender + name="AUDIT" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>ENTRY</marker> + <marker>EXIT</marker> + </evaluator> + <onMismatch>DENY</onMismatch> + <onMatch>ACCEPT</onMatch> + </filter> + <file>${logDirectory}/audit.log</file> + <append>true</append> + <encoder> + <pattern>${auditPattern}</pattern> + </encoder> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <FileNamePattern>${logDirectory}/audit.%d{yyyy-MM-dd}.%i.log.zip + </FileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + </appender> + <appender + name="asyncEELFAudit" + class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="AUDIT" /> + </appender> + + <appender + name="METRIC" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>INVOKE</marker> + <marker>INVOKE-RETURN</marker> + </evaluator> + <onMismatch>DENY</onMismatch> + <onMatch>ACCEPT</onMatch> + </filter> + <file>${logDirectory}/metric.log</file> + <append>true</append> + <encoder> + <pattern>${metricPattern}</pattern> + </encoder> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <FileNamePattern>${logDirectory}/metric.%d{yyyy-MM-dd}.%i.log.zip + </FileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + </appender> + + <appender + name="asyncEELFMetrics" + class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="METRIC" /> + </appender> + + <!-- SECURITY related loggers --> + <appender + name="SECURITY" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/security.log</file> + <append>true</append> + <encoder> + <pattern>%X{EntryTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%.20thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n + </pattern> + </encoder> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <FileNamePattern>${logDirectory}/security.%d{yyyy-MM-dd}.%i.log.zip + </FileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + </appender> + + <appender + name="asyncEELFSecurity" + class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="SECURITY" /> + </appender> + <!-- logback jms appenders & loggers definition starts here --> + <appender + name="auditLogs" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + </filter> + <file>${logDirectory}/Audits.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/Audits-%d{yyyy-MM-dd}.%i.log.zip + </fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern> + </encoder> + </appender> + + <appender + name="perfLogs" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + </filter> + <file>${logDirectory}/Perform.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDirectory}/Perform--%d{yyyy-MM-dd}.%i.log.zip + </fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>20</maxHistory> + <totalSizeCap>1GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern> + </encoder> + </appender> + + <logger + name="org.onap.aaf" + level="DEBUG"> + <appender-ref ref="DEBUG" /> + </logger> + <logger + name="org.hibernate" + level="INFO"> + <appender-ref ref="DEBUG" /> + </logger> + <logger + name="org.apache.camel.Tracing" + level="INFO"> + <appender-ref ref="DEBUG" /> + </logger> + + <logger + name="org.apache" + level="INFO"> + <appender-ref ref="DEBUG" /> + </logger> + <!-- Spring related loggers --> + <logger + name="org.springframework" + level="INFO"> + <appender-ref ref="DEBUG" /> + </logger> + + <!-- CLAMP related loggers --> + <logger + name="org.onap.clamp" + level="DEBUG"> + <appender-ref ref="ERROR" /> + <appender-ref ref="DEBUG" /> + </logger> + + <logger + name="com.att.eelf.error" + level="OFF"> + <appender-ref ref="ERROR" /> + </logger> + <!-- EELF related loggers --> + <logger + name="com.att.eelf.audit" + level="INFO" + additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + <logger + name="com.att.eelf.metrics" + level="DEBUG" + additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + <logger + name="com.att.eelf.security" + level="DEBUG" + additivity="false"> + <appender-ref ref="asyncEELFSecurity" /> + </logger> + + <!-- logback internals logging --> + <logger + name="ch.qos.logback.classic" + level="INFO" /> + <logger + name="ch.qos.logback.core" + level="INFO" /> + <logger + name="AuditRecord" + level="INFO" + additivity="false"> + <appender-ref ref="auditLogs" /> + </logger> + <logger + name="AuditRecord_DirectCall" + level="INFO" + additivity="false"> + <appender-ref ref="auditLogs" /> + </logger> + <logger + name="PerfTrackerRecord" + level="INFO" + additivity="false"> + <appender-ref ref="perfLogs" /> + </logger> + <!-- logback jms appenders & loggers definition ends here --> + + <root level="DEBUG"> + <appender-ref ref="DEBUG" /> + <appender-ref ref="STDOUT" /> + <appender-ref ref="AUDIT" /> + <appender-ref ref="METRIC" /> + <appender-ref ref="ERROR" /> + </root> +</included> diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..ffa497f1d --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,19 @@ +<configuration debug="true"> + <springProperty name="logbackFilePath" + source="clamp.config.logback.path" /> + <springProperty name="logbackFileName" + source="clamp.config.logback.filename" /> + <springProperty name="logDirectory" + source="clamp.config.log.path" /> + + <if condition='isNull("logbackFilePath")'> + <then> + <!-- Classpath case --> + <include resource="${logbackFileName}" /> + </then> + <else> + <!-- File system case --> + <include file="${logbackFilePath}/${logbackFileName}" /> + </else> + </if> +</configuration>
\ No newline at end of file diff --git a/src/main/resources/logmessages.properties b/src/main/resources/logmessages.properties new file mode 100644 index 000000000..fc9f74a36 --- /dev/null +++ b/src/main/resources/logmessages.properties @@ -0,0 +1,27 @@ +### +# ============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============================================ +# =================================================================== +# +### + +LOGSERVICE_EMAIL_ERROR=SERVICE0007I|Exception while sending e-mail:{0}|Resolution needed|action is required +LOGSERVICE_EMAIL_CLASS=SERVICE0008I|classUrl.getFile:{0}|Resolution needed|action is required +LOGSERVICE_EMAIL_CLASS_NULL=SERVICE0009I|classUrl is NULL|Resolution needed|action is required +PROCESS_INSTANCE_ID=SERVICE0010I|Process Instance Id:{0}|No resolution needed|No action is required diff --git a/src/main/resources/system.properties b/src/main/resources/system.properties new file mode 100644 index 000000000..f95fc7009 --- /dev/null +++ b/src/main/resources/system.properties @@ -0,0 +1,27 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-2018 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============================================ +# =================================================================== +# +### Static JVM parameters can be set here by the dev team +### These will be loaded at Clamp startup +# +# JVM SSL/TLS properties +jdk.tls.client.protocols=TLSv1.1,TLSv1.2 +https.protocols=TLSv1.1,TLSv1.2 diff --git a/src/main/script/SelectNpmRepo.groovy b/src/main/script/SelectNpmRepo.groovy new file mode 100644 index 000000000..92371cfe9 --- /dev/null +++ b/src/main/script/SelectNpmRepo.groovy @@ -0,0 +1,34 @@ +/*- + * ============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.clds.maven.scripts + +println project.properties['clamp.project.version']; + +if ( project.properties['clamp.project.version'].endsWith("-SNAPSHOT") ) { + project.properties['npm.publish.url']="https://nexus3.onap.org/repository/npm.snapshot/" +} else { + project.properties['npm.publish.url']="https://nexus3.onap.org/repository/npm.snapshot/" +} + +println 'NPM repository: ' + project.properties['npm.publish.url']; diff --git a/src/main/script/TagVersion.groovy b/src/main/script/TagVersion.groovy new file mode 100644 index 000000000..ccfcca3c4 --- /dev/null +++ b/src/main/script/TagVersion.groovy @@ -0,0 +1,40 @@ +/*- + * ============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.clds.maven.scripts + +println project.properties['clamp.project.version']; +def versionArray; +if ( project.properties['clamp.project.version'] != null ) { + versionArray = project.properties['clamp.project.version'].split('\\.'); +} + +if ( project.properties['clamp.project.version'].endsWith("-SNAPSHOT") ) { + project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-latest"; + project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-"+project.properties['clamp.build.timestamp']; +} else { + project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-latest"; + project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-"+project.properties['clamp.build.timestamp']; +} + +println 'New Tag for docker:' + project.properties['project.docker.latesttag.version'];
\ No newline at end of file diff --git a/src/main/script/checkLibIndex.sh b/src/main/script/checkLibIndex.sh new file mode 100755 index 000000000..9a28e7df9 --- /dev/null +++ b/src/main/script/checkLibIndex.sh @@ -0,0 +1,122 @@ +#!/bin/bash +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2020 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============================================ +# =================================================================== +# +### + +baseDir=$(git rev-parse --show-toplevel) + +if [[ ! -d $baseDir ]] +then + echo "[ERROR] failed to determine git base directory" + exit 1 +fi + +tmpSrcFileList=/tmp/upldateLibIndex.$$.list +reactUiBaseDir="${baseDir}/ui-react" +reactLibIndexFile="ui-react-lib/libIndex.js" +exclusionList="ui-react-lib/libExportExclusions.dat" + + +if [[ ! -d "$reactUiBaseDir" ]] +then + echo "[ERROR] reacUiBaseDir=$reacUiBaseDir is not accessible" + exit 1 +fi + +if [[ ! -d "$baseDir/$reactLibBaseDir" ]] +then + echo "[ERROR] reactLibBaseDir=$baseDir/$reactLibBaseDir is not accessible" + exit 1 +fi + +if [[ ! -r "$baseDir/$reactLibIndexFile" ]] +then + echo "[ERROR] file reactLibIndexFile=$baseDir/$reactLibIndexFile is not accessible" + exit 1 +fi + + +if ! cd $reactUiBaseDir +then + echo "[ERROR] could not cd to reactUiBaseDir=$reactUiBaseDir" + exit 1 +fi + +find ./src -name \*.js | egrep -v "__snapshot|\.test\." 2>/dev/null | sed 's/.js$//' > $tmpSrcFileList + +if [[ ! -s $tmpSrcFileList ]] +then + echo "[ERROR] no source files found in reactUiBaseDir=$reactUiBaseDir" + rm -f $tmpSrcFileList + exit 1 +fi + +export nErrors=0 + +# Verify that any .js file found within ui-react/src other than test related files +# is also referenced in ui-react-lib/libIndex.js + +for srcFileName in `<$tmpSrcFileList` +do + if [[ -r "$baseDir/$exclusionList" ]] + then + if grep $srcFileName $baseDir/$exclusionList >/dev/null 2>&1 + then + continue + fi + fi + + if ! grep $srcFileName "$baseDir/$reactLibIndexFile" > /dev/null 2>&1 + then + echo "[ERROR] file=${srcFileName}.js is not declared in $reactLibIndexFile" + echo "[ERROR] and not found in exclsionList=${exclusionList}." + echo "[ERROR] Please either add it to $reactLibIndexFile" + echo "[ERROR] or to the exclusion list in ${exclusionList}." + echo "" + (( nErrors++ )) + fi +done + +# Verify for each entry in ui-react-lib/libIndex.js, that the referenced source file exists +# in ui-react/src; if not, developer probably forgot to remove it from libIndex.js. + +egrep '^export ' $baseDir/$reactLibIndexFile |\ +sed -e "s+.*\./src+./src+" -e "s+'.*+.js+" > $tmpSrcFileList + +for srcFileName in `<$tmpSrcFileList` +do + if [[ ! -r "$srcFileName" ]] + then + echo "[ERROR] source file=$srcFileName in libIndex.js is not accessible" + (( nErrors++ )) + fi +done + +rm -f $tmpSrcFileList + +if (( nErrors == 0 )) +then + echo "[INFO] $reactLibIndexFile passes sanity check" + exit 0 +fi + +exit $nErrors diff --git a/src/test/java/org/onap/clamp/clds/client/CdsServicesTest.java b/src/test/java/org/onap/clamp/clds/client/CdsServicesTest.java new file mode 100644 index 000000000..3d189cf71 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/client/CdsServicesTest.java @@ -0,0 +1,56 @@ +/*- + * ============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.google.gson.JsonObject; +import java.io.IOException; +import org.junit.Test; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.skyscreamer.jsonassert.JSONAssert; + +public class CdsServicesTest { + + @Test + public void testParseCdsListTypeProperties() throws IOException { + String cdsResponse = ResourceFileUtils + .getResourceAsString("example/cds-response/vFW-CDS-resource-assignment-workflow.json"); + CdsServices services = new CdsServices(); + JsonObject output = services.parseCdsResponse(cdsResponse); + JSONAssert.assertEquals(ResourceFileUtils + .getResourceAsString("example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json"), + JsonUtils.GSON.toJson(output), true); + } + + @Test + public void testParseCdsResponse() throws IOException { + String cdsResponse = ResourceFileUtils + .getResourceAsString("example/cds-response/vFW-CDS-modify-config-workflow.json"); + CdsServices services = new CdsServices(); + JsonObject output = services.parseCdsResponse(cdsResponse); + JSONAssert.assertEquals(ResourceFileUtils + .getResourceAsString("example/cds-response/vFW-CDS-modify-config-wf-expected-result.json"), + JsonUtils.GSON.toJson(output), true); + } + +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java b/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java new file mode 100644 index 000000000..7152ee11d --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/config/CldsUserJsonDecoderTest.java @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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============================================ + * Modifications copyright (c) 2018 Nokia + * =================================================================== + * + */ + +package org.onap.clamp.clds.config; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.onap.clamp.authorization.CldsUser; +import org.onap.clamp.clds.exception.CldsUsersException; + +public class CldsUserJsonDecoderTest { + + private String user1 = "admin1"; + private String user2 = "admin2"; + private String password = "5f4dcc3b5aa765d61d8327deb882cf99"; + private String[] normalPermissionsArray = { "permission-type-cl|dev|read", "permission-type-cl|dev|update", + "permission-type-cl-manage|dev|*", "permission-type-filter-vf|dev|*", "permission-type-template|dev|read", + "permission-type-template|dev|update" }; + private String[] incompletePermissionsArray = { "permission-type-cl|dev|*", "permission-type-cl|dev|*", + "permission-type-cl-manage|dev|*", "permission-type-filter-vf|dev|*", "permission-type-template|dev|read", + "permission-type-template|dev|update" }; + + @Test + public void testDecodingDoubleUsers() { + + // when + CldsUser[] usersArray = CldsUserJsonDecoder + .decodeJson(CldsUserJsonDecoderTest.class.getResourceAsStream("/clds/clds-users-two-users.json")); + + // then + assertThat(usersArray).hasSize(2); + assertThat(usersArray[0]).extracting(CldsUser::getUser, CldsUser::getPassword, CldsUser::getPermissionsString) + .containsExactly(user1, password, normalPermissionsArray); + + assertThat(usersArray[1]).extracting(CldsUser::getUser, CldsUser::getPassword, CldsUser::getPermissionsString) + .containsExactly(user2, password, normalPermissionsArray); + + } + + @Test + public void testDecodingNoPermission() { + // when + CldsUser[] usersArray = CldsUserJsonDecoder + .decodeJson(this.getClass().getResourceAsStream("/clds/clds-users-no-permission.json")); + + // then + assertThat(usersArray).hasSize(1); + CldsUser user = usersArray[0]; + assertThat(user.getUser()).isEqualTo(user1); + assertThat(user.getPassword()).isEqualTo(null); + assertThat(user.getPermissionsString()).isEmpty(); + } + + @Test + public void testDecodingIncompletePermissions() { + + // when + CldsUser[] usersArray = CldsUserJsonDecoder + .decodeJson(this.getClass().getResourceAsStream("/clds/clds-users-incomplete-permissions.json")); + + // then + assertThat(usersArray).hasSize(1); + CldsUser user = usersArray[0]; + assertThat(user.getUser()).isEqualTo(user1); + assertThat(user.getPassword()).isEqualTo(password); + assertThat(user.getPermissionsString()).isEqualTo(incompletePermissionsArray); + } + + @Test(expected = CldsUsersException.class) + public void shouldThrowCldsUsersException() { + // when + CldsUserJsonDecoder.decodeJson(this.getClass().getResourceAsStream("/clds/clds-parse-exception.json")); + } + +} diff --git a/src/test/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java b/src/test/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java new file mode 100644 index 000000000..06df124ce --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java @@ -0,0 +1,105 @@ +/*- + * ============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========================================================= + * Modifications copyright (c) 2018 Nokia + * ================================================================================ + * + */ + +package org.onap.clamp.clds.config.sdc; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import org.junit.Test; +import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; + +/** + * This class tests the SDC Controller config. + */ +public class SdcSingleControllerConfigurationTest { + + /** + * @param fileName file for sdc controller configuration. + * @param sdcControllerName sdc controller name. + * @return instance of SdcSingleControllerConfiguration. + */ + public static SdcSingleControllerConfiguration loadControllerConfiguration(String fileName, + String sdcControllerName) { + + InputStreamReader streamReader = new InputStreamReader(ResourceFileUtils.getResourceAsStream(fileName), + StandardCharsets.UTF_8); + JsonObject jsonNode = JsonUtils.GSON.fromJson(streamReader, JsonObject.class); + + return new SdcSingleControllerConfiguration(jsonNode, sdcControllerName); + } + + @Test + public final void testTheInit() throws SdcParametersException, IOException { + SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-TLS.json", + "sdc-controller1"); + assertEquals("User", sdcConfig.getUser()); + assertEquals("ThePassword", sdcConfig.getPassword()); + assertEquals("consumerGroup", sdcConfig.getConsumerGroup()); + assertEquals("consumerId", sdcConfig.getConsumerID()); + assertEquals("environmentName", sdcConfig.getEnvironmentName()); + assertEquals("hostname:8080", sdcConfig.getAsdcAddress()); + assertEquals(10, sdcConfig.getPollingInterval()); + assertEquals(30, sdcConfig.getPollingTimeout()); + + assertThat(SdcSingleControllerConfiguration.SUPPORTED_ARTIFACT_TYPES_LIST) + .hasSameSizeAs(sdcConfig.getRelevantArtifactTypes()); + assertEquals("ThePassword", sdcConfig.getKeyStorePassword()); + assertTrue(sdcConfig.activateServerTLSAuth()); + assertThat(sdcConfig.getMsgBusAddress()).contains("localhost"); + } + + @Test(expected = SdcParametersException.class) + public final void testAllRequiredParameters() throws IOException { + SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-TLS.json", + "sdc-controller1"); + // No exception should be raised + sdcConfig.testAllRequiredParameters(); + sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-bad.json", "sdc-controller1"); + fail("Should have raised an exception"); + } + + @Test + public final void testAllRequiredParametersEmptyEncrypted() throws IOException { + SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration( + "clds/sdc-controller-config-empty-encrypted.json", "sdc-controller1"); + sdcConfig.testAllRequiredParameters(); + assertNull(sdcConfig.getKeyStorePassword()); + } + + @Test + public final void testConsumerGroupWithNull() throws IOException { + SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-NULL.json", + "sdc-controller1"); + assertTrue(sdcConfig.getConsumerGroup() == null); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java b/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java new file mode 100644 index 000000000..207e93684 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/AuthorizationControllerItCase.java @@ -0,0 +1,137 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * Modifications Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import org.apache.camel.Exchange; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.clamp.authorization.AuthorizationController; +import org.onap.clamp.authorization.SecureServicePermission; +import org.onap.clamp.clds.exception.NotAuthorizedException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Test CldsDAO calls through CldsModel and CldsEvent. This really test the DB + * and stored procedures. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class AuthorizationControllerItCase { + + @Autowired + private AuthorizationController auth; + + private static SecurityContext sc = SecurityContextHolder.getContext(); + + /** + * Setup the variable before the tests execution. + */ + @BeforeClass + public static void setupBefore() { + + sc.setAuthentication(new Authentication() { + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return Arrays.asList(new SimpleGrantedAuthority( + new SecureServicePermission("permission-type-cl", "dev", "read").getKey()), + new SimpleGrantedAuthority(new SecureServicePermission("permission-type-cl-manage", "dev", + "DEPLOY").getKey()), + new SimpleGrantedAuthority(new SecureServicePermission("permission-type-filter-vf", "dev", + "12345-55555-55555-5555").getKey())); + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public Object getPrincipal() { + return "admin"; + } + + @Override + public boolean isAuthenticated() { + return true; + } + + @Override + public void setAuthenticated(boolean authenticatedFlag) throws IllegalArgumentException { + + } + + @Override + public String getName() { + return "admin"; + } + }); + + } + + @AfterClass + + public static void afterCleanup() { + sc.setAuthentication(null); + } + + @Test + public void testIsUserPermitted() { + assertEquals(AuthorizationController.getPrincipalName(sc),"admin"); + assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "dev", "read"))); + assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl-manage", "dev", "DEPLOY"))); + assertTrue(auth.isUserPermitted( + new SecureServicePermission("permission-type-filter-vf", "dev", "12345-55555-55555-5555"))); + assertFalse(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "test", "read"))); + } + + @Test(expected = NotAuthorizedException.class) + public void testIfAuthorizeThrowException() { + Exchange ex = Mockito.mock(Exchange.class); + auth.authorize(ex, "cl", "test", "read"); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/CldsHealthcheckServiceItCase.java b/src/test/java/org/onap/clamp/clds/it/CldsHealthcheckServiceItCase.java new file mode 100644 index 000000000..587b7c915 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/CldsHealthcheckServiceItCase.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.model.CldsHealthCheck; +import org.onap.clamp.clds.service.CldsHealthcheckService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Tests HealthCheck Service. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class CldsHealthcheckServiceItCase { + + @Autowired + private CldsHealthcheckService cldsHealthcheckService; + + @Test + public void testGetHealthCheck() { + CldsHealthCheck cldsHealthCheck = cldsHealthcheckService.gethealthcheck(); + assertNotNull(cldsHealthCheck); + assertEquals("UP", cldsHealthCheck.getHealthCheckStatus()); + assertEquals("CLDS-APP", cldsHealthCheck.getHealthCheckComponent()); + assertEquals("OK", cldsHealthCheck.getDescription()); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/HttpsItCase.java b/src/test/java/org/onap/clamp/clds/it/HttpsItCase.java new file mode 100644 index 000000000..90a240181 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/HttpsItCase.java @@ -0,0 +1,159 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.it; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.nio.charset.Charset; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.io.FileUtils; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; + +/** + * Test HTTP and HTTPS settings + redirection of HTTP to HTTPS. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) +@TestPropertySource(locations = "classpath:https/https-test.properties") +@DirtiesContext +public class HttpsItCase { + + @Value("${server.port}") + private String httpsPort; + @Value("${server.http-to-https-redirection.port}") + private String httpPort; + + /** + * Setup the variable before tests execution. + */ + @BeforeClass + public static void setUp() { + try { + // setup ssl context to ignore certificate errors + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws java.security.cert.CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws java.security.cert.CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLContext.setDefault(ctx); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Test + public void testDesignerIndex() throws Exception { + RestTemplate template = new RestTemplate(); + final MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(new HostnameVerifier() { + + @Override + public boolean verify(final String hostname, final SSLSession session) { + return true; + } + }); + template.setRequestFactory(factory); + ResponseEntity<String> entity = template.getForEntity("http://localhost:" + this.httpPort + "/swagger.html", + String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND); + ResponseEntity<String> httpsEntity = template + .getForEntity("https://localhost:" + this.httpsPort + "/swagger.html", String.class); + assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(httpsEntity.getBody()).contains("Clamp Rest API"); + } + + @Test + public void testSwaggerJson() throws Exception { + RestTemplate template = new RestTemplate(); + final MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(new HostnameVerifier() { + + @Override + public boolean verify(final String hostname, final SSLSession session) { + return true; + } + }); + template.setRequestFactory(factory); + ResponseEntity<String> httpsEntity = template + .getForEntity("https://localhost:" + this.httpsPort + "/restservices/clds/api-doc", String.class); + assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(httpsEntity.getBody()).contains("swagger"); + FileUtils.writeStringToFile(new File("docs/swagger/swagger.json"), httpsEntity.getBody(), + Charset.defaultCharset()); + } + + /** + * Http Request Factory for ignoring SSL hostname errors. Not for production + * use! + */ + class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory { + + private final HostnameVerifier verifier; + + public MySimpleClientHttpRequestFactory(final HostnameVerifier verifier) { + this.verifier = verifier; + } + + @Override + protected void prepareConnection(final HttpURLConnection connection, final String httpMethod) + throws IOException { + if (connection instanceof HttpsURLConnection) { + ((HttpsURLConnection) connection).setHostnameVerifier(this.verifier); + } + super.prepareConnection(connection, httpMethod); + } + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/RobotItCase.java b/src/test/java/org/onap/clamp/clds/it/RobotItCase.java new file mode 100644 index 000000000..5eff96e44 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/RobotItCase.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.it; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.BuildImageResultCallback; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.command.LogContainerCmd; +import com.github.dockerjava.api.model.AccessMode; +import com.github.dockerjava.api.model.Bind; +import com.github.dockerjava.api.model.BuildResponseItem; +import com.github.dockerjava.api.model.Frame; +import com.github.dockerjava.api.model.Volume; +import com.github.dockerjava.core.DockerClientBuilder; +import com.github.dockerjava.core.command.LogContainerResultCallback; +import com.github.dockerjava.netty.NettyDockerCmdExecFactory; +import java.io.File; +import java.util.Objects; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@TestPropertySource(locations = "classpath:robotframework/robotframework-test.properties") +@DirtiesContext +public class RobotItCase { + + @Value("${server.port}") + private String httpPort; + private static final int TIMEOUT_S = 150; + protected static final EELFLogger logger = EELFManager.getInstance().getLogger(RobotItCase.class); + + @Test + public void robotTests() throws Exception { + File robotFolder = new File(getClass().getClassLoader().getResource("robotframework").getFile()); + Volume testsVolume = new Volume("/opt/robotframework/tests"); + DockerClient client = DockerClientBuilder + .getInstance() + .withDockerCmdExecFactory(new NettyDockerCmdExecFactory()) + .build(); + + + BuildImageResultCallback callback = new BuildImageResultCallback() { + @Override + public void onNext(BuildResponseItem item) { + System.out.println("XXX ITEM " + item); + super.onNext(item); + } + }; + + String imageId = client.buildImageCmd(robotFolder).exec(callback).awaitImageId(); + CreateContainerResponse createContainerResponse = client.createContainerCmd(imageId) + .withVolumes(testsVolume) + .withBinds( + new Bind(robotFolder.getAbsolutePath() + "/tests/", testsVolume, AccessMode.rw)) + .withEnv("CLAMP_PORT=" + httpPort) + .withStopTimeout(TIMEOUT_S) + .withNetworkMode("host") + .exec(); + String id = createContainerResponse.getId(); + client.startContainerCmd(id).exec(); + InspectContainerResponse exec; + + int tries = 0; + do { + Thread.sleep(1000); + exec = client.inspectContainerCmd(id).exec(); + tries++; + } while (exec.getState().getRunning() && tries < TIMEOUT_S); + Assert.assertEquals(exec.getState().getError(), 0L, + Objects.requireNonNull(exec.getState().getExitCodeLong()).longValue()); + LogContainerCmd logContainerCmd = client.logContainerCmd(id); + logContainerCmd.withStdOut(true).withStdErr(true); + try { + logContainerCmd.exec(new LogContainerResultCallback() { + @Override + public void onNext(Frame item) { + logger.info(item.toString()); + } + }).awaitCompletion(); + } catch (InterruptedException e) { + throw new Exception("Failed to retrieve logs of container " + id, e); + } + client.stopContainerCmd(id); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/config/CldsReferencePropertiesItCase.java b/src/test/java/org/onap/clamp/clds/it/config/CldsReferencePropertiesItCase.java new file mode 100644 index 000000000..c4c0c345a --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/config/CldsReferencePropertiesItCase.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 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.clds.it.config; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Test corg.onap.clamp.ClampDesigner.model.refprop package using RefProp. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class CldsReferencePropertiesItCase { + + @Autowired + private ClampProperties refProp; + + /** + * Test getting a value the properties in string. + */ + @Test + public void testGetStringValue() { + assertEquals("healthcheck", refProp.getStringValue("policy.api.userName")); + } + + /** + * Test getting prop value as a JSON Node / template. + * + * @throws IOException when JSON parsing fails + */ + @Test + public void testGetFileContent() throws IOException { + String users = ResourceFileUtils.getResourceAsString("clds/clds-users.json"); + assertEquals(users, refProp.getFileContent("files.cldsUsers")); + // Test composite key + assertEquals(users, refProp.getFileContent("files", "cldsUsers")); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/config/SdcControllersConfigurationItCase.java b/src/test/java/org/onap/clamp/clds/it/config/SdcControllersConfigurationItCase.java new file mode 100644 index 000000000..0c08a2e36 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/config/SdcControllersConfigurationItCase.java @@ -0,0 +1,90 @@ +/*- + * ============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.clds.it.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.gson.JsonSyntaxException; + +import java.io.IOException; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.config.sdc.SdcControllersConfiguration; +import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration; +import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * This class tests the SDC Controller config. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({"clamp-default","clamp-default-user","clamp-sdc-controller"}) +public class SdcControllersConfigurationItCase { + + @Autowired + private SdcControllersConfiguration sdcControllersConfiguration; + + public final void loadFile(String fileName) throws IOException { + ReflectionTestUtils.setField(sdcControllersConfiguration, "sdcControllerFile", fileName); + sdcControllersConfiguration.loadConfiguration(); + } + + @Test + public void testGetAllDefinedControllers() throws IOException { + loadFile("classpath:/clds/sdc-controllers-config.json"); + Map<String, SdcSingleControllerConfiguration> mapResult = sdcControllersConfiguration + .getAllDefinedControllers(); + assertTrue(mapResult.size() == 2); + assertEquals("sdc-controller1", mapResult.get("sdc-controller1").getSdcControllerName()); + assertEquals("sdc-controller2", mapResult.get("sdc-controller2").getSdcControllerName()); + } + + @Test + public void testGetSdcSingleControllerConfiguration() throws IOException { + loadFile("classpath:/clds/sdc-controllers-config.json"); + assertEquals("sdc-controller1", sdcControllersConfiguration + .getSdcSingleControllerConfiguration("sdc-controller1").getSdcControllerName()); + assertEquals("sdc-controller2", sdcControllersConfiguration + .getSdcSingleControllerConfiguration("sdc-controller2").getSdcControllerName()); + } + + @Test(expected = JsonSyntaxException.class) + public void testBadJsonLoading() throws IOException { + loadFile("classpath:/clds/sdc-controllers-config-bad.json"); + fail("Should have raised an exception"); + } + + @Test(expected = SdcParametersException.class) + public void testMissingParamInJsonLoading() throws IOException { + loadFile("classpath:/clds/sdc-controllers-config-missing-param.json"); + sdcControllersConfiguration.getAllDefinedControllers(); + fail("Should have raised an exception"); + } +} diff --git a/src/test/java/org/onap/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java b/src/test/java/org/onap/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java new file mode 100644 index 000000000..a8c3e58d4 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java @@ -0,0 +1,153 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.it.sdc.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.assertj.core.api.Assertions; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.clamp.clds.config.ClampProperties; +import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfigurationTest; +import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException; +import org.onap.clamp.clds.sdc.controller.SdcSingleController; +import org.onap.clamp.clds.sdc.controller.SdcSingleControllerStatus; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.loop.CsarInstaller; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.notification.IResourceInstance; +import org.slf4j.MDC; +import org.slf4j.spi.MDCAdapter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({"clamp-default","clamp-default-user","clamp-sdc-controller"}) +public class SdcSingleControllerItCase { + + private static final String CSAR_ARTIFACT_NAME = "testArtifact.csar"; + private static final String SERVICE_UUID = "serviceUUID"; + private static final String RESOURCE1_UUID = "resource1UUID"; + private static final String RESOURCE1_INSTANCE_NAME = "sim-1802 0"; + + @Autowired + private ClampProperties clampProp; + + private SdcSingleController sdcSingleController; + + private CsarInstaller csarInstaller = mock(CsarInstaller.class); + + private INotificationData buildFakeSdcNotification() { + // BUild what is needed for CSAR + IArtifactInfo serviceArtifact = mock(IArtifactInfo.class); + Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE); + Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME); + List<IArtifactInfo> servicesList = new ArrayList<>(); + servicesList.add(serviceArtifact); + INotificationData notifData = mock(INotificationData.class); + Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList); + // Build what is needed for UUID + Mockito.when(notifData.getServiceInvariantUUID()).thenReturn(SERVICE_UUID); + // Build fake resource with one artifact BLUEPRINT + IResourceInstance resource1 = mock(IResourceInstance.class); + Mockito.when(resource1.getResourceType()).thenReturn("VF"); + Mockito.when(resource1.getResourceInvariantUUID()).thenReturn(RESOURCE1_UUID); + Mockito.when(resource1.getResourceInstanceName()).thenReturn(RESOURCE1_INSTANCE_NAME); + // Create a fake artifact for resource + IArtifactInfo blueprintArtifact = mock(IArtifactInfo.class); + Mockito.when(blueprintArtifact.getArtifactType()).thenReturn(CsarHandler.BLUEPRINT_TYPE); + List<IArtifactInfo> artifactsListForResource = new ArrayList<>(); + artifactsListForResource.add(blueprintArtifact); + Mockito.when(resource1.getArtifacts()).thenReturn(artifactsListForResource); + List<IResourceInstance> resourcesList = new ArrayList<>(); + resourcesList.add(resource1); + Mockito.when(notifData.getResources()).thenReturn(resourcesList); + return notifData; + } + + /** + * Initialization method. + */ + @Before + public void init() { + sdcSingleController = new SdcSingleController(clampProp, csarInstaller, SdcSingleControllerConfigurationTest + .loadControllerConfiguration("clds/sdc-controller-config-TLS.json", "sdc-controller1"), null) { + }; + } + + @Test + public void testTreatNotification() { + // when + sdcSingleController.treatNotification(buildFakeSdcNotification()); + // then + Assertions.assertThat(sdcSingleController.getNbOfNotificationsOngoing()).isEqualTo(0); + } + + @Test + public void testCloseSdc() throws SdcControllerException { + // when + sdcSingleController.closeSdc(); + // then + assertThat(sdcSingleController.getControllerStatus()).isEqualTo(SdcSingleControllerStatus.STOPPED); + } + + @Test + public void testActivateCallback() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, + InstantiationException, ClassNotFoundException { + // given + + Class<?> innerClass = Class + .forName("org.onap.clamp.clds.sdc.controller.SdcSingleController$SdcNotificationCallBack"); + Constructor<?> constructor = innerClass.getDeclaredConstructor(SdcSingleController.class, + SdcSingleController.class); + constructor.setAccessible(true); + Object child = constructor.newInstance(sdcSingleController, sdcSingleController); + Method method = child.getClass().getDeclaredMethod("activateCallback", INotificationData.class); + method.setAccessible(true); + MDCAdapter mdcAdapter = MDC.getMDCAdapter(); + // when + method.invoke(child, buildFakeSdcNotification()); + // then + assertThat(mdcAdapter.get("ResponseCode")).isEqualTo("0"); + assertThat(mdcAdapter.get("StatusCode")).isEqualTo("COMPLETE"); + assertThat(mdcAdapter.get("ResponseDescription")) + .isEqualTo("SDC Notification received and processed successfully"); + assertThat(mdcAdapter.get("ClassName")).isEqualTo(child.getClass().getName()); + } +} diff --git a/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java b/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java new file mode 100644 index 000000000..50da40049 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java @@ -0,0 +1,126 @@ +/*- + * ============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.clds.model.dcae; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.builder.ExchangeBuilder; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class DcaeInventoryResponseCacheTestItCase { + + public static DcaeInventoryCache inventoryCache = new DcaeInventoryCache(); + + @Autowired + CamelContext camelContext; + + /** + * Initialize the responses. + */ + @BeforeClass + public static void createExample() { + DcaeInventoryResponse response1 = new DcaeInventoryResponse(); + response1.setAsdcServiceId("id1"); + response1.setAsdcResourceId("0"); + DcaeInventoryResponse response2 = new DcaeInventoryResponse(); + response2.setAsdcServiceId("id1"); + response2.setAsdcResourceId("1"); + DcaeInventoryResponse response3 = new DcaeInventoryResponse(); + response3.setAsdcServiceId("id1"); + response3.setAsdcResourceId("2"); + DcaeInventoryResponse response4 = new DcaeInventoryResponse(); + response4.setAsdcServiceId("id2"); + response4.setAsdcResourceId("0"); + DcaeInventoryResponse response5 = new DcaeInventoryResponse(); + response5.setAsdcServiceId("id2"); + response5.setAsdcResourceId("1"); + + inventoryCache.addDcaeInventoryResponse(response1); + inventoryCache.addDcaeInventoryResponse(response3); + inventoryCache.addDcaeInventoryResponse(response2); + inventoryCache.addDcaeInventoryResponse(response4); + inventoryCache.addDcaeInventoryResponse(response5); + } + + @Test + public void testGetAllLoopIds() { + assertThat(inventoryCache.getAllLoopIds().size()).isEqualTo(2); + } + + @Test + public void testGetAllBlueprintsPerLoopId() { + int value = 0; + for (DcaeInventoryResponse inventoryResponse : inventoryCache.getAllBlueprintsPerLoopId("id1")) { + assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId())).isEqualTo(value++); + } + + value = 0; + for (DcaeInventoryResponse inventoryResponse : inventoryCache.getAllBlueprintsPerLoopId("id2")) { + assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId())).isEqualTo(value++); + } + } + + @Test + public void testDcaeInventoryResponse() { + Exchange exchange = ExchangeBuilder.anExchange(camelContext).build(); + Exchange exchangeResponse = camelContext.createProducerTemplate() + .send("direct:get-all-dcae-blueprint-inventory", exchange); + assertThat(exchangeResponse.getIn().getHeader("CamelHttpResponseCode")).isEqualTo(200); + Set<DcaeInventoryResponse> blueprint = inventoryCache.getAllBlueprintsPerLoopId("testAsdcServiceId"); + assertThat(blueprint.size()).isEqualTo(2); + + DcaeInventoryResponse response1 = new DcaeInventoryResponse(); + response1.setAsdcResourceId("0"); + response1.setTypeName("testTypeName"); + response1.setAsdcServiceId("testAsdcServiceId"); + response1.setBlueprintTemplate("testBlueprintTemplate"); + response1.setTypeId("testtypeId"); + DcaeInventoryResponse response2 = new DcaeInventoryResponse(); + response2.setAsdcResourceId("1"); + response2.setTypeName("testTypeName2"); + response2.setAsdcServiceId("testAsdcServiceId"); + response2.setBlueprintTemplate("testBlueprintTemplate2"); + response2.setTypeId("testtypeId2"); + + Set<DcaeInventoryResponse> expectedBlueprint = new HashSet<>(); + expectedBlueprint.add(response1); + expectedBlueprint.add(response2); + + assertEquals(blueprint, expectedBlueprint); + } +} diff --git a/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseTest.java b/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseTest.java new file mode 100644 index 000000000..fc4872c3b --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/model/dcae/DcaeInventoryResponseTest.java @@ -0,0 +1,60 @@ +/*- + * ============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.clds.model.dcae; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.TreeSet; + +import org.junit.Test; + +public class DcaeInventoryResponseTest { + + @Test + public void testComparator() { + DcaeInventoryResponse response1 = new DcaeInventoryResponse(); + response1.setAsdcServiceId("id1"); + response1.setAsdcResourceId("0"); + DcaeInventoryResponse response2 = new DcaeInventoryResponse(); + response2.setAsdcServiceId("id2"); + response2.setAsdcResourceId("1"); + DcaeInventoryResponse response3 = new DcaeInventoryResponse(); + response3.setAsdcServiceId("id3"); + response3.setAsdcResourceId("2"); + DcaeInventoryResponse response4 = new DcaeInventoryResponse(); + response4.setAsdcServiceId("id4"); + response4.setAsdcResourceId("3"); + + TreeSet<DcaeInventoryResponse> responseSet = new TreeSet<>(); + responseSet.add(response4); + responseSet.add(response3); + responseSet.add(response1); + responseSet.add(response2); + + int value = 0; + for (DcaeInventoryResponse inventoryResponse : responseSet) { + assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId()) == value++).isTrue(); + } + } +} diff --git a/src/test/java/org/onap/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java b/src/test/java/org/onap/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java new file mode 100644 index 000000000..560f54cf4 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Samsung. 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.clds.model.jsontype; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; + +import org.hibernate.HibernateException; +import org.junit.Test; +import org.onap.clamp.dao.model.jsontype.JsonTypeDescriptor; + +public class JsonTypeDescriptorTest { + + private JsonTypeDescriptor descriptor = new JsonTypeDescriptor(); + + @Test + public void testFromString() { + JsonObject object = new JsonObject(); + object.addProperty("one","oneValue"); + JsonObject child = new JsonObject(); + child.addProperty("two","twoValue"); + object.add("child",child); + + JsonObject jsonResult = descriptor.fromString("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}"); + + assertThat(jsonResult).isEqualTo(object); + } + + @Test + public void testUnwrap() { + JsonObject res1 = descriptor.unwrap(null, null, null); + assertThat(res1).isNull(); + + JsonObject object = new JsonObject(); + object.addProperty("one","oneValue"); + JsonObject child = new JsonObject(); + child.addProperty("two","twoValue"); + object.add("child",child); + String res2 = descriptor.unwrap(object, String.class, null); + assertThat(res2.replace("\n", "").replace(" ", "")) + .isEqualTo("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}"); + + Object res3 = descriptor.unwrap(object, JsonObject.class, null); + String res3Str = ((String) res3).replace(" ", "").replace("\\n", "").replace("\\", "") + .replace("\"{", "{").replace("}\"", "}"); + assertThat(res3Str).isEqualTo("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}"); + } + + @Test(expected = HibernateException.class) + public void testUnwrapExpectationThrown() { + JsonObject object = new JsonObject(); + object.addProperty("one","oneValue"); + + descriptor.unwrap(object, Integer.class, null); + } + + @Test + public void testWrap() { + JsonObject res1 = descriptor.wrap(null, null); + assertThat(res1).isNull(); + + JsonObject object = new JsonObject(); + object.addProperty("one","oneValue"); + JsonObject child = new JsonObject(); + child.addProperty("two","twoValue"); + object.add("child",child); + JsonObject res2 = descriptor.wrap("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}", null); + assertThat(res2).isEqualTo(object); + } + + @Test(expected = HibernateException.class) + public void testWrapExpectationThrown() { + descriptor.wrap(1, null); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParserTest.java b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParserTest.java new file mode 100644 index 000000000..a768526a0 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/BlueprintParserTest.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.sdc.controller.installer; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.yaml.snakeyaml.Yaml; + +public class BlueprintParserTest { + private static final Gson GSON = new Gson(); + private static final String FIRST_APPP = "first_app"; + private static final String SECOND_APPP = "second_app"; + private static final String THIRD_APPP = "third_app"; + private static final String MODEL_TYPE1 = "type1"; + private static final String MODEL_TYPE_TCA = "onap.policies.monitoring.cdap.tca.hi.lo.app"; + private static final String VERSION = "1.0.0"; + + private static String microServiceTheWholeBlueprintValid; + private static String newMicroServiceBlueprint; + private static JsonObject jsonObjectBlueprintInvalid; + private static JsonObject jsonObjectBlueprintWithoutName; + private static JsonObject jsonObjectBlueprintWithoutProperties; + private static JsonObject jsonObjectBlueprintWithoutRelationships; + private static JsonObject jsonObjectBlueprintValidWithVersion; + + /** + * Method to load Blueprints before all test. + * + * @throws IOException In case of issues when opening the files + */ + @BeforeClass + public static void loadBlueprints() throws IOException { + microServiceTheWholeBlueprintValid = ResourceFileUtils + .getResourceAsString("clds/blueprint-with-microservice-chain.yaml"); + + newMicroServiceBlueprint = ResourceFileUtils.getResourceAsString("clds/new-microservice.yaml"); + + String microServiceBlueprintInvalid = ResourceFileUtils + .getResourceAsString("clds/single-microservice-fragment-invalid.yaml"); + jsonObjectBlueprintInvalid = yamlToJson(microServiceBlueprintInvalid); + String microServiceBlueprintWithoutName = ResourceFileUtils + .getResourceAsString("clds/single-microservice-fragment-without-name.yaml"); + jsonObjectBlueprintWithoutName = yamlToJson(microServiceBlueprintWithoutName); + String microServiceBlueprintWithoutProperties = ResourceFileUtils + .getResourceAsString("clds/single-microservice-fragment-without-properties.yaml"); + jsonObjectBlueprintWithoutProperties = yamlToJson(microServiceBlueprintWithoutProperties); + String microServiceBlueprintValidWithVersion = ResourceFileUtils + .getResourceAsString("clds/single-microservice-fragment-valid-with-version.yaml"); + jsonObjectBlueprintValidWithVersion = yamlToJson(microServiceBlueprintValidWithVersion); + + String microServiceBlueprintWithoutRelationships = ResourceFileUtils + .getResourceAsString("clds/single-microservice-fragment-without-relationships.yaml"); + jsonObjectBlueprintWithoutRelationships = yamlToJson(microServiceBlueprintWithoutRelationships); + + } + + @Test + public void getNameShouldReturnDefinedName() { + final JsonObject jsonObject = jsonObjectBlueprintInvalid; + String expectedName = jsonObject.get(jsonObject.keySet().iterator().next()).getAsJsonObject().get("properties") + .getAsJsonObject().get("name").getAsString(); + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + String actualName = BlueprintParser.getName(entry); + + Assert.assertEquals(expectedName, actualName); + } + + @Test + public void getNameShouldReturnServiceNameWhenNoNameDefined() { + final JsonObject jsonObject = jsonObjectBlueprintWithoutName; + + String expectedName = jsonObject.keySet().iterator().next(); + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + String actualName = BlueprintParser.getName(entry); + + Assert.assertEquals(expectedName, actualName); + } + + @Test + public void getNameShouldReturnServiceNameWhenNoPropertiesDefined() { + final JsonObject jsonObject = jsonObjectBlueprintWithoutProperties; + + String expectedName = jsonObject.keySet().iterator().next(); + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + String actualName = BlueprintParser.getName(entry); + + Assert.assertEquals(expectedName, actualName); + } + + @Test + public void getInputShouldReturnInputWhenPresent() { + final JsonObject jsonObject = jsonObjectBlueprintInvalid; + + String expected = FIRST_APPP; + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + String actual = BlueprintParser.getInput(entry); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getInputShouldReturnEmptyStringWhenAbsent() { + final JsonObject jsonObject = jsonObjectBlueprintWithoutRelationships; + + String expected = ""; + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + String actual = BlueprintParser.getInput(entry); + + Assert.assertEquals(expected, actual); + } + + @Test(expected = BlueprintParserException.class) + public void getNodeRepresentationFromIncompleteYaml() throws BlueprintParserException { + BlueprintParser.getNodeRepresentation(jsonObjectBlueprintInvalid.entrySet().iterator().next(), + jsonObjectBlueprintInvalid, null); + } + + @Test + public void getNodeRepresentationFromCompleteYamlWithModelVersion() throws BlueprintParserException { + final JsonObject jsonObject = jsonObjectBlueprintValidWithVersion; + + BlueprintMicroService expected = new BlueprintMicroService(SECOND_APPP, MODEL_TYPE1, "", "10.0.0"); + Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next(); + BlueprintMicroService actual = BlueprintParser.getNodeRepresentation(entry, jsonObject, null); + + Assert.assertEquals(expected, actual); + } + + @Test + public void getMicroServicesFromBlueprintTest() throws BlueprintParserException { + BlueprintMicroService thirdApp = new BlueprintMicroService(THIRD_APPP, MODEL_TYPE_TCA, SECOND_APPP, VERSION); + BlueprintMicroService firstApp = new BlueprintMicroService(FIRST_APPP, MODEL_TYPE_TCA, "", VERSION); + BlueprintMicroService secondApp = new BlueprintMicroService(SECOND_APPP, MODEL_TYPE_TCA, FIRST_APPP, VERSION); + + Set<BlueprintMicroService> expected = new HashSet<>(Arrays.asList(firstApp, secondApp, thirdApp)); + Set<BlueprintMicroService> actual = BlueprintParser.getMicroServices(microServiceTheWholeBlueprintValid); + + Assert.assertEquals(expected, actual); + } + + @Test + public void fallBackToOneMicroServiceTcaTest() { + BlueprintMicroService tcaMs = new BlueprintMicroService(BlueprintParser.TCA, + "onap.policies.monitoring.cdap.tca.hi.lo.app", "", VERSION); + List<BlueprintMicroService> expected = Collections.singletonList(tcaMs); + List<BlueprintMicroService> actual = BlueprintParser.fallbackToOneMicroService(); + + Assert.assertEquals(expected, actual); + } + + @Test + public void newMicroServiceTest() throws BlueprintParserException { + List<BlueprintMicroService> microServicesChain = new ChainGenerator() + .getChainOfMicroServices(BlueprintParser.getMicroServices(newMicroServiceBlueprint)); + if (microServicesChain.isEmpty()) { + microServicesChain = BlueprintParser.fallbackToOneMicroService(); + } + assertThat(microServicesChain.size()).isEqualTo(1); + assertThat(microServicesChain.get(0).getName()).isEqualTo("pmsh"); + } + + private static JsonObject yamlToJson(String yamlString) { + Yaml yaml = new Yaml(); + Map<String, Object> map = yaml.load(yamlString); + JSONObject jsonObject = new JSONObject(map); + return GSON.fromJson(jsonObject.toString(), JsonObject.class); + } +} diff --git a/src/test/java/org/onap/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java new file mode 100644 index 000000000..83b3dda01 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.clds.sdc.controller.installer; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +public class ChainGeneratorTest { + private static final String FIRST_APPP = "first_app"; + private static final String SECOND_APPP = "second_app"; + private static final String THIRD_APPP = "third_app"; + private static final String FOURTH_APPP = "fourth_app"; + private static final String DEFAULT_VERSION = "1.0.0"; + + @Test + public void getChainOfMicroServicesTest() { + BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION); + BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", FIRST_APPP, DEFAULT_VERSION); + BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", SECOND_APPP, DEFAULT_VERSION); + BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", THIRD_APPP, DEFAULT_VERSION); + + List<BlueprintMicroService> expectedList = Arrays.asList(ms1, ms2, ms3, ms4); + Set<BlueprintMicroService> inputSet = new HashSet<>(expectedList); + + List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet); + Assert.assertEquals(expectedList, actualList); + } + + @Test + public void getChainOfMicroServicesTwiceNoInputTest() { + BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION); + BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", "", DEFAULT_VERSION); + BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", SECOND_APPP, DEFAULT_VERSION); + BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", FIRST_APPP, DEFAULT_VERSION); + + Set<BlueprintMicroService> inputSet = new HashSet<>(Arrays.asList(ms1, ms2, ms3, ms4)); + List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet); + Assert.assertTrue(actualList.isEmpty()); + } + + @Test + public void getChainOfMicroServicesBranchingTest() { + BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION); + BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", FIRST_APPP, DEFAULT_VERSION); + BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", FIRST_APPP, DEFAULT_VERSION); + BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", FIRST_APPP, DEFAULT_VERSION); + + Set<BlueprintMicroService> inputSet = new HashSet<>(Arrays.asList(ms1, ms2, ms3, ms4)); + List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet); + Assert.assertTrue(actualList.isEmpty()); + } +} diff --git a/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java new file mode 100644 index 000000000..f04e3fa3c --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java @@ -0,0 +1,200 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.sdc.controller.installer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.notification.IResourceInstance; +import org.onap.sdc.api.results.IDistributionClientDownloadResult; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; + +public class CsarHandlerTest { + + private static final String SDC_FOLDER = "/tmp/csar-handler-tests"; + private static final String CSAR_ARTIFACT_NAME = "testArtifact.csar"; + private static final String SERVICE_UUID = "serviceUUID"; + private static final String RESOURCE1_UUID = "resource1UUID"; + private static final String RESOURCE1_INSTANCE_NAME = "sim-1802 0"; + private static final String RESOURCE1_INSTANCE_NAME_IN_CSAR = "sim18020"; + private static final String BLUEPRINT1_NAME = "FOI.Simfoimap223S0112.event_proc_bp.yaml"; + private static final String BLUEPRINT2_NAME = "FOI.Simfoimap223S0112.event_proc_bp2.yaml"; + + @Test + public void testConstructor() throws CsarHandlerException { + IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class); + Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE); + Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME); + List<IArtifactInfo> servicesList = new ArrayList<>(); + servicesList.add(serviceArtifact); + INotificationData notifData = Mockito.mock(INotificationData.class); + Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList); + CsarHandler csar = new CsarHandler(notifData, "test-controller", SDC_FOLDER); + assertEquals(SDC_FOLDER + "/test-controller" + "/" + CSAR_ARTIFACT_NAME, csar.getFilePath()); + } + + @Test(expected = CsarHandlerException.class) + public void testFailingConstructor() throws CsarHandlerException { + INotificationData notifData = Mockito.mock(INotificationData.class); + Mockito.when(notifData.getServiceArtifacts()).thenReturn(new ArrayList<>()); + new CsarHandler(notifData, "test-controller", "/tmp/csar-handler-tests"); + fail("Exception should have been raised"); + } + + private INotificationData buildFakeSdcNotification() { + // BUild what is needed for CSAR + IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class); + Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE); + Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME); + List<IArtifactInfo> servicesList = new ArrayList<>(); + servicesList.add(serviceArtifact); + INotificationData notifData = Mockito.mock(INotificationData.class); + Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList); + // Build what is needed for UUID + Mockito.when(notifData.getServiceInvariantUUID()).thenReturn(SERVICE_UUID); + // Build fake resource with one artifact BLUEPRINT + IResourceInstance resource1 = Mockito.mock(IResourceInstance.class); + Mockito.when(resource1.getResourceType()).thenReturn("VF"); + Mockito.when(resource1.getResourceInvariantUUID()).thenReturn(RESOURCE1_UUID); + Mockito.when(resource1.getResourceInstanceName()).thenReturn(RESOURCE1_INSTANCE_NAME); + // Create a fake artifact for resource + IArtifactInfo blueprintArtifact = Mockito.mock(IArtifactInfo.class); + Mockito.when(blueprintArtifact.getArtifactType()).thenReturn(CsarHandler.BLUEPRINT_TYPE); + List<IArtifactInfo> artifactsListForResource = new ArrayList<>(); + artifactsListForResource.add(blueprintArtifact); + Mockito.when(resource1.getArtifacts()).thenReturn(artifactsListForResource); + List<IResourceInstance> resourcesList = new ArrayList<>(); + resourcesList.add(resource1); + Mockito.when(notifData.getResources()).thenReturn(resourcesList); + return notifData; + } + + private IDistributionClientDownloadResult buildFakeSdcResut() throws IOException { + IDistributionClientDownloadResult resultArtifact = Mockito.mock(IDistributionClientDownloadResult.class); + Mockito.when(resultArtifact.getArtifactPayload()).thenReturn( + IOUtils.toByteArray(ResourceFileUtils.getResourceAsStream("example/sdc/service-Simsfoimap0112.csar"))); + return resultArtifact; + } + + private IDistributionClientDownloadResult buildFakeSdcResultWithoutPolicyModel() throws IOException { + IDistributionClientDownloadResult resultArtifact = Mockito.mock(IDistributionClientDownloadResult.class); + Mockito.when(resultArtifact.getArtifactPayload()).thenReturn( + IOUtils.toByteArray(ResourceFileUtils.getResourceAsStream("example/sdc/service-without-policy.csar"))); + return resultArtifact; + } + + @Test + public void testSave() + throws SdcArtifactInstallerException, SdcToscaParserException, CsarHandlerException, IOException { + CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests"); + // Test the save + csar.save(buildFakeSdcResut()); + assertTrue((new File(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME)).exists()); + assertEquals(CSAR_ARTIFACT_NAME, csar.getArtifactElement().getArtifactName()); + assertNotNull(csar.getSdcCsarHelper()); + // Test dcaeBlueprint + String blueprint = csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getDcaeBlueprint(); + assertNotNull(blueprint); + assertTrue(!blueprint.isEmpty()); + assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1")); + // Test additional properties from Sdc notif + assertEquals(BLUEPRINT1_NAME, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintArtifactName()); + assertEquals(RESOURCE1_UUID, + csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getResourceAttached().getResourceInvariantUUID()); + assertEquals(SERVICE_UUID, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintInvariantServiceUuid()); + + // Just check the second one is there as well + assertEquals(BLUEPRINT2_NAME, csar.getMapOfBlueprints().get(BLUEPRINT2_NAME).getBlueprintArtifactName()); + blueprint = csar.getMapOfBlueprints().get(BLUEPRINT2_NAME).getDcaeBlueprint(); + assertNotNull(blueprint); + assertTrue(!blueprint.isEmpty()); + assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1")); + // Do some cleanup + Path path = Paths.get(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME); + Files.deleteIfExists(path); + + } + + @Test + public void testLoadingOfPolicyModelFromCsar() + throws CsarHandlerException, IOException, SdcArtifactInstallerException, SdcToscaParserException { + CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests"); + csar.save(buildFakeSdcResut()); + String policyModelYaml = csar.getPolicyModelYaml().get(); + assertTrue(policyModelYaml.contains("tosca_simple_yaml_1_0_0")); + } + + @Test + public void testLoadingOfNonexistentPolicyModelFromCsar() + throws CsarHandlerException, IOException, SdcArtifactInstallerException, SdcToscaParserException { + CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests"); + csar.save(buildFakeSdcResultWithoutPolicyModel()); + assertFalse(csar.getPolicyModelYaml().isPresent()); + } + + @Test + public void testDoubleSave() + throws SdcArtifactInstallerException, SdcToscaParserException, CsarHandlerException, IOException { + CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests"); + // Test the save + csar.save(buildFakeSdcResut()); + assertTrue((new File(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME)).exists()); + assertEquals(CSAR_ARTIFACT_NAME, csar.getArtifactElement().getArtifactName()); + assertNotNull(csar.getSdcCsarHelper()); + // Test dcaeBlueprint + String blueprint = csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getDcaeBlueprint(); + assertNotNull(blueprint); + assertTrue(!blueprint.isEmpty()); + assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1")); + // Test additional properties from Sdc notif + assertEquals(BLUEPRINT1_NAME, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintArtifactName()); + assertEquals(RESOURCE1_UUID, + csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getResourceAttached().getResourceInvariantUUID()); + assertEquals(SERVICE_UUID, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintInvariantServiceUuid()); + Path path = Paths.get(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME); + // A double save should simply overwrite the existing + csar.save(buildFakeSdcResut()); + // Do some cleanup + Files.deleteIfExists(path); + } +} diff --git a/src/test/java/org/onap/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java b/src/test/java/org/onap/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java new file mode 100644 index 000000000..01dc8404c --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.onap.clamp.tosca.Dictionary; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class DictionaryRepositoriesTestItCase { + @Autowired + private DictionaryRepository dictionaryRepository; + + @Test + @Transactional + public void crudTest() { + // Setup + Dictionary dictionaryTest1 = new Dictionary(); + dictionaryTest1.setName("testDictionary1"); + dictionaryTest1.setSecondLevelDictionary(1); + dictionaryTest1.setSubDictionaryType("testType"); + + DictionaryElement element1 = new DictionaryElement(); + element1.setName("element1"); + element1.setShortName("shortName1"); + element1.setType("type1"); + element1.setDescription("description1"); + + dictionaryTest1.addDictionaryElements(element1); + + Dictionary dictionaryTest2 = new Dictionary(); + dictionaryTest2.setName("testDictionary2"); + dictionaryTest2.setSecondLevelDictionary(1); + dictionaryTest2.setSubDictionaryType("testType"); + + DictionaryElement element2 = new DictionaryElement(); + element2.setName("element2"); + element2.setShortName("shortName2"); + element2.setSubDictionary("testDictionary1"); + element2.setType("type2"); + element2.setDescription("description2"); + + dictionaryTest2.addDictionaryElements(element2); + + dictionaryRepository.save(dictionaryTest1); + List<String> res1 = dictionaryRepository.getAllDictionaryNames(); + assertThat(res1.size()).isGreaterThanOrEqualTo(1); + assertThat(res1).contains("testDictionary1"); + + dictionaryRepository.save(dictionaryTest2); + List<String> res2 = dictionaryRepository.getAllDictionaryNames(); + assertThat(res2.size()).isGreaterThanOrEqualTo(2); + assertThat(res2).contains("testDictionary1"); + assertThat(res2).contains("testDictionary2"); + } +} diff --git a/src/test/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertorTestItCase.java b/src/test/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertorTestItCase.java new file mode 100644 index 000000000..e73547652 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertorTestItCase.java @@ -0,0 +1,201 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights + * reserved. + * Modifications Copyright (C) 2019 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.tosca; + +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonObject; +import java.io.IOException; +import javax.transaction.Transactional; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.tosca.Dictionary; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryService; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class ToscaYamlToJsonConvertorTestItCase { + + @Autowired + private DictionaryService dictionaryService; + + @Autowired + private ToscaYamlToJsonConvertor toscaYamlToJsonConvertor; + + /** + * This Test validates TOSCA yaml to JSON Schema conversion based on JSON Editor + * Schema. + * + * @throws IOException In case of issue when opening the tosca yaml file and + * converted json file + */ + @Test + public final void testParseToscaYaml() throws IOException { + String toscaModelYaml = ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml"); + ToscaYamlToJsonConvertor convertor = new ToscaYamlToJsonConvertor(); + + String parsedJsonSchema = + convertor.parseToscaYaml(toscaModelYaml, "onap.policies.monitoring.cdap.tca.hi.lo.app"); + assertNotNull(parsedJsonSchema); + JSONAssert.assertEquals( + ResourceFileUtils.getResourceAsString("tosca/policy-yaml-to-json.json"), + parsedJsonSchema, true); + } + + /** + * This Test validates TOSCA yaml with constraints to JSON Schema conversion + * based on JSON Editor Schema. + * + * @throws IOException In case of issue when opening the tosca yaml file and + * converted json file + */ + @Test + public final void testParseToscaYamlWithConstraints() throws IOException { + String toscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca-with-constraints.yaml"); + ToscaYamlToJsonConvertor convertor = new ToscaYamlToJsonConvertor(); + + String parsedJsonSchema = + convertor.parseToscaYaml(toscaModelYaml, "onap.policies.monitoring.example.app"); + assertNotNull(parsedJsonSchema); + JSONAssert.assertEquals( + ResourceFileUtils.getResourceAsString("tosca/policy-yaml-to-json-with-constraints.json"), + parsedJsonSchema, true); + } + + /** + * This Test validates TOSCA yaml with different datatypes to JSON Schema + * conversion based on JSON Editor Schema. + * + * @throws IOException In case of issue when opening the tosca yaml file and + * converted json file + */ + @Test + public final void testParseToscaYamlWithTypes() throws IOException { + String toscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca-with-datatypes.yaml"); + ToscaYamlToJsonConvertor convertor = new ToscaYamlToJsonConvertor(); + + String parsedJsonSchema = + convertor.parseToscaYaml(toscaModelYaml, "onap.policies.monitoring.example.app"); + assertNotNull(parsedJsonSchema); + JSONAssert.assertEquals( + ResourceFileUtils.getResourceAsString("tosca/policy-yaml-to-json-with-datatypes.json"), + parsedJsonSchema, true); + } + + /** + * This Test validates Tosca yaml with metadata tag that contains policy_model_type and acronym + * parameters which defines the Tosca Policy name and its short name. + * + * @throws IOException In case of issue when opening the tosca yaml file and + * converted json file + */ + @Test + @Transactional + public final void testMetadataClampPossibleValues() throws IOException { + setupDictionary(); + String toscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca_metadata_clamp_possible_values.yaml"); + + JsonObject jsonObject = toscaYamlToJsonConvertor.validateAndConvertToJson(toscaModelYaml); + assertNotNull(jsonObject); + String policyModelType = toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject, + ToscaSchemaConstants.METADATA_POLICY_MODEL_TYPE); + String acronym = toscaYamlToJsonConvertor.getValueFromMetadata(jsonObject, + ToscaSchemaConstants.METADATA_ACRONYM); + String parsedJsonSchema = + toscaYamlToJsonConvertor.parseToscaYaml(toscaModelYaml, policyModelType); + + assertNotNull(parsedJsonSchema); + assertEquals("onap.policies.monitoring.cdap.tca.hi.lo.app", policyModelType); + assertEquals("tca", acronym); + JSONAssert.assertEquals( + ResourceFileUtils + .getResourceAsString("tosca/tosca_metadata_clamp_possible_values_json_schema.json"), + parsedJsonSchema, true); + + } + + private void setupDictionary() { + + // Set up dictionary elements + Dictionary dictionaryTest = new Dictionary(); + dictionaryTest.setName("Context"); + dictionaryTest.setSecondLevelDictionary(0); + + DictionaryElement element = new DictionaryElement(); + element.setName("PROD"); + element.setShortName("PROD"); + element.setType("string"); + element.setDescription("Production"); + dictionaryTest.addDictionaryElements(element); + + dictionaryService.saveOrUpdateDictionary(dictionaryTest); + + Dictionary dictionaryTest1 = new Dictionary(); + dictionaryTest1.setName("EventDictionary"); + dictionaryTest1.setSecondLevelDictionary(0); + + DictionaryElement element1 = new DictionaryElement(); + element1.setName("alarmCondition"); + element1.setShortName("alarmCondition"); + element1.setType("string"); + element1.setDescription("Alarm Condition"); + dictionaryTest1.addDictionaryElements(element1); + + dictionaryTest1 = dictionaryService.saveOrUpdateDictionary(dictionaryTest1); + + DictionaryElement element3 = new DictionaryElement(); + element3.setName("timeEpoch"); + element3.setShortName("timeEpoch"); + element3.setType("datetime"); + element3.setDescription("Time Epoch"); + dictionaryTest1.addDictionaryElements(element3); + + dictionaryService.saveOrUpdateDictionary(dictionaryTest1); + + Dictionary dictionaryTest2 = new Dictionary(); + dictionaryTest2.setName("Operators"); + dictionaryTest2.setSecondLevelDictionary(0); + + DictionaryElement element2 = new DictionaryElement(); + element2.setName("equals"); + element2.setShortName("equals"); + element2.setType("string|datetime"); + element2.setDescription("equals"); + dictionaryTest2.addDictionaryElements(element2); + dictionaryService.saveOrUpdateDictionary(dictionaryTest2); + } + +} diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/ArrayFieldTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/ArrayFieldTest.java new file mode 100644 index 000000000..8a81445b2 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/ArrayFieldTest.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import com.google.gson.JsonArray; +import java.io.IOException; +import java.util.ArrayList; +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.elements.ArrayField; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.ResourceFileUtils; + +public class ArrayFieldTest extends TestCase { + + /** + * Test the deploy method. + * + * @throws IOException in case of failure + */ + public void testDeploy() throws IOException { + JsonTemplateManager jsonTemplateManager = new JsonTemplateManager(ResourceFileUtils.getResourceAsString( + "tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml"), ResourceFileUtils.getResourceAsString( + "clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor"); + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("actor"); + ArrayField arrayParser = new ArrayField((ArrayList<Object>) toscaElementProperty.getItems().get("default")); + JsonArray toTest = arrayParser.deploy(); + String reference = "[1,\"String\",5.5,true]"; + assertEquals(reference, String.valueOf(toTest)); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/ConstraintTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/ConstraintTest.java new file mode 100644 index 000000000..f147f404d --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/ConstraintTest.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.ArrayList; +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.ResourceFileUtils; + +public class ConstraintTest extends TestCase { + + JsonTemplateManager jsonTemplateManager = new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/constraints.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + + ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Operation"); + + public ConstraintTest() throws IOException { + } + + /** + * Test get value array. + */ + public void testGetValuesArray() { + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("timeout"); + JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("integer"); + JsonObject resultProcess = new JsonObject(); + toscaElementProperty.addConstraintsAsJson(resultProcess, + (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + jsonTemplate); + String reference = "{\"enum\":[3,4,5.5,6,10]}"; + assertEquals(reference, String.valueOf(resultProcess)); + toscaElementProperty = toscaElement.getProperties().get("success"); + jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string"); + resultProcess = new JsonObject(); + toscaElementProperty.addConstraintsAsJson(resultProcess, + (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + jsonTemplate); + reference = "{\"enum\":[\"VALID\",\"TERMINATED\"]}"; + assertEquals(reference, String.valueOf(resultProcess)); + } + + /** + * Test get Specific length. + */ + public void testGetSpecificLength() { + //Test for string type, same process for array + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("id"); + JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string"); + JsonObject resultProcess = new JsonObject(); + toscaElementProperty.addConstraintsAsJson(resultProcess, + (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + jsonTemplate); + int specificLength = 8; + int toTest = resultProcess.get("minLength").getAsInt(); + assertEquals(specificLength, toTest); + toTest = resultProcess.get("maxLength").getAsInt(); + assertEquals(specificLength, toTest); + } + + /** + * Test get limit value. + */ + public void testGetLimitValue() { + //Test for array type, same process for string + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("description"); + JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("array"); + JsonObject resultProcess = new JsonObject(); + toscaElementProperty.addConstraintsAsJson(resultProcess, + (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + jsonTemplate); + + int toTest = resultProcess.get("minItems").getAsInt(); + assertEquals(5, toTest); + toTest = resultProcess.get("maxItems").getAsInt(); + assertEquals(7, toTest); + } + +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateFieldTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateFieldTest.java new file mode 100644 index 000000000..29f5a1da8 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateFieldTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateField; + +public class JsonTemplateFieldTest extends TestCase { + + JsonTemplateField field1 = new JsonTemplateField("type", "testType", true, true); + JsonTemplateField field2 = new JsonTemplateField("type"); + JsonTemplateField field3 = new JsonTemplateField("type", "testType1", true, true); + JsonTemplateField field4 = new JsonTemplateField("type", "testType", false, true); + JsonTemplateField field5 = new JsonTemplateField("type", "testType", true, false); + JsonTemplateField field6 = new JsonTemplateField("type", "testType", true, true); + + /** + * Test fieldsEqual method. + */ + public void testFieldsEqualsMethod() { + assertFalse(JsonTemplateField.fieldsEquals(field1,field3)); + assertFalse(JsonTemplateField.fieldsEquals(field1,field4)); + assertFalse(JsonTemplateField.fieldsEquals(field1,field5)); + assertTrue(JsonTemplateField.fieldsEquals(field1,field6)); + } + + /** + * Test equals method. + */ + public void testEqualsMethod() { + assertTrue(field1.equals(field2)); + assertTrue(field1.equals(field3)); + assertTrue(field1.equals(field4)); + assertTrue(field1.equals(field5)); + assertTrue(field1.equals(field6)); + } + + /** + * Test compareWithField method. + */ + public void testCompareWithFieldMethod() { + assertFalse(field1.compareWithField(field2)); + assertFalse(field1.compareWithField(field3)); + assertFalse(field1.compareWithField(field4)); + assertFalse(field1.compareWithField(field5)); + assertTrue(field1.equals(field6)); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateManagerTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateManagerTest.java new file mode 100644 index 000000000..504103559 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateManagerTest.java @@ -0,0 +1,203 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateField; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.ResourceFileUtils; + +public class JsonTemplateManagerTest extends TestCase { + + /** + * Test the launch translation wit operational policies. + * + * @throws IOException In case of failure + * @throws UnknownComponentException In case of failure + */ + public void testLaunchTranslationTca() throws IOException, UnknownComponentException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap" + + ".policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file"), + ResourceFileUtils.getResourceAsString( + "clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + String componentName = "onap.policies.monitoring.cdap.tca.hi.lo.app"; + jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null); + } + + /** + * Test the launch translation wit operational policies. + * + * @throws IOException In case of failure + * @throws UnknownComponentException In case of failure + */ + public void testLaunchTranslationFrequencyLimiter() throws IOException, UnknownComponentException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap" + + ".policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file"), + ResourceFileUtils.getResourceAsString( + "clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + String componentName = "onap.policies.controlloop.guard.common.FrequencyLimiter"; + jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null); + } + + /** + * Test the launch translation wit operational policies. + * + * @throws IOException In case of failure + * @throws UnknownComponentException In case of failure + */ + public void testLaunchTranslationApex() throws IOException, UnknownComponentException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap" + + ".policies.controlloop.operational.common.Apex/versions/1.0.0/.file"), + ResourceFileUtils.getResourceAsString( + "clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + String componentName = "onap.policies.controlloop.operational.common.Apex"; + jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null); + } + + /** + * Test the launch translation wit operational policies. + * + * @throws IOException In case of failure + * @throws UnknownComponentException In case of failure + */ + public void testLaunchTranslationDrools() throws IOException, UnknownComponentException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap" + + ".policies.controlloop.operational.common.Drools/versions/1.0.0/.file"), + ResourceFileUtils.getResourceAsString( + "clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + String componentName = "onap.policies.controlloop.operational.common.Drools"; + jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null); + } + + + /** + * Test the launch translation. + * + * @throws IOException In case of failure + * @throws UnknownComponentException In case of failure + */ + public void testLaunchTranslation() throws IOException, UnknownComponentException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + String componentName = "onap.policies.controlloop.operational.common.Drools"; + jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null); + } + + /** + * Test addTemplate. + * + * @throws IOException In case of failure + */ + public void testAddTemplate() throws IOException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + int count = jsonTemplateManager.getJsonSchemaTemplates().size(); + List<JsonTemplateField> + jsonTemplateFields = + new ArrayList<>(Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"), + new JsonTemplateField( + "required"), + new JsonTemplateField("metadata"), new JsonTemplateField("constraints"))); + jsonTemplateManager.addTemplate("test", jsonTemplateFields); + assertNotSame(count, jsonTemplateManager.getJsonSchemaTemplates().size()); + } + + /** + * test Remove template. + * + * @throws IOException In case of failure + */ + public void testRemoveTemplate() throws IOException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + int count = jsonTemplateManager.getJsonSchemaTemplates().size(); + jsonTemplateManager.removeTemplate("string"); + assertNotSame(count, jsonTemplateManager.getJsonSchemaTemplates().size()); + } + + /** + * Test update template. + * + * @throws IOException In case of failure + */ + public void testUpdateTemplate() throws IOException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + int count = jsonTemplateManager.getJsonSchemaTemplates().get("integer").getJsonTemplateFields().size(); + jsonTemplateManager.updateTemplate("integer", new JsonTemplateField("type"), false); + assertNotSame(count, + jsonTemplateManager.getJsonSchemaTemplates().get("integer").getJsonTemplateFields().size()); + } + + /** + * Test has template. + * + * @throws IOException In case of failure + */ + public void testHasTemplate() throws IOException { + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + boolean has = true; + List<JsonTemplateField> jsonTemplateFieldsString = + new ArrayList<>(Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"), + new JsonTemplateField("required"), + new JsonTemplateField("metadata"), new JsonTemplateField("constraints"))); + JsonTemplate jsonTemplateTest = new JsonTemplate("String", jsonTemplateFieldsString); + has = jsonTemplateManager.hasTemplate(jsonTemplateTest); + assertEquals(false, has); + } + +} diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateTest.java new file mode 100644 index 000000000..dc736a48b --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/JsonTemplateTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateField; + +public class JsonTemplateTest extends TestCase { + + JsonTemplate toTest = new JsonTemplate("toTest"); + List<JsonTemplateField> + jsonTemplateFields = new ArrayList<>( + Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"), + new JsonTemplateField( + "enum"))); + + /** + * Test check failed. + */ + public void testCheckFields() { + toTest.setJsonTemplateFields(jsonTemplateFields); + JsonTemplate reference = new JsonTemplate("toTest"); + reference.setJsonTemplateFields(jsonTemplateFields); + assertTrue(toTest.checkFields(reference)); + } + + /** + * Test other methods. + */ + public void testOtherFields() { + toTest.setJsonTemplateFields(jsonTemplateFields); + toTest.addField(new JsonTemplateField("moreField")); + toTest.setVisibility("moreField", true); + toTest.setStatic("moreField", true); + toTest.updateValueField("moreField", "testValue"); + + assertTrue(toTest.isVisible("moreField")); + assertTrue(toTest.getSpecificField("moreField").getValue().equals("testValue")); + assertTrue(toTest.fieldStaticStatus("moreField")); + assertTrue(toTest.toString() + .equals(" templateFields : [type null null null, description null null null, " + + "enum null null null, moreField testValue true true]")); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java new file mode 100644 index 000000000..1d4ee4311 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java @@ -0,0 +1,147 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import com.google.gson.JsonObject; +import java.io.IOException; +import javax.transaction.Transactional; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.onap.clamp.clds.tosca.update.execution.ToscaMetadataExecutor; +import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParserWithDictionarySupport; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.tosca.Dictionary; +import org.onap.clamp.tosca.DictionaryElement; +import org.onap.clamp.tosca.DictionaryService; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +@ActiveProfiles({"clamp-default","clamp-default-user","default-dictionary-elements"}) +public class ToscaConverterWithDictionarySupportItCase { + + @Autowired + private DictionaryService dictionaryService; + + @Autowired + private ToscaMetadataParserWithDictionarySupport toscaMetadataParserWithDictionarySupport; + + @Autowired + private ToscaMetadataExecutor toscaMetadataExecutor; + + /** + * This Test validates Tosca yaml with metadata tag that contains policy_model_type and acronym + * parameters which defines the Tosca Policy name and its short name. + * + * @throws IOException In case of issue when opening the tosca yaml file and + * converted json file + */ + @Test + @Transactional + public final void testMetadataClampPossibleValues() throws IOException, UnknownComponentException { + + // Set up dictionary elements + Dictionary dictionaryTest = new Dictionary(); + dictionaryTest.setName("Context"); + dictionaryTest.setSecondLevelDictionary(0); + + DictionaryElement element = new DictionaryElement(); + element.setName("PROD"); + element.setShortName("PROD"); + element.setType("string"); + element.setDescription("Production"); + dictionaryTest.addDictionaryElements(element); + + dictionaryService.saveOrUpdateDictionary(dictionaryTest); + + Dictionary dictionaryTest1 = new Dictionary(); + dictionaryTest1.setName("EventDictionary"); + dictionaryTest1.setSecondLevelDictionary(0); + + DictionaryElement element1 = new DictionaryElement(); + element1.setName("alarmCondition"); + element1.setShortName("alarmCondition"); + element1.setType("string"); + element1.setDescription("Alarm Condition"); + dictionaryTest1.addDictionaryElements(element1); + + dictionaryService.saveOrUpdateDictionary(dictionaryTest1); + + Dictionary dictionaryTest2 = new Dictionary(); + dictionaryTest2.setName("Operators"); + dictionaryTest2.setSecondLevelDictionary(0); + + DictionaryElement element2 = new DictionaryElement(); + element2.setName("equals"); + element2.setShortName("equals"); + element2.setType("string"); + element2.setDescription("equals"); + dictionaryTest2.addDictionaryElements(element2); + dictionaryService.saveOrUpdateDictionary(dictionaryTest2); + + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils + .getResourceAsString("tosca/new-converter/tosca_metadata_clamp_possible_values.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + + JsonObject jsonSchema = jsonTemplateManager.getJsonSchemaForPolicyType( + "onap.policies.monitoring.cdap.tca.hi.lo.app", toscaMetadataParserWithDictionarySupport, null); + + JSONAssert.assertEquals( + ResourceFileUtils + .getResourceAsString("tosca/new-converter/tca-with-metadata.json"), + JsonUtils.GSON.toJson(jsonSchema), true); + } + + @Test + @Transactional + public final void testMetadataClampPossibleValueWithExecutor() throws IOException, UnknownComponentException { + Service service = new Service(ResourceFileUtils.getResourceAsString("tosca/service-details.json"), + ResourceFileUtils.getResourceAsString("tosca/resource-details-cds.json")); + JsonTemplateManager jsonTemplateManager = + new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap" + + ".policies.controlloop.operational.common.Apex/versions/1.0.0/.file"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + + JsonObject jsonSchema = jsonTemplateManager.getJsonSchemaForPolicyType( + "onap.policies.controlloop.operational.common.Apex", toscaMetadataParserWithDictionarySupport, service); + + JSONAssert.assertEquals( + ResourceFileUtils + .getResourceAsString("tosca/new-converter/tosca_apex_with_metadata.json"), + JsonUtils.GSON.toJson(jsonSchema), true); + } +} diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementPropertyTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementPropertyTest.java new file mode 100644 index 000000000..52f8444ff --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementPropertyTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.clds.tosca.update; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.ArrayList; +import junit.framework.TestCase; +import org.onap.clamp.clds.tosca.update.elements.ToscaElement; +import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplate; +import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager; +import org.onap.clamp.clds.util.ResourceFileUtils; + +public class ToscaElementPropertyTest extends TestCase { + public ToscaElementPropertyTest() throws IOException { + } + + /** + * Test Parse array. + * + * @throws IOException In case of failure + */ + public void testParseArray() throws IOException { + JsonTemplateManager jsonTemplateManager = new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor"); + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("actor"); + JsonArray toTest = + toscaElementProperty.parseArray((ArrayList<Object>) toscaElementProperty.getItems().get("default")); + assertNotNull(toTest); + } + + /** + * Test add constraint as json. + * + * @throws IOException In case of failure + */ + public void testAddConstraintsAsJson() throws IOException { + JsonTemplateManager jsonTemplateManager = new JsonTemplateManager( + ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"), + ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json")); + ToscaElement toscaElement = + jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.operation.Failure"); + ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("category"); + JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string"); + JsonObject toTest = new JsonObject(); + toscaElementProperty + .addConstraintsAsJson(toTest, (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"), + jsonTemplate); + String test = "{\"enum\":[\"error\",\"timeout\",\"retries\",\"guard\",\"exception\"]}"; + assertEquals(test, String.valueOf(toTest)); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementTest.java b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementTest.java new file mode 100644 index 000000000..ba8454bb2 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/tosca/update/ToscaElementTest.java @@ -0,0 +1,52 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.clds.tosca.update;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import junit.framework.TestCase;
+import org.onap.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.clamp.clds.util.ResourceFileUtils;
+
+public class ToscaElementTest extends TestCase {
+
+ /**
+ * Test propertiesName.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testPropertiesNames() throws IOException {
+ ArrayList<String> reference = new ArrayList<>(Arrays.asList("actor", "operation", "target", "payload"));
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor");
+ assertEquals(reference, toscaElement.propertiesNames());
+ }
+
+}
diff --git a/src/test/java/org/onap/clamp/clds/util/CryptoUtilsTest.java b/src/test/java/org/onap/clamp/clds/util/CryptoUtilsTest.java new file mode 100644 index 000000000..f6054d538 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/CryptoUtilsTest.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; + +import java.security.InvalidKeyException; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({ "javax.crypto.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*" }) +public class CryptoUtilsTest { + + private final String data = "This is a test string"; + + @Test + @PrepareForTest({ CryptoUtils.class }) + public final void testEncryption() throws Exception { + String encodedString = CryptoUtils.encrypt(data); + assertNotNull(encodedString); + assertEquals(data, CryptoUtils.decrypt(encodedString)); + } + + @Test + @PrepareForTest({ CryptoUtils.class }) + public final void testEncryptedStringIsDifferent() throws Exception { + String encodedString1 = CryptoUtils.encrypt(data); + String encodedString2 = CryptoUtils.encrypt(data); + byte[] encryptedMessage1 = Hex.decodeHex(encodedString1.toCharArray()); + byte[] encryptedMessage2 = Hex.decodeHex(encodedString2.toCharArray()); + assertNotNull(encryptedMessage1); + assertNotNull(encryptedMessage2); + assertNotEquals(encryptedMessage1, encryptedMessage2); + byte[] subData1 = ArrayUtils.subarray(encryptedMessage1, 16, encryptedMessage1.length); + byte[] subData2 = ArrayUtils.subarray(encryptedMessage2, 16, encryptedMessage2.length); + assertNotEquals(subData1, subData2); + } + + @Test + @PrepareForTest({ CryptoUtils.class }) + public final void testEncryptionBaseOnRandomKey() throws Exception { + SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey(); + final String encryptionKey = String.valueOf(Hex.encodeHex(secretKey.getEncoded())); + setAesEncryptionKeyEnv(encryptionKey); + + String encodedString = CryptoUtils.encrypt(data); + String decodedString = CryptoUtils.decrypt(encodedString); + assertEquals(data, decodedString); + } + + @Test(expected = InvalidKeyException.class) + @PrepareForTest({ CryptoUtils.class }) + public final void testEncryptionBadKey() throws Exception { + final String badEncryptionKey = "93210sd"; + setAesEncryptionKeyEnv(badEncryptionKey); + + CryptoUtils.encrypt(data); + } + + private static void setAesEncryptionKeyEnv(String value) { + PowerMockito.mockStatic(System.class); + PowerMockito.when(System.getenv(eq("AES_ENCRYPTION_KEY"))).thenReturn(value); + } +} diff --git a/src/test/java/org/onap/clamp/clds/util/JsonUtilsTest.java b/src/test/java/org/onap/clamp/clds/util/JsonUtilsTest.java new file mode 100644 index 000000000..bc2ec2122 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/JsonUtilsTest.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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============================================ + * Modifications copyright (c) 2019 Nokia + * =================================================================== + * + */ + +package org.onap.clamp.clds.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.junit.Test; + +public class JsonUtilsTest { + + public static class TestClass extends TestObject { + + String test2; + TestObject2 object2; + + TestClass(String value1, String value2) { + super(value1); + test2 = value2; + } + + void setObject2(TestObject2 object2) { + this.object2 = object2; + } + } + + @Test + public void testGetObjectMapperInstance() { + assertNotNull(JsonUtils.GSON); + } + + /** + * This method test that the security hole in GSON is not enabled in the default + * ObjectMapper. + */ + @Test + public void testCreateBeanDeserializer() { + TestClass test = new TestClass("value1", "value2"); + test.setObject2(new TestObject2("test3")); + Object testObject = JsonUtils.GSON.fromJson("[\"org.onap.clamp.clds.util.JsonUtilsTest$TestClass\"" + + ",{\"test\":\"value1\",\"test2\":\"value2\",\"object2\":[\"org.onap.clamp.clds.util.TestObject2\"," + + "{\"test3\":\"test3\"}]}]", Object.class); + assertNotNull(testObject); + assertFalse(testObject instanceof TestObject); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionFileNotExists() throws IOException { + ResourceFileUtils.getResourceAsString("example/notExist.json"); + } +} diff --git a/src/test/java/org/onap/clamp/clds/util/LoggingUtilsTest.java b/src/test/java/org/onap/clamp/clds/util/LoggingUtilsTest.java new file mode 100644 index 000000000..7e823e163 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/LoggingUtilsTest.java @@ -0,0 +1,138 @@ +/*- +* ============LICENSE_START======================================================= +* ONAP CLAMP +* Copyright (C) 2019 Samsung. 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.clds.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.servlet.http.HttpServletRequest; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.event.Level; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * Test Logging Utils. + */ +@RunWith(MockitoJUnitRunner.class) +public class LoggingUtilsTest { + + protected static final Logger logger = LoggerFactory.getLogger(LoggingUtilsTest.class); + + private static final String SERVICE_NAME = "LogginUtilsTest: Test Entering method"; + + private LoggingUtils util; + + @Before + public void setup() { + this.util = new LoggingUtils(logger); + } + + @Test + public void testEnteringLoggingUtils() { + // given + final String userName = "test"; + + UserDetails userDetails = Mockito.mock(UserDetails.class); + Mockito.when(userDetails.getUsername()).thenReturn(userName); + + Authentication localAuth = Mockito.mock(Authentication.class); + Mockito.when(localAuth.getPrincipal()).thenReturn(userDetails); + + SecurityContext securityContext = Mockito.mock(SecurityContext.class); + Mockito.when(securityContext.getAuthentication()).thenReturn(localAuth); + SecurityContextHolder.setContext(securityContext); + + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + // when + util.entering(request, SERVICE_NAME); + + // then + String[] keys = {OnapLogConstants.Mdcs.PARTNER_NAME, OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, + OnapLogConstants.Mdcs.REQUEST_ID, OnapLogConstants.Mdcs.INVOCATION_ID, + OnapLogConstants.Mdcs.CLIENT_IP_ADDRESS, OnapLogConstants.Mdcs.SERVER_FQDN, + OnapLogConstants.Mdcs.INSTANCE_UUID, OnapLogConstants.Mdcs.SERVICE_NAME}; + Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap(); + + assertTrue(checkMapKeys(mdc, keys)); + assertEquals(userName, mdc.get(OnapLogConstants.Mdcs.PARTNER_NAME)); + } + + @Test + public void testExistingLoggingUtils() { + // given + MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, + ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + + // when + util.exiting(HttpStatus.OK.value(), SERVICE_NAME, Level.INFO, + OnapLogConstants.ResponseStatus.COMPLETE); + + // then + Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap(); + assertNull(mdc); + } + + @Test + public void testInvokeTestUtils() { + // given + final String targetEntity = "LoggingUtilsTest"; + final String targetServiceName = "testInvokeTestUtils"; + HttpsURLConnection secureConnection = Mockito.mock(HttpsURLConnection.class); + + // when + secureConnection = util.invokeHttps(secureConnection, targetEntity, targetServiceName); + + // then + assertNotNull(secureConnection); + String[] keys = + {OnapLogConstants.Mdcs.TARGET_ENTITY, OnapLogConstants.Mdcs.TARGET_SERVICE_NAME, + OnapLogConstants.Mdcs.INVOCATIONID_OUT, OnapLogConstants.Mdcs.INVOKE_TIMESTAMP}; + Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap(); + + assertTrue(checkMapKeys(mdc, keys)); + assertEquals(targetEntity, mdc.get(OnapLogConstants.Mdcs.TARGET_ENTITY)); + assertEquals(targetServiceName, mdc.get(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME)); + } + + private boolean checkMapKeys(Map map, String[] keys) { + return Arrays.stream(keys).allMatch(key -> map.get(key) != null); + } +} diff --git a/src/test/java/org/onap/clamp/clds/util/TestObject.java b/src/test/java/org/onap/clamp/clds/util/TestObject.java new file mode 100644 index 000000000..418c80815 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/TestObject.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.util; + +public class TestObject { + + private String test; + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + + // @JsonProperty("test"), @JsonCreator + public TestObject(String theString) { + this.setTest(theString); + } + + public TestObject() { + } +} diff --git a/src/test/java/org/onap/clamp/clds/util/TestObject2.java b/src/test/java/org/onap/clamp/clds/util/TestObject2.java new file mode 100644 index 000000000..4fd77c230 --- /dev/null +++ b/src/test/java/org/onap/clamp/clds/util/TestObject2.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2018 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.clds.util; + +public class TestObject2 { + + private String test3; + + public String getTest3() { + return test3; + } + + public void setTest3(String test) { + this.test3 = test; + } + + public TestObject2(String theString) { + this.setTest3(theString); + } + + public TestObject2() { + } +} diff --git a/src/test/java/org/onap/clamp/flow/FlowLogOperationTest.java b/src/test/java/org/onap/clamp/flow/FlowLogOperationTest.java new file mode 100644 index 000000000..648c03307 --- /dev/null +++ b/src/test/java/org/onap/clamp/flow/FlowLogOperationTest.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Samsung. 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.flow; + +import static junit.framework.Assert.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultExchange; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.clamp.clds.util.LoggingUtils; +import org.onap.clamp.clds.util.OnapLogConstants; +import org.onap.clamp.flow.log.FlowLogOperation; +import org.slf4j.MDC; +import org.slf4j.spi.MDCAdapter; +import org.springframework.test.util.ReflectionTestUtils; + +public class FlowLogOperationTest { + + private FlowLogOperation flowLogOperation = new FlowLogOperation(); + + @Test + public void testStratLog() { + // given + LoggingUtils loggingUtils = mock(LoggingUtils.class); + ReflectionTestUtils.setField(flowLogOperation, "util", loggingUtils); + + // when + Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.REQUEST_ID)).thenReturn("MockRequestId"); + Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.INVOCATION_ID)).thenReturn("MockInvocationId"); + Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.PARTNER_NAME)).thenReturn("MockPartnerName"); + Exchange exchange = new DefaultExchange(mock(CamelContext.class)); + flowLogOperation.startLog(exchange, "serviceName"); + + // then + assertThat(exchange.getProperty(OnapLogConstants.Headers.REQUEST_ID)).isEqualTo("MockRequestId"); + assertThat(exchange.getProperty(OnapLogConstants.Headers.INVOCATION_ID)).isEqualTo("MockInvocationId"); + assertThat(exchange.getProperty(OnapLogConstants.Headers.PARTNER_NAME)).isEqualTo("MockPartnerName"); + } + + @Test + public void testInvokeLog() { + // given + final String mockEntity = "mockEntity"; + final String mockServiceName = "mockSerivceName"; + MDCAdapter mdcAdapter = MDC.getMDCAdapter(); + // when + flowLogOperation.invokeLog(mockEntity, mockServiceName); + // then + String entity = mdcAdapter.get(OnapLogConstants.Mdcs.TARGET_ENTITY); + String serviceName = mdcAdapter.get(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME); + assertEquals(entity, mockEntity); + assertEquals(serviceName, mockServiceName); + } + + @Test + public void testEndLog() { + // given + MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, "2019-05-19T00:00:00.007Z"); + MDCAdapter mdcAdapter = MDC.getMDCAdapter(); + /// when + flowLogOperation.endLog(); + // then + assertThat(mdcAdapter.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP)).isNull(); + } + + @Test + public void testErrorLog() { + // given + MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, "2019-05-19T00:00:00.007Z"); + MDCAdapter mdcAdapter = MDC.getMDCAdapter(); + // when + flowLogOperation.errorLog(); + // then + assertThat(mdcAdapter.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP)).isNull(); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/loop/CsarInstallerItCase.java b/src/test/java/org/onap/clamp/loop/CsarInstallerItCase.java new file mode 100644 index 000000000..f986ca935 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/CsarInstallerItCase.java @@ -0,0 +1,312 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications copyright (c) 2019 Nokia + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import javax.transaction.Transactional; +import org.apache.commons.lang3.RandomStringUtils; +import org.json.JSONException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.clamp.clds.Application; +import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException; +import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException; +import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException; +import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact; +import org.onap.clamp.clds.sdc.controller.installer.CsarHandler; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.cds.CdsDataInstaller; +import org.onap.clamp.loop.service.ServicesRepository; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.LoopTemplateLoopElementModel; +import org.onap.clamp.loop.template.LoopTemplatesRepository; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.onap.sdc.api.notification.IArtifactInfo; +import org.onap.sdc.api.notification.INotificationData; +import org.onap.sdc.api.notification.IResourceInstance; +import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; +import org.onap.sdc.toscaparser.api.elements.Metadata; +import org.skyscreamer.jsonassert.JSONAssert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Commit; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@ActiveProfiles({"clamp-default", "clamp-default-user", "clamp-sdc-controller"}) +public class CsarInstallerItCase { + + private static final String CSAR_ARTIFACT_NAME_CDS = "example/sdc/service_Vloadbalancerms_cds.csar"; + private static final String CSAR_ARTIFACT_NAME_NO_CDS = "example/sdc/service_Vloadbalancerms_no_cds.csar"; + private static final String INVARIANT_SERVICE_UUID = "4cc5b45a-1f63-4194-8100-cd8e14248c92"; + private static final String INVARIANT_RESOURCE1_UUID = "07e266fc-49ab-4cd7-8378-ca4676f1b9ec"; + private static final String INVARIANT_RESOURCE2_UUID = "023a3f0d-1161-45ff-b4cf-8918a8ccf3ad"; + private static final String RESOURCE_INSTANCE_NAME_RESOURCE1 = "ResourceInstanceName1"; + private static final String RESOURCE_INSTANCE_NAME_RESOURCE2 = "ResourceInstanceName2"; + + @Autowired + private LoopTemplatesRepository loopTemplatesRepo; + + @Autowired + ServicesRepository serviceRepository; + + @Autowired + PolicyModelsRepository policyModelsRepository; + + @Autowired + @Qualifier("csarInstaller") + private CsarInstaller csarInstaller; + + private BlueprintArtifact buildFakeBuildprintArtifact(String instanceName, String invariantResourceUuid, + String blueprintFilePath, String artifactName, + String invariantServiceUuid) throws IOException { + IResourceInstance resource = Mockito.mock(IResourceInstance.class); + Mockito.when(resource.getResourceInstanceName()).thenReturn(instanceName); + Mockito.when(resource.getResourceInvariantUUID()).thenReturn(invariantResourceUuid); + BlueprintArtifact blueprintArtifact = Mockito.mock(BlueprintArtifact.class); + Mockito.when(blueprintArtifact.getDcaeBlueprint()) + .thenReturn(ResourceFileUtils.getResourceAsString(blueprintFilePath)); + Mockito.when(blueprintArtifact.getBlueprintArtifactName()).thenReturn(artifactName); + Mockito.when(blueprintArtifact.getBlueprintInvariantServiceUuid()).thenReturn(invariantServiceUuid); + Mockito.when(blueprintArtifact.getResourceAttached()).thenReturn(resource); + return blueprintArtifact; + } + + private CsarHandler buildBadFakeCsarHandler(String generatedName, String csarFileName) throws IOException, + SdcToscaParserException { + + // Build a Bad csar because the blueprint contains a link to a microservice that does not exist in the emulator + // Create fake notification + INotificationData notificationData = Mockito.mock(INotificationData.class); + Mockito.when(notificationData.getServiceVersion()).thenReturn("1.0"); + // Create fake resource in notification + CsarHandler csarHandler = Mockito.mock(CsarHandler.class); + List<IResourceInstance> listResources = new ArrayList<>(); + Mockito.when(notificationData.getResources()).thenReturn(listResources); + Map<String, BlueprintArtifact> blueprintMap = new HashMap<>(); + Mockito.when(csarHandler.getMapOfBlueprints()).thenReturn(blueprintMap); + // Create fake blueprint artifact 1 on resource1 + BlueprintArtifact blueprintArtifact = buildFakeBuildprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1, + INVARIANT_RESOURCE1_UUID, "example/sdc/blueprint-dcae/tca-guilin.yaml", "tca-guilin.yaml", + INVARIANT_SERVICE_UUID); + listResources.add(blueprintArtifact.getResourceAttached()); + blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact); + + // Build fake csarhandler + Mockito.when(csarHandler.getSdcNotification()).thenReturn(notificationData); + // Build fake csar Helper + ISdcCsarHelper csarHelper = Mockito.mock(ISdcCsarHelper.class); + Metadata data = Mockito.mock(Metadata.class); + Mockito.when(data.getValue("name")).thenReturn(generatedName); + Mockito.when(notificationData.getServiceName()).thenReturn(generatedName); + Mockito.when(csarHelper.getServiceMetadata()).thenReturn(data); + + // Create helper based on real csar to test policy yaml and global properties + // set + SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance(); + String path = Thread.currentThread().getContextClassLoader().getResource(csarFileName).getFile(); + ISdcCsarHelper sdcHelper = factory.getSdcCsarHelper(path); + Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(sdcHelper); + + // Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(csarHelper); + Mockito.when(csarHandler.getPolicyModelYaml()) + .thenReturn(Optional.ofNullable(ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml"))); + return csarHandler; + } + + private CsarHandler buildFakeCsarHandler(String generatedName, String csarFileName) throws IOException, + SdcToscaParserException { + // Create fake notification + INotificationData notificationData = Mockito.mock(INotificationData.class); + Mockito.when(notificationData.getServiceVersion()).thenReturn("1.0"); + // Create fake resource in notification + CsarHandler csarHandler = Mockito.mock(CsarHandler.class); + List<IResourceInstance> listResources = new ArrayList<>(); + Mockito.when(notificationData.getResources()).thenReturn(listResources); + Map<String, BlueprintArtifact> blueprintMap = new HashMap<>(); + Mockito.when(csarHandler.getMapOfBlueprints()).thenReturn(blueprintMap); + // Create fake blueprint artifact 1 on resource1 + BlueprintArtifact blueprintArtifact = buildFakeBuildprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1, + INVARIANT_RESOURCE1_UUID, "example/sdc/blueprint-dcae/tca.yaml", "tca.yaml", INVARIANT_SERVICE_UUID); + listResources.add(blueprintArtifact.getResourceAttached()); + blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact); + // Create fake blueprint artifact 2 on resource2 + blueprintArtifact = buildFakeBuildprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE2, INVARIANT_RESOURCE2_UUID, + "example/sdc/blueprint-dcae/tca_2.yaml", "tca_2.yaml", INVARIANT_SERVICE_UUID); + listResources.add(blueprintArtifact.getResourceAttached()); + blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact); + + // Create fake blueprint artifact 3 on resource 1 so that it's possible to + // test multiple CL deployment per Service/vnf + blueprintArtifact = buildFakeBuildprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1, INVARIANT_RESOURCE1_UUID, + "example/sdc/blueprint-dcae/tca_3.yaml", "tca_3.yaml", INVARIANT_SERVICE_UUID); + blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact); + + // Build fake csarhandler + Mockito.when(csarHandler.getSdcNotification()).thenReturn(notificationData); + // Build fake csar Helper + ISdcCsarHelper csarHelper = Mockito.mock(ISdcCsarHelper.class); + Metadata data = Mockito.mock(Metadata.class); + Mockito.when(data.getValue("name")).thenReturn(generatedName); + Mockito.when(notificationData.getServiceName()).thenReturn(generatedName); + Mockito.when(csarHelper.getServiceMetadata()).thenReturn(data); + + // Create helper based on real csar to test policy yaml and global properties + // set + SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance(); + String path = Thread.currentThread().getContextClassLoader().getResource(csarFileName).getFile(); + ISdcCsarHelper sdcHelper = factory.getSdcCsarHelper(path); + Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(sdcHelper); + + // Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(csarHelper); + Mockito.when(csarHandler.getPolicyModelYaml()) + .thenReturn(Optional.ofNullable(ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml"))); + return csarHandler; + } + + @Test + @Transactional + public void testGetPolicyModelYaml() throws IOException, SdcToscaParserException, CsarHandlerException { + INotificationData notificationData = Mockito.mock(INotificationData.class); + IArtifactInfo serviceArtifacts = Mockito.mock(IArtifactInfo.class); + Mockito.when(serviceArtifacts.getArtifactType()).thenReturn("TOSCA_CSAR"); + List<IArtifactInfo> serviceArtifactsList = new ArrayList<>(); + serviceArtifactsList.add(serviceArtifacts); + Mockito.when(notificationData.getServiceArtifacts()).thenReturn(serviceArtifactsList); + + CsarHandler csarHandler = new CsarHandler(notificationData, "", ""); + csarHandler + .setFilePath(Thread.currentThread().getContextClassLoader().getResource(CSAR_ARTIFACT_NAME_CDS). + getFile()); + Assert.assertEquals(csarHandler.getPolicyModelYaml(), Optional + .ofNullable(ResourceFileUtils.getResourceAsString("example/sdc/expected-result/policy-data.yaml"))); + } + + @Test + @Transactional + public void testIsCsarAlreadyDeployedTca() throws SdcArtifactInstallerException, SdcToscaParserException, + CsarHandlerException, IOException, InterruptedException, BlueprintParserException { + String generatedName = RandomStringUtils.randomAlphanumeric(5); + CsarHandler csarHandler = buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_CDS); + assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isFalse(); + csarInstaller.installTheCsar(csarHandler); + assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isTrue(); + } + + @Test + @Transactional + public void testWithoutCdsTca() throws SdcArtifactInstallerException, SdcToscaParserException, + CsarHandlerException, IOException, InterruptedException, BlueprintParserException { + String generatedName = RandomStringUtils.randomAlphanumeric(5); + CsarHandler csarHandler = buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_NO_CDS); + + assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isFalse(); + csarInstaller.installTheCsar(csarHandler); + assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isTrue(); + } + + @Test(expected = SdcArtifactInstallerException.class) + @Transactional + public void testInstallTheBadCsarTca() + throws IOException, SdcToscaParserException, InterruptedException, BlueprintParserException, + SdcArtifactInstallerException { + // This test validates that the blueprint is well rejected because the blueprint contains a link + // to a policy that does not exist on the policy engine emulator. + String generatedName = RandomStringUtils.randomAlphanumeric(5); + csarInstaller.installTheCsar(buildBadFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_NO_CDS)); + } + + @Test + @Transactional + @Commit + public void testInstallTheCsarTca() throws SdcArtifactInstallerException, SdcToscaParserException, + CsarHandlerException, IOException, JSONException, InterruptedException, BlueprintParserException { + String generatedName = RandomStringUtils.randomAlphanumeric(5); + csarInstaller.installTheCsar(buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_CDS)); + + assertThat(serviceRepository.existsById("63cac700-ab9a-4115-a74f-7eac85e3fce0")).isTrue(); + // We should have CDS info + assertThat(serviceRepository.findById("63cac700-ab9a-4115-a74f-7eac85e3fce0").get().getResourceByType("VF") + .getAsJsonObject("vLoadBalancerMS 0").getAsJsonObject( + CdsDataInstaller.CONTROLLER_PROPERTIES)).isNotNull(); + assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0", + RESOURCE_INSTANCE_NAME_RESOURCE1, "tca.yaml"))).isTrue(); + assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0", + RESOURCE_INSTANCE_NAME_RESOURCE1, "tca_3.yaml"))).isTrue(); + assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0", + RESOURCE_INSTANCE_NAME_RESOURCE2, "tca_2.yaml"))).isTrue(); + // Verify now that policy and json representation, global properties are well + // set + LoopTemplate loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName, + "1.0", RESOURCE_INSTANCE_NAME_RESOURCE1, "tca.yaml")).get(); + assertThat(loopTemplate.getLoopElementModelsUsed()).hasSize(1); + assertThat(loopTemplate.getModelService().getServiceUuid()).isEqualTo("63cac700-ab9a-4115-a74f-7eac85e3fce0"); + JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/model-properties.json"), + JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService()), true); + JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/service-details.json"), + JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService().getServiceDetails()), true); + JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/resource-details.json"), + JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService().getResourceDetails()), true); + assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0])) + .getLoopElementModel().getName()).isNotEmpty(); + + loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0", + RESOURCE_INSTANCE_NAME_RESOURCE1, "tca_3.yaml")).get(); + assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0])) + .getLoopElementModel().getName()).isNotEmpty(); + assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0])) + .getLoopElementModel().getName()).isNotEmpty(); + assertThat(loopTemplate.getMaximumInstancesAllowed()).isEqualByComparingTo(Integer.valueOf(0)); + loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0", + RESOURCE_INSTANCE_NAME_RESOURCE2, "tca_2.yaml")).get(); + assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0])) + .getLoopElementModel().getName()).isNotEmpty(); + + assertThat(policyModelsRepository.findAll().size()).isGreaterThanOrEqualTo(1); + assertThat(policyModelsRepository + .existsById(new PolicyModelId("onap.policies.monitoring.cdap.tca.hi.lo.app", "1.0.0"))).isTrue(); + assertThat(policyModelsRepository + .getOne((new PolicyModelId("onap.policies.monitoring.cdap.tca.hi.lo.app", "1.0.0"))) + .getPolicyModelTosca()).isNotBlank(); + } +} diff --git a/src/test/java/org/onap/clamp/loop/DcaeComponentTest.java b/src/test/java/org/onap/clamp/loop/DcaeComponentTest.java new file mode 100644 index 000000000..022d10eb2 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/DcaeComponentTest.java @@ -0,0 +1,214 @@ +/*- + * ============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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.List; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.json.simple.parser.ParseException; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.clamp.clds.model.dcae.DcaeInventoryResponse; +import org.onap.clamp.clds.model.dcae.DcaeOperationStatusResponse; +import org.onap.clamp.loop.components.external.DcaeComponent; +import org.onap.clamp.loop.components.external.ExternalComponentState; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.policy.microservice.MicroServicePolicy; + +public class DcaeComponentTest { + + private Loop createTestLoop() { + Loop loopTest = new Loop("ControlLoopTest"); + loopTest.setGlobalPropertiesJson( + new Gson().fromJson( + "{\"dcaeDeployParameters\":{\"uniqueBlueprintParameters\": {\"policy_id\": \"name\"}}}", + JsonObject.class)); + loopTest.setLastComputedState(LoopState.DESIGN); + loopTest.setDcaeDeploymentId("123456789"); + loopTest.setDcaeDeploymentStatusUrl("http4://localhost:8085"); + + MicroServicePolicy microServicePolicy = new MicroServicePolicy("configPolicyTest", new PolicyModel("policy1", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0"), true, + new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, null, null); + microServicePolicy.setConfigurationsJson(new Gson().fromJson("{\"param1\":\"value1\"}", JsonObject.class)); + + loopTest.addMicroServicePolicy(microServicePolicy); + LoopTemplate loopTemplate = new LoopTemplate("test", "yaml", 1, null); + loopTemplate.setDcaeBlueprintId("UUID-blueprint"); + loopTest.setLoopTemplate(loopTemplate); + + return loopTest; + } + + /** + * Test the DcaeReponse roughly. + * + * @throws IOException In case of issues + */ + @Test + public void convertDcaeResponseTest() throws IOException { + String dcaeFakeResponse = "{'requestId':'testId','operationType':'install','status':'state'," + + "'error':'errorMessage', 'links':{'self':'selfUrl','uninstall':'uninstallUrl'}}"; + DcaeOperationStatusResponse responseObject = DcaeComponent.convertDcaeResponse(dcaeFakeResponse); + assertThat(responseObject.getRequestId()).isEqualTo("testId"); + assertThat(responseObject.getOperationType()).isEqualTo("install"); + assertThat(responseObject.getStatus()).isEqualTo("state"); + assertThat(responseObject.getError()).isEqualTo("errorMessage"); + assertThat(responseObject.getLinks()).isNotNull(); + assertThat(responseObject.getLinks().getSelf()).isEqualTo("selfUrl"); + assertThat(responseObject.getLinks().getUninstall()).isEqualTo("uninstallUrl"); + + assertThat(responseObject.getLinks().getStatus()).isNull(); + } + + @Test + public void testGetDeployPayload() throws IOException { + Loop loop = this.createTestLoop(); + String deploymentPayload = DcaeComponent.getDeployPayload(loop); + String expectedPayload = "{\"serviceTypeId\":\"UUID-blueprint\",\"inputs\":{\"policy_id\":\"name\"}}"; + assertThat(deploymentPayload).isEqualTo(expectedPayload); + } + + @Test + public void testGetUndeployPayload() throws IOException { + Loop loop = this.createTestLoop(); + String unDeploymentPayload = DcaeComponent.getUndeployPayload(loop); + String expectedPayload = "{\"serviceTypeId\":\"UUID-blueprint\"}"; + assertThat(unDeploymentPayload).isEqualTo(expectedPayload); + } + + /** + * Test the computeState method of the DcaeComponent roughly. + * + * @throws IOException In case of issues + */ + @Test + public void computeStateTest() throws IOException { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(null); + + DcaeComponent dcae = new DcaeComponent(); + + // initial state + ExternalComponentState state = dcae.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("BLUEPRINT_DEPLOYED"); + + // OperationalType = install + DcaeOperationStatusResponse dcaeResponse = Mockito.mock(DcaeOperationStatusResponse.class); + Mockito.when(dcaeResponse.getOperationType()).thenReturn("install"); + + Mockito.when(dcaeResponse.getStatus()).thenReturn("succeeded"); + Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(dcaeResponse); + ExternalComponentState state2 = dcae.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("MICROSERVICE_INSTALLED_SUCCESSFULLY"); + Mockito.when(dcaeResponse.getStatus()).thenReturn("processing"); + ExternalComponentState state3 = dcae.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("PROCESSING_MICROSERVICE_INSTALLATION"); + + Mockito.when(dcaeResponse.getStatus()).thenReturn("failed"); + ExternalComponentState state4 = dcae.computeState(exchange); + assertThat(state4.getStateName()).isEqualTo("MICROSERVICE_INSTALLATION_FAILED"); + + // OperationalType = uninstall + Mockito.when(dcaeResponse.getOperationType()).thenReturn("uninstall"); + + Mockito.when(dcaeResponse.getStatus()).thenReturn("succeeded"); + Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(dcaeResponse); + ExternalComponentState state5 = dcae.computeState(exchange); + assertThat(state5.getStateName()).isEqualTo("MICROSERVICE_UNINSTALLED_SUCCESSFULLY"); + + Mockito.when(dcaeResponse.getStatus()).thenReturn("processing"); + ExternalComponentState state6 = dcae.computeState(exchange); + assertThat(state6.getStateName()).isEqualTo("PROCESSING_MICROSERVICE_UNINSTALLATION"); + + Mockito.when(dcaeResponse.getStatus()).thenReturn("failed"); + ExternalComponentState state7 = dcae.computeState(exchange); + assertThat(state7.getStateName()).isEqualTo("MICROSERVICE_UNINSTALLATION_FAILED"); + + // error cases + Mockito.when(dcaeResponse.getOperationType()).thenReturn("whatever"); + ExternalComponentState state8 = dcae.computeState(exchange); + assertThat(state8.getStateName()).isEqualTo("IN_ERROR"); + + Mockito.when(dcaeResponse.getOperationType()).thenReturn("install"); + Mockito.when(dcaeResponse.getStatus()).thenReturn("anythingelse"); + ExternalComponentState state9 = dcae.computeState(exchange); + assertThat(state9.getStateName()).isEqualTo("IN_ERROR"); + } + + /** + * Test the Converter to DcaeInventoryResponse method. + * + * @throws IOException In case of failure + * @throws ParseException In case of failure + */ + @Test + public void convertToDcaeInventoryResponseTest() throws IOException, ParseException { + String dcaeFakeResponse = "{\n" + " \"links\": {\n" + " \"previousLink\": {\n" + + " \"title\": \"string\",\n" + " \"rel\": \"string\",\n" + " \"uri\": \"string\",\n" + + " \"uriBuilder\": {},\n" + " \"rels\": [\n" + " \"string\"\n" + " ],\n" + + " \"params\": {\n" + " \"additionalProp1\": \"string\",\n" + + " \"additionalProp2\": \"string\",\n" + " \"additionalProp3\": \"string\"\n" + + " },\n" + " \"type\": \"string\"\n" + " },\n" + " \"nextLink\": {\n" + + " \"title\": \"string\",\n" + " \"rel\": \"string\",\n" + " \"uri\": \"string\",\n" + + " \"uriBuilder\": {},\n" + " \"rels\": [\n" + " \"string\"\n" + " ],\n" + + " \"params\": {\n" + " \"additionalProp1\": \"string\",\n" + + " \"additionalProp2\": \"string\",\n" + " \"additionalProp3\": \"string\"\n" + + " },\n" + " \"type\": \"string\"\n" + " }\n" + " },\n" + " \"totalCount\": 0,\n" + + " \"items\": [\n" + " {\n" + " \"owner\": \"testOwner\",\n" + + " \"application\": \"testApplication\",\n" + " \"component\": \"testComponent\",\n" + + " \"typeName\": \"testTypeName\",\n" + " \"typeVersion\": 0,\n" + + " \"blueprintTemplate\": \"testBlueprintTemplate\",\n" + " \"serviceIds\": [\n" + + " \"serviceId1\", \"serviceId2\"\n" + " ],\n" + " \"vnfTypes\": [\n" + + " \"vnfType1\", \"vnfType2\"\n" + " ],\n" + " \"serviceLocations\": [\n" + + " \"serviceLocation1\", \"serviceLocation2\"\n" + " ],\n" + + " \"asdcServiceId\": \"testAsdcServiceId\",\n" + + " \"asdcResourceId\": \"testAsdcResourceId\",\n" + + " \"asdcServiceURL\": \"testAsdcServiceURL\",\n" + " \"typeId\": \"testTypeId\",\n" + + " \"selfLink\": {\n" + " \"title\": \"selfLinkTitle\",\n" + + " \"rel\": \"selfLinkRel\",\n" + " \"uri\": \"selfLinkUri\",\n" + + " \"uriBuilder\": {},\n" + " \"rels\": [\n" + " \"string\"\n" + " ],\n" + + " \"params\": {\n" + " \"additionalProp1\": \"string\",\n" + + " \"additionalProp2\": \"string\",\n" + " \"additionalProp3\": \"string\"\n" + + " },\n" + " \"type\": \"string\"\n" + " },\n" + + " \"created\": \"2020-01-22T09:38:15.436Z\",\n" + + " \"deactivated\": \"2020-01-22T09:38:15.437Z\"\n" + " }\n" + " ]\n" + "}"; + List<DcaeInventoryResponse> responseObject = DcaeComponent.convertToDcaeInventoryResponse(dcaeFakeResponse); + assertThat(responseObject.get(0).getAsdcResourceId()).isEqualTo("testAsdcResourceId"); + assertThat(responseObject.get(0).getAsdcServiceId()).isEqualTo("testAsdcServiceId"); + assertThat(responseObject.get(0).getTypeName()).isEqualTo("testTypeName"); + assertThat(responseObject.get(0).getTypeId()).isEqualTo("testTypeId"); + assertThat(responseObject.get(0).getBlueprintTemplate()).isEqualTo("testBlueprintTemplate"); + } +} diff --git a/src/test/java/org/onap/clamp/loop/DeployFlowTestItCase.java b/src/test/java/org/onap/clamp/loop/DeployFlowTestItCase.java new file mode 100644 index 000000000..169db9db1 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/DeployFlowTestItCase.java @@ -0,0 +1,321 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import java.io.IOException; +import java.util.Set; +import javax.transaction.Transactional; +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.builder.ExchangeBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelsService; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class DeployFlowTestItCase { + private Gson gson = new Gson(); + + @Autowired + CamelContext camelContext; + + @Autowired + PolicyModelsService policyModelsService; + + @Autowired + LoopService loopService; + + @Autowired + LoopsRepository loopsRepository; + + /** + * This method tests a deployment a single blueprint. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void deployWithSingleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", + "{\"dcaeDeployParameters\":{\"uniqueBlueprintParameters\": {\"policy_id\": \"name\"}}}", + "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + template.setBlueprint("yamlcontent"); + loopTest.setLoopTemplate(template); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + loopTest.addMicroServicePolicy(microServicePolicy); + loopService.saveOrUpdateLoop(loopTest); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest) + .build(); + + camelContext.createProducerTemplate().send("direct:deploy-loop", myCamelExchange); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest"); + assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNotNull(); + assertThat(loopAfterTest.getDcaeDeploymentId()).isNotNull(); + } + + /** + * This method tests the deployment of multiple separated blueprints. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void deployWithMultipleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest2 = createLoop("ControlLoopTest2", "yamlcontent", "{\"dcaeDeployParameters\": {" + + "\"microService1\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName1_tca\"}," + + "\"microService2\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName2_tca\"}" + + "}}", "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + loopTest2.setLoopTemplate(template); + MicroServicePolicy microServicePolicy1 = getMicroServicePolicy("microService1", "", "{\"configtype\":\"json\"}", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true); + MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("microService2", "", "{\"configtype\":\"json\"}", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true); + loopTest2.addMicroServicePolicy(microServicePolicy1); + loopTest2.addMicroServicePolicy(microServicePolicy2); + loopsRepository.saveAndFlush(loopTest2); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest2) + .build(); + + camelContext.createProducerTemplate().send("direct:deploy-loop", myCamelExchange); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest2"); + Set<MicroServicePolicy> policyList = loopAfterTest.getMicroServicePolicies(); + for (MicroServicePolicy policy : policyList) { + assertThat(policy.getDcaeDeploymentStatusUrl()).isNotNull(); + assertThat(policy.getDcaeDeploymentId()).isNotNull(); + } + assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNull(); + assertThat(loopAfterTest.getDcaeDeploymentId()).isNull(); + } + + /** + * This method tests the undeployment of a single blueprint. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void undeployWithSingleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + template.setBlueprint("yamlcontent"); + loopTest.setLoopTemplate(template); + loopTest.setDcaeDeploymentId("testDeploymentId"); + loopTest.setDcaeDeploymentStatusUrl("testUrl"); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + loopTest.addMicroServicePolicy(microServicePolicy); + loopService.saveOrUpdateLoop(loopTest); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest) + .build(); + + camelContext.createProducerTemplate().send("direct:undeploy-loop", myCamelExchange); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest"); + assertThat(loopAfterTest.getDcaeDeploymentStatusUrl().contains("/uninstall")).isTrue(); + assertThat(loopAfterTest.getDcaeDeploymentId()).isNull(); + } + + /** + * This method tests the undeployment of multiple separated blueprints. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void undeployWithMultipleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest2 = createLoop("ControlLoopTest2", "yamlcontent", "{\"dcaeDeployParameters\": {" + + "\"microService1\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName1_tca\"}," + + "\"microService2\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName2_tca\"}" + + "}}", "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + loopTest2.setLoopTemplate(template); + MicroServicePolicy microServicePolicy1 = getMicroServicePolicy("microService1", "", "{\"configtype\":\"json\"}", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true, + "testDeploymentId1", "testDeploymentStatusUrl1"); + MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("microService2", "", "{\"configtype\":\"json\"}", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true, + "testDeploymentId2", "testDeploymentStatusUrl2"); + loopTest2.addMicroServicePolicy(microServicePolicy1); + loopTest2.addMicroServicePolicy(microServicePolicy2); + loopsRepository.saveAndFlush(loopTest2); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest2) + .build(); + + camelContext.createProducerTemplate().send("direct:undeploy-loop", myCamelExchange); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest2"); + Set<MicroServicePolicy> policyList = loopAfterTest.getMicroServicePolicies(); + for (MicroServicePolicy policy : policyList) { + assertThat(policy.getDcaeDeploymentStatusUrl().contains("/uninstall")).isTrue(); + assertThat(policy.getDcaeDeploymentId()).isNull(); + + } + assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNull(); + assertThat(loopAfterTest.getDcaeDeploymentId()).isNull(); + } + + /** + * This method tests the DCAE get status for a single blueprint. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void getStatusWithSingleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + template.setBlueprint("yamlcontent"); + loopTest.setLoopTemplate(template); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + loopTest.addMicroServicePolicy(microServicePolicy); + loopService.saveOrUpdateLoop(loopTest); + assertThat(loopTest.getComponents().size()).isEqualTo(2); + assertThat(loopTest.getComponent("DCAE")).isNotNull(); + assertThat(loopTest.getComponent("POLICY")).isNotNull(); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest) + .build(); + + camelContext.createProducerTemplate().send("direct:update-dcae-status-for-loop", myCamelExchange); + + assertThat(loopTest.getComponent("DCAE").getState().getStateName()).isEqualTo("BLUEPRINT_DEPLOYED"); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest"); + assertThat(loopAfterTest.getComponents().size()).isEqualTo(2); + assertThat(loopAfterTest.getComponent("DCAE")).isNotNull(); + assertThat(loopAfterTest.getComponent("POLICY")).isNotNull(); + } + + /** + * This method tests the dcae get status for multiple blueprints. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + */ + @Test + @Transactional + public void getStatusWithMultipleBlueprintTest() throws JsonSyntaxException, IOException { + Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "UUID-blueprint"); + LoopTemplate template = new LoopTemplate(); + template.setName("templateName"); + loopTest.setLoopTemplate(template); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("configPolicyTest2", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + loopTest.addMicroServicePolicy(microServicePolicy); + loopTest.addMicroServicePolicy(microServicePolicy2); + loopService.saveOrUpdateLoop(loopTest); + assertThat(loopTest.getComponents().size()).isEqualTo(3); + assertThat(loopTest.getComponent("DCAE")).isNull(); + assertThat(loopTest.getComponent("DCAE_configPolicyTest")).isNotNull(); + assertThat(loopTest.getComponent("DCAE_configPolicyTest2")).isNotNull(); + assertThat(loopTest.getComponent("POLICY")).isNotNull(); + Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest) + .build(); + + camelContext.createProducerTemplate().send("direct:update-dcae-status-for-loop", myCamelExchange); + + assertThat(loopTest.getComponent("DCAE_configPolicyTest").getState().getStateName()) + .isEqualTo("BLUEPRINT_DEPLOYED"); + assertThat(loopTest.getComponent("DCAE_configPolicyTest2").getState().getStateName()) + .isEqualTo("BLUEPRINT_DEPLOYED"); + + Loop loopAfterTest = loopService.getLoop("ControlLoopTest"); + assertThat(loopAfterTest.getComponents().size()).isEqualTo(3); + assertThat(loopAfterTest.getComponent("DCAE")).isNull(); + assertThat(loopAfterTest.getComponent("POLICY")).isNotNull(); + assertThat(loopTest.getComponent("DCAE_configPolicyTest")).isNotNull(); + assertThat(loopTest.getComponent("DCAE_configPolicyTest2")).isNotNull(); + } + + private Loop createLoop(String name, String blueprint, String globalPropertiesJson, + String dcaeBlueprintId) throws JsonSyntaxException, IOException { + Loop loop = new Loop(name); + loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class)); + loop.setLastComputedState(LoopState.DESIGN); + return loop; + } + + private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation, + String policyTosca, String jsonProperties, boolean shared) { + + PolicyModel policyModel = new PolicyModel(modelType, policyTosca, "1.0.0"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + MicroServicePolicy microService = new MicroServicePolicy(name, policyModel, + shared, + gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null); + + microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class)); + return microService; + } + + private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation, + String policyTosca, String jsonProperties, boolean shared, + String deploymengId, + String deploymentStatusUrl) { + MicroServicePolicy microService = getMicroServicePolicy(name, modelType, jsonRepresentation, policyTosca, + jsonProperties, shared); + + microService.setDcaeDeploymentId(deploymengId); + microService.setDcaeDeploymentStatusUrl(deploymentStatusUrl); + return microService; + } +} diff --git a/src/test/java/org/onap/clamp/loop/ExternalComponentStateTest.java b/src/test/java/org/onap/clamp/loop/ExternalComponentStateTest.java new file mode 100644 index 000000000..34fcc077f --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/ExternalComponentStateTest.java @@ -0,0 +1,82 @@ +/*- + * ============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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.onap.clamp.loop.components.external.ExternalComponentState; + +public class ExternalComponentStateTest { + private ExternalComponentState state = new ExternalComponentState("NOT_SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + + @Test + public void generalTest() { + assertThat(state.toString()).isEqualTo("NOT_SENT"); + state.setLevel(70); + assertThat(state.getLevel()).isEqualTo(70); + } + + @Test + public void equalsTest() { + assertThat(state.equals(null)).isEqualTo(false); + + ExternalComponentState state2 = new ExternalComponentState("NOT_SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + assertThat(state.equals(state2)).isEqualTo(true); + + assertThat(state.equals(12)).isEqualTo(false); + + state2.setLevel(70); + assertThat(state.equals(state2)).isEqualTo(true); + + ExternalComponentState state3 = new ExternalComponentState("SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + assertThat(state.equals(state3)).isEqualTo(false); + + ExternalComponentState state4 = new ExternalComponentState(null, + "The policies defined have NOT yet been created on the policy engine", 90); + ExternalComponentState state5 = new ExternalComponentState(null, + "The policies defined have NOT yet been", 50); + assertThat(state4.equals(state3)).isEqualTo(false); + assertThat(state4.equals(state5)).isEqualTo(true); + } + + @Test + public void compareToTest() { + ExternalComponentState state2 = new ExternalComponentState("NOT_SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + assertThat(state.compareTo(state2)).isEqualTo(0); + + ExternalComponentState state3 = new ExternalComponentState("SENT", + "The policies defined have NOT yet been created on the policy engine", 50); + assertThat(state.compareTo(state3)).isEqualTo(1); + + ExternalComponentState state4 = new ExternalComponentState(null, + "The policies defined have NOT yet been created on the policy engine", 100); + assertThat(state.compareTo(state4)).isEqualTo(-1); + + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/loop/LoopControllerTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopControllerTestItCase.java new file mode 100644 index 000000000..f170bc6df --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopControllerTestItCase.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights + * reserved. + * Modifications Copyright (C) 2019 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.IOException; +import java.util.Set; +import javax.transaction.Transactional; +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.service.Service; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelsService; +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; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class LoopControllerTestItCase { + + private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest"; + private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}"; + + @Autowired + LoopService loopService; + + @Autowired + LoopsRepository loopsRepository; + + @Autowired + MicroServicePolicyService microServicePolicyService; + + @Autowired + OperationalPolicyService operationalPolicyService; + + @Autowired + PolicyModelsService policyModelsService; + + @Autowired + LoopController loopController; + + private void saveTestLoopToDb() { + Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, "blueprint", "representation"); + testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class)); + LoopTemplate template = new LoopTemplate(); + template.setName("testTemplate"); + testLoop.setLoopTemplate(template); + Service modelService = new Service("{\"name\":\"serviceName\",\"UUID\":\"uuid\"}", "{}"); + testLoop.setModelService(modelService); + loopService.saveOrUpdateLoop(testLoop); + } + + private Loop createTestLoop(String loopName, String loopBlueprint, String loopSvg) { + return new Loop(loopName); + } + + @Test + @Transactional + public void testUpdateOperationalPolicies() { + saveTestLoopToDb(); + String policy = "[{\"name\":\"OPERATIONAL_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules\"," + + "\"configurationsJson\":{" + + "\"operational_policy\":{\"controlLoop\":{\"trigger_policy\":\"unique-policy-id-1-modifyConfig\"," + + "\"timeout\":\"3600\",\"abatement\":\"false\"," + + "\"controlLoopName\":\"LOOP_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules\"}," + + "\"policies\":[{\"id\":\"unique-policy-id-1-modifyConfig\",\"recipe\":\"ModifyConfig\"," + + "\"retry\":\"2\",\"timeout\":\"1200\",\"actor\":\"APPC\",\"payload\":\"{\\\"active-streams\\\":5}\"," + + "\"success\":\"\",\"failure\":\"\",\"failure_timeout\":\"\",\"failure_retries\":\"\"," + + "\"failure_exception\":\"\",\"failure_guard\":\"\",\"target\":{\"type\":\"VNF\"," + + "\"resourceID\":\"vFW_PG_T1\"}}]}}}]"; + JsonParser parser = new JsonParser(); + JsonElement ele = parser.parse(policy); + JsonArray arr = ele.getAsJsonArray(); + Loop loop = loopController.updateOperationalPolicies(EXAMPLE_LOOP_NAME, arr); + assertThat(loop.getOperationalPolicies()).hasSize(1); + Set<OperationalPolicy> opSet = loop.getOperationalPolicies(); + OperationalPolicy op = opSet.iterator().next(); + assertThat(op.getName()).isEqualTo("OPERATIONAL_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules"); + } + + @Test + @Transactional + public void testUpdateGlobalProperties() { + saveTestLoopToDb(); + String policy = "{\"dcaeDeployParameters\":{\"aaiEnrichmentHost\":\"aai.onap.svc.cluster.local\"," + + "\"aaiEnrichmentPort\":\"8443\",\"enableAAIEnrichment\":\"false\",\"dmaap_host\":\"message-router" + + ".onap\",\"dmaap_port\":\"3904\",\"enableRedisCaching\":\"false\",\"redisHosts\":\"dcae-redis.onap" + + ".svc.cluster.local:6379\",\"tag_version\":\"nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments" + + ".tca-cdap-container:1.1.1\",\"consul_host\":\"consul-server.onap\",\"consul_port\":\"8500\"," + + "\"cbs_host\":\"config-binding-service\",\"cbs_port\":\"10000\",\"external_port\":\"32012\"," + + "\"policy_model_id\":\"onap.policies.monitoring.cdap.tca.hi.lo.app\"," + + "\"policy_id\":\"tca_k8s_CLTCA_v1_0_vFW_PG_T10_k8s-tca-clamp-policy-05162019\"}}"; + JsonParser parser = new JsonParser(); + JsonElement ele = parser.parse(policy); + JsonObject obj = ele.getAsJsonObject(); + loopController.updateGlobalPropertiesJson(EXAMPLE_LOOP_NAME, obj); + Loop loop = loopController.getLoop(EXAMPLE_LOOP_NAME); + JsonObject globalPropertiesJson = loop.getGlobalPropertiesJson(); + JsonObject prop = globalPropertiesJson.getAsJsonObject("dcaeDeployParameters"); + assertThat(prop.get("aaiEnrichmentHost").getAsString()).isEqualTo("aai.onap.svc.cluster.local"); + } + + @Test + @Transactional + public void testUpdateMicroservicePolicy() { + saveTestLoopToDb(); + PolicyModel policyModel = new PolicyModel("testPolicyModel", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + MicroServicePolicy policy = new MicroServicePolicy("policyName", policyModel, false, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + loopController.updateMicroservicePolicy(EXAMPLE_LOOP_NAME, policy); + assertThat(microServicePolicyService.isExisting("policyName")).isTrue(); + } + + @Test + @Transactional + public void testAddAndRemoveOperationalPolicies() throws IOException { + saveTestLoopToDb(); + PolicyModel policyModel = new PolicyModel("testPolicyModel", + null, "1.0.0"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + + loopController.addOperationalPolicy(EXAMPLE_LOOP_NAME, "testPolicyModel", "1.0.0"); + + Loop newLoop = loopController.getLoop(EXAMPLE_LOOP_NAME); + Set<OperationalPolicy> opPolicyList = newLoop.getOperationalPolicies(); + assertThat(opPolicyList.size()).isEqualTo(1); + for (OperationalPolicy policy : opPolicyList) { + assertThat(policy.getName().contains("OPERATIONAL_serviceName")).isTrue(); + assertThat(policy.getPolicyModel().getPolicyModelType()).isEqualTo("testPolicyModel"); + assertThat(policy.getPolicyModel().getVersion()).isEqualTo("1.0.0"); + } + + loopController.removeOperationalPolicy(EXAMPLE_LOOP_NAME, "testPolicyModel", "1.0.0"); + Loop newLoop2 = loopController.getLoop(EXAMPLE_LOOP_NAME); + assertThat(newLoop2.getOperationalPolicies().size()).isEqualTo(0); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/loop/LoopLogServiceTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopLogServiceTestItCase.java new file mode 100644 index 000000000..ddab7b659 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopLogServiceTestItCase.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; +import java.util.Set; +import javax.transaction.Transactional; +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.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class LoopLogServiceTestItCase { + + private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest"; + private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}"; + private static final String CLAMP_COMPONENT = "CLAMP"; + private static final String SAMPLE_LOG_MESSAGE = "Sample log"; + private static final String BLUEPRINT = "blueprint"; + + @Autowired + LoopService loopService; + + @Autowired + LoopsRepository loopsRepository; + + @Autowired + LoopLogService loopLogService; + + private void saveTestLoopToDb() { + Loop testLoop = new Loop(EXAMPLE_LOOP_NAME); + testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class)); + loopService.saveOrUpdateLoop(testLoop); + } + + @Test + @Transactional + public void testAddLog() { + saveTestLoopToDb(); + Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME); + loopLogService.addLog(SAMPLE_LOG_MESSAGE, "INFO", loop); + Set<LoopLog> loopLogs = loop.getLoopLogs(); + assertThat(loopLogs).hasSize(1); + LoopLog loopLog = loopLogs.iterator().next(); + assertThat(loopLog.getMessage()).isEqualTo(SAMPLE_LOG_MESSAGE); + } + + @Test + @Transactional + public void testLoopLog() { + LoopLog log = new LoopLog(); + Long id = Long.valueOf(100); + log.setId(id); + log.setLogComponent(CLAMP_COMPONENT); + log.setLogType(LogType.INFO); + log.setMessage(SAMPLE_LOG_MESSAGE); + Loop testLoop = new Loop(EXAMPLE_LOOP_NAME); + log.setLoop(testLoop); + assertThat(log.getMessage()).isEqualTo(SAMPLE_LOG_MESSAGE); + assertThat(log.getLogType()).isEqualTo(LogType.INFO); + assertThat(log.getLogComponent()).isEqualTo(CLAMP_COMPONENT); + assertThat(log.getId()).isEqualTo(id); + assertThat(log.getLoop()).isEqualTo(testLoop); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/loop/LoopRepositoriesItCase.java b/src/test/java/org/onap/clamp/loop/LoopRepositoriesItCase.java new file mode 100644 index 000000000..9815575cc --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopRepositoriesItCase.java @@ -0,0 +1,253 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import java.time.Instant; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.onap.clamp.loop.log.LogType; +import org.onap.clamp.loop.log.LoopLog; +import org.onap.clamp.loop.log.LoopLogRepository; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.service.ServicesRepository; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopElementModelsRepository; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.LoopTemplatesRepository; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsRepository; +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.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class LoopRepositoriesItCase { + + private Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create(); + + @Autowired + private LoopsRepository loopRepository; + + @Autowired + private MicroServicePolicyService microServicePolicyService; + + @Autowired + private OperationalPolicyService operationalPolicyService; + + @Autowired + private LoopLogRepository loopLogRepository; + + @Autowired + private LoopTemplatesRepository loopTemplateRepository; + + @Autowired + private LoopElementModelsRepository microServiceModelsRepository; + + @Autowired + private PolicyModelsRepository policyModelsRepository; + + @Autowired + private ServicesRepository servicesRepository; + + private Service getService(String serviceDetails, String resourceDetails) { + return new Service(serviceDetails, resourceDetails); + } + + private OperationalPolicy getOperationalPolicy(String configJson, String name, PolicyModel policyModel) { + return new OperationalPolicy(name, null, new Gson().fromJson(configJson, JsonObject.class), policyModel, + null, null, null); + } + + private LoopElementModel getLoopElementModel(String yaml, String name, String policyType, String createdBy, + PolicyModel policyModel) { + LoopElementModel model = new LoopElementModel(name, policyType, yaml); + model.addPolicyModel(policyModel); + return model; + } + + private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, + String policyAcronym) { + return new PolicyModel(policyType, policyModelTosca, version, policyAcronym); + } + + private LoopTemplate getLoopTemplates(String name, String blueprint, String createdBy, + Integer maxInstancesAllowed) { + LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null); + template.addLoopElementModel(getLoopElementModel("yaml", "microService1", "org.onap.policy.drools", createdBy, + getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools"))); + template.addLoopElementModel(getLoopElementModel("yaml", "oppolicy1", "org.onap.policy.drools.legacy", + createdBy, getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "DroolsLegacy"))); + loopTemplateRepository.save(template); + return template; + } + + private Loop getLoop(String name, String blueprint, String globalPropertiesJson, + String dcaeId, String dcaeUrl, String dcaeBlueprintId) { + Loop loop = new Loop(); + loop.setName(name); + loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class)); + loop.setLastComputedState(LoopState.DESIGN); + loop.setDcaeDeploymentId(dcaeId); + loop.setDcaeDeploymentStatusUrl(dcaeUrl); + loop.setLoopTemplate(getLoopTemplates("templateName", "yaml", "toto", 1)); + return loop; + } + + private MicroServicePolicy getMicroServicePolicy(String name, String jsonRepresentation, String jsonProperties, + boolean shared, PolicyModel policyModel) { + MicroServicePolicy microService = new MicroServicePolicy(name, policyModel, shared, + gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null); + microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class)); + return microService; + } + + private LoopLog getLoopLog(LogType type, String message, Loop loop) { + return new LoopLog(message, type, "CLAMP", loop); + } + + /** + * This method does a crud test and save a loop template and a loop object in db. + */ + @Test + @Transactional + public void crudTest() { + // Setup + Loop loopTest = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "123456789", "https://dcaetest.org", "UUID-blueprint"); + OperationalPolicy opPolicy = this.getOperationalPolicy("{\"type\":\"GUARD\"}", "GuardOpPolicyTest", + getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "DroolsLegacy")); + loopTest.addOperationalPolicy(opPolicy); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "{\"configtype\":\"json\"}", + "{\"param1\":\"value1\"}", true, getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools")); + loopTest.addMicroServicePolicy(microServicePolicy); + LoopLog loopLog = getLoopLog(LogType.INFO, "test message", loopTest); + loopTest.addLog(loopLog); + Service service = getService( + "{\"name\": \"vLoadBalancerMS\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}", "{\"CP\": {}}"); + loopTest.setModelService(service); + + // Attempt to save into the database the entire loop + Loop loopInDb = loopRepository.save(loopTest); + assertThat(loopInDb).isNotNull(); + assertThat(loopRepository.findById(loopInDb.getName()).get()).isNotNull(); + assertThat(loopInDb.getCreatedDate()).isNotNull(); + assertThat(loopInDb.getUpdatedDate()).isNotNull(); + assertThat(loopInDb.getUpdatedDate()).isEqualTo(loopInDb.getCreatedDate()); + assertThat(loopInDb.getName()).isEqualTo("ControlLoopTest"); + // Autogen id so now set the ID in the previous model so that we can compare the + // objects + loopLog.setId(((LoopLog) loopInDb.getLoopLogs().toArray()[0]).getId()); + + assertThat(loopInDb).isEqualToIgnoringGivenFields(loopTest, "components", "createdDate", "updatedDate", + "createdBy", "updatedBy"); + assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(true); + assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(true); + assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(true); + assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(true); + assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true); + assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true); + assertThat(servicesRepository.existsById(loopInDb.getModelService().getServiceUuid())).isEqualTo(true); + assertThat(microServiceModelsRepository.existsById( + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getName())) + .isEqualTo(true); + assertThat(policyModelsRepository.existsById(new PolicyModelId( + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels() + .first().getPolicyModelType(), + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels() + .first().getVersion()))).isEqualTo(true); + + // Now attempt to read from database + Loop loopInDbRetrieved = loopRepository.findById(loopTest.getName()).get(); + assertThat(loopInDbRetrieved).isEqualToIgnoringGivenFields(loopTest, "components", "createdDate", "updatedDate", + "createdBy", "updatedBy"); + assertThat(loopInDbRetrieved).isEqualToComparingOnlyGivenFields(loopInDb, "createdDate", "updatedDate", + "createdBy", "updatedBy"); + assertThat((LoopLog) loopInDbRetrieved.getLoopLogs().toArray()[0]).isEqualToComparingFieldByField(loopLog); + assertThat((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]) + .isEqualToIgnoringGivenFields(opPolicy, "createdDate", "updatedDate", "createdBy", "updatedBy"); + assertThat(((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getCreatedDate()) + .isNotNull(); + assertThat(((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getUpdatedDate()) + .isNotNull(); + assertThat(((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getCreatedBy()) + .isNotNull(); + assertThat(((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getUpdatedBy()) + .isNotNull(); + + assertThat((MicroServicePolicy) loopInDbRetrieved.getMicroServicePolicies().toArray()[0]) + .isEqualToIgnoringGivenFields(microServicePolicy, "createdDate", "updatedDate", "createdBy", + "updatedBy"); + + // Attempt an update + ((LoopLog) loopInDbRetrieved.getLoopLogs().toArray()[0]).setLogInstant(Instant.now()); + loopInDbRetrieved.setLastComputedState(LoopState.RUNNING); + Loop loopInDbRetrievedUpdated = loopRepository.saveAndFlush(loopInDbRetrieved); + // Loop loopInDbRetrievedUpdated = + // loopRepository.findById(loopTest.getName()).get(); + assertThat((LoopLog) loopInDbRetrievedUpdated.getLoopLogs().toArray()[0]) + .isEqualToComparingFieldByField(loopInDbRetrieved.getLoopLogs().toArray()[0]); + // UpdatedDate should have been changed + assertThat(loopInDbRetrievedUpdated.getUpdatedDate()).isNotEqualTo(loopInDbRetrievedUpdated.getCreatedDate()); + // createdDate should have NOT been changed + assertThat(loopInDbRetrievedUpdated.getCreatedDate()).isEqualTo(loopInDb.getCreatedDate()); + // other audit are the same + assertThat(loopInDbRetrievedUpdated.getCreatedBy()).isEqualTo("Not found"); + assertThat(loopInDbRetrievedUpdated.getUpdatedBy()).isEqualTo("Not found"); + + // Attempt to delete the object and check it has well been cascaded + + loopRepository.delete(loopInDbRetrieved); + assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(false); + assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(false); + assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(true); + assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(false); + assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true); + assertThat(servicesRepository.existsById(loopInDb.getModelService().getServiceUuid())).isEqualTo(true); + assertThat(microServiceModelsRepository.existsById( + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getName())) + .isEqualTo(true); + + assertThat(policyModelsRepository.existsById(new PolicyModelId( + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels() + .first().getPolicyModelType(), + loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels() + .first().getVersion()))).isEqualTo(true); + + } +} diff --git a/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java b/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java new file mode 100644 index 000000000..15cf59f38 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopServiceTestItCase.java @@ -0,0 +1,380 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 Nokia 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; +import java.util.Set; +import java.util.stream.Collectors; +import javax.transaction.Transactional; +import org.assertj.core.util.Lists; +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.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelsService; +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; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class LoopServiceTestItCase { + + private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest"; + private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}"; + + @Autowired + LoopService loopService; + + @Autowired + LoopsRepository loopsRepository; + + @Autowired + MicroServicePolicyService microServicePolicyService; + + @Autowired + OperationalPolicyService operationalPolicyService; + + @Autowired + LoopLogService loopLogService; + + @Autowired + PolicyModelsService policyModelsService; + + @Test + @Transactional + public void shouldCreateEmptyLoop() { + // given + String loopBlueprint = "blueprint"; + Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, loopBlueprint); + testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class)); + testLoop.setLastComputedState(LoopState.DESIGN); + + // when + Loop actualLoop = loopService.saveOrUpdateLoop(testLoop); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop).isEqualTo(loopsRepository.findById(actualLoop.getName()).get()); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + assertThat(actualLoop.getGlobalPropertiesJson().getAsJsonPrimitive("testName").getAsString()) + .isEqualTo("testValue"); + } + + @Test + @Transactional + public void shouldAddOperationalPolicyToLoop() { + // given + saveTestLoopToDb(); + OperationalPolicy operationalPolicy = new OperationalPolicy("policyName", null, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null); + + // when + Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(operationalPolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies(); + assertThat(savedPolicies).hasSize(1); + assertThat(savedPolicies) + .usingElementComparatorIgnoringFields("loop", "createdBy", "createdDate", "updatedBy", "updatedDate") + .contains(operationalPolicy); + OperationalPolicy savedPolicy = savedPolicies.iterator().next(); + assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME); + + } + + @Test + @Transactional + public void shouldAddMicroservicePolicyToLoop() { + // given + saveTestLoopToDb(); + PolicyModel policyModel = new PolicyModel("org.policies.policyModel1", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "policyModel1"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + MicroServicePolicy microServicePolicy = new MicroServicePolicy("policyName", policyModel, + false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + + // when + Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(microServicePolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies(); + assertThat(savedPolicies).hasSize(1); + assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate", + "createdBy", "updatedBy").containsExactly(microServicePolicy); + assertThat(savedPolicies).extracting("usedByLoops").hasSize(1); + + } + + @Test + @Transactional + //@Commit + public void shouldCreateNewMicroservicePolicyAndUpdateJsonRepresentationOfOldOne() { + // given + saveTestLoopToDb(); + PolicyModel policyModel1 = new PolicyModel("org.policies.firstPolicyName", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "firstPolicyName"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = new PolicyModel("org.policies.secondPolicyName", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "secondPolicyName"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy("firstPolicyName", policyModel1, false, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + + loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy)); + MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy("secondPolicyName", policyModel2, false, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + + // when + firstMicroServicePolicy + .setConfigurationsJson(JsonUtils.GSON.fromJson("{\"name1\":\"value1\"}", JsonObject.class)); + Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(firstMicroServicePolicy, secondMicroServicePolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies(); + assertThat(savedPolicies).hasSize(2); + assertThat(savedPolicies).contains(firstMicroServicePolicy); + assertThat(savedPolicies).contains(secondMicroServicePolicy); + assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate", + "createdBy", "updatedBy").containsExactlyInAnyOrder(firstMicroServicePolicy, secondMicroServicePolicy); + } + + private void saveTestLoopToDb() { + Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, "blueprint"); + testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class)); + LoopTemplate template = new LoopTemplate(); + template.setName("testTemplate"); + testLoop.setLoopTemplate(template); + loopService.saveOrUpdateLoop(testLoop); + } + + @Test + @Transactional + public void shouldRemoveOldMicroservicePolicyIfNotInUpdatedList() { + // given + saveTestLoopToDb(); + PolicyModel policyModel1 = new PolicyModel("org.policies.firstPolicyName", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "firstPolicyName"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = new PolicyModel("org.policies.secondPolicyName", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "secondPolicyName"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy("firstPolicyName", policyModel1, + false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy)); + + MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy("secondPolicyName", policyModel2, + false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + + // when + Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(secondMicroServicePolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies(); + assertThat(savedPolicies).hasSize(1); + assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate", + "createdBy", "updatedBy").containsExactly(secondMicroServicePolicy); + + } + + @Test + @Transactional + public void shouldCreateNewOperationalPolicyAndUpdateJsonRepresentationOfOldOne() { + // given + saveTestLoopToDb(); + + JsonObject newJsonConfiguration = JsonUtils.GSON.fromJson("{}", JsonObject.class); + + OperationalPolicy firstOperationalPolicy = new OperationalPolicy("firstPolicyName", null, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null); + loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy)); + + OperationalPolicy secondOperationalPolicy = new OperationalPolicy("secondPolicyName", null, + newJsonConfiguration, null, null, null, null); + + // when + firstOperationalPolicy.setConfigurationsJson(newJsonConfiguration); + Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(firstOperationalPolicy, secondOperationalPolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies(); + assertThat(savedPolicies).hasSize(2); + assertThat(savedPolicies) + .usingElementComparatorIgnoringFields("loop", "createdDate", "updatedDate", "createdBy", "updatedBy") + .containsExactlyInAnyOrder(firstOperationalPolicy, secondOperationalPolicy); + Set<String> policiesLoops = Lists.newArrayList(savedPolicies).stream().map(OperationalPolicy::getLoop) + .map(Loop::getName).collect(Collectors.toSet()); + assertThat(policiesLoops).containsExactly(EXAMPLE_LOOP_NAME); + } + + @Test + @Transactional + public void shouldRemoveOldOperationalPolicyIfNotInUpdatedList() { + // given + saveTestLoopToDb(); + + OperationalPolicy firstOperationalPolicy = new OperationalPolicy("firstPolicyName", null, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null); + loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy)); + + OperationalPolicy secondOperationalPolicy = new OperationalPolicy("policyName", null, + JsonUtils.GSON.fromJson("{}", JsonObject.class), null, null, "pdpGroup1", "pdpSubgroup1"); + + // when + Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, + Lists.newArrayList(secondOperationalPolicy)); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies(); + assertThat(savedPolicies).hasSize(1); + assertThat(savedPolicies) + .usingElementComparatorIgnoringFields("loop", "createdDate", "updatedDate", "createdBy", "updatedBy") + .containsExactly(secondOperationalPolicy); + OperationalPolicy savedPolicy = savedPolicies.iterator().next(); + assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME); + + } + + @Test + @Transactional + public void shouldCreateModelPropertiesAndUpdateJsonRepresentationOfOldOne() { + // given + saveTestLoopToDb(); + String expectedJson = "{\"test\":\"test\"}"; + JsonObject baseGlobalProperites = JsonUtils.GSON.fromJson("{}", JsonObject.class); + JsonObject updatedGlobalProperites = JsonUtils.GSON.fromJson(expectedJson, JsonObject.class); + loopService.updateAndSaveGlobalPropertiesJson(EXAMPLE_LOOP_NAME, baseGlobalProperites); + + // when + Loop actualLoop = loopService.updateAndSaveGlobalPropertiesJson(EXAMPLE_LOOP_NAME, updatedGlobalProperites); + + // then + assertThat(actualLoop).isNotNull(); + assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME); + JsonObject returnedGlobalProperties = actualLoop.getGlobalPropertiesJson(); + 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, "CLAMP", loop)); + LoopTemplate template = new LoopTemplate(); + template.setName("testTemplate"); + loop.setLoopTemplate(template); + loop = loopService.saveOrUpdateLoop(loop); + // Add op policy + OperationalPolicy operationalPolicy = new OperationalPolicy("opPolicy", null, + JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null); + loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(operationalPolicy)); + + PolicyModel policyModel = new PolicyModel("org.policies.microPolicy", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "microPolicy"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + // Add Micro service policy + MicroServicePolicy microServicePolicy = new MicroServicePolicy("microPolicy", policyModel, + false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, 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, except for Microservice + assertThat(loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null)).isNull(); + assertThat(microServicePolicyService.isExisting("microPolicy")).isTrue(); + assertThat(operationalPolicyService.isExisting("opPolicy")).isFalse(); + assertThat(loopLogService.isExisting(((LoopLog) loop.getLoopLogs().toArray()[0]).getId())).isFalse(); + } + + @Test + @Transactional + public void testUpdateLoopState() { + saveTestLoopToDb(); + Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME); + loopService.updateLoopState(loop, "SUBMITTED"); + Loop updatedLoop = loopService.getLoop(EXAMPLE_LOOP_NAME); + assertThat(updatedLoop.getLastComputedState()).isEqualTo(LoopState.SUBMITTED); + } + + @Test + @Transactional + public void testUpdateDcaeDeploymentFields() { + saveTestLoopToDb(); + Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME); + loopService.updateDcaeDeploymentFields(loop, "CLAMP_c5ce429a-f570-48c5-a7ea-53bed8f86f85", + "https4://deployment-handler.onap:8443"); + loop = loopService.getLoop(EXAMPLE_LOOP_NAME); + assertThat(loop.getDcaeDeploymentId()).isEqualTo("CLAMP_c5ce429a-f570-48c5-a7ea-53bed8f86f85"); + assertThat(loop.getDcaeDeploymentStatusUrl()).isEqualTo("https4://deployment-handler.onap:8443"); + } + + @Test + @Transactional + public void testUpdateMicroservicePolicy() { + saveTestLoopToDb(); + assertThat(microServicePolicyService.isExisting("policyName")).isFalse(); + PolicyModel policyModel = new PolicyModel("org.policies.policyName", + "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "policyName"); + policyModelsService.saveOrUpdatePolicyModel(policyModel); + MicroServicePolicy microServicePolicy = new MicroServicePolicy("policyName", policyModel, + false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null); + loopService.updateMicroservicePolicy(EXAMPLE_LOOP_NAME, microServicePolicy); + assertThat(microServicePolicyService.isExisting("policyName")).isTrue(); + } + + private Loop createTestLoop(String loopName, String loopBlueprint) { + return new Loop(loopName); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/clamp/loop/LoopTemplateLoopElementModelTest.java b/src/test/java/org/onap/clamp/loop/LoopTemplateLoopElementModelTest.java new file mode 100644 index 000000000..70ff9b118 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopTemplateLoopElementModelTest.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.LoopTemplateLoopElementModel; +import org.onap.clamp.loop.template.PolicyModel; + + +public class LoopTemplateLoopElementModelTest { + + private LoopElementModel loopElementModel = getLoopElementModel("yaml", "microService1", + getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools", "type1")); + private LoopTemplate loopTemplate = getLoopTemplate("templateName", "yaml", 1); + + private LoopElementModel getLoopElementModel(String yaml, String name, PolicyModel policyModel) { + LoopElementModel model = new LoopElementModel(); + model.setBlueprint(yaml); + model.setName(name); + model.addPolicyModel(policyModel); + model.setLoopElementType("OPERATIONAL_POLICY"); + return model; + } + + private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, String policyAcronym, + String policyVariant) { + return new PolicyModel(policyType, policyModelTosca, version, policyAcronym); + } + + private LoopTemplate getLoopTemplate(String name, String blueprint, Integer maxInstancesAllowed) { + LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null); + template.addLoopElementModel(loopElementModel); + return template; + } + + /** + * This tests compareTo method. + */ + @Test + public void compareToTest() { + LoopTemplateLoopElementModel model1 = new LoopTemplateLoopElementModel(); + LoopTemplateLoopElementModel model2 = new LoopTemplateLoopElementModel(); + assertThat(model1.compareTo(model2)).isEqualTo(1); + + model1.setFlowOrder(2); + assertThat(model1.compareTo(model2)).isEqualTo(-1); + + model2.setFlowOrder(3); + assertThat(model1.compareTo(model2)).isEqualTo(1); + } + + /** + * This tests equals method. + */ + @Test + public void equalsTest() { + LoopTemplateLoopElementModel model1 = new LoopTemplateLoopElementModel(); + LoopTemplateLoopElementModel model2 = new LoopTemplateLoopElementModel(); + + assertThat(model1.equals(model2)).isTrue(); + + model1.setLoopTemplate(loopTemplate); + assertThat(model1.equals(model2)).isFalse(); + model2.setLoopTemplate(loopTemplate); + assertThat(model1.equals(model2)).isTrue(); + + model1.setLoopElementModel(loopElementModel); + assertThat(model1.equals(model2)).isFalse(); + model2.setLoopElementModel(loopElementModel); + assertThat(model1.equals(model2)).isTrue(); + + model1.setFlowOrder(1); + assertThat(model1.equals(model2)).isTrue(); + model2.setFlowOrder(2); + assertThat(model1.equals(model2)).isTrue(); + } + +} diff --git a/src/test/java/org/onap/clamp/loop/LoopTemplatesServiceItCase.java b/src/test/java/org/onap/clamp/loop/LoopTemplatesServiceItCase.java new file mode 100644 index 000000000..b8b1144f6 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopTemplatesServiceItCase.java @@ -0,0 +1,146 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 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.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import java.util.SortedSet;
+import javax.transaction.Transactional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.clamp.clds.Application;
+import org.onap.clamp.loop.template.LoopElementModel;
+import org.onap.clamp.loop.template.LoopTemplate;
+import org.onap.clamp.loop.template.LoopTemplateLoopElementModel;
+import org.onap.clamp.loop.template.LoopTemplatesService;
+import org.onap.clamp.loop.template.LoopType;
+import org.onap.clamp.loop.template.PolicyModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopTemplatesServiceItCase {
+
+ @Autowired
+ LoopTemplatesService loopTemplatesService;
+
+ private static final String POLICY_MODEL_TYPE_1 = "org.onap.test";
+ private static final String VERSION = "1.0.0";
+
+ private LoopElementModel getLoopElementModel(String yaml, String name, String loopElementType,
+ String createdBy, PolicyModel policyModel) {
+ LoopElementModel model = new LoopElementModel(name, loopElementType, yaml);
+ model.setBlueprint("");
+ model.setDcaeBlueprintId("");
+ model.addPolicyModel(policyModel);
+ return model;
+ }
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym, String createdBy) {
+ return new PolicyModel(policyType, policyModelTosca, version, policyAcronym);
+ }
+
+ private LoopTemplate getLoopTemplate(String name, String blueprint, String createdBy, Integer maxInstancesAllowed) {
+ LoopTemplate template =
+ new LoopTemplate(name, blueprint, maxInstancesAllowed, null);
+ template.addLoopElementModel(getLoopElementModel("yaml", "microService1", "MicroService",
+ createdBy, getPolicyModel(POLICY_MODEL_TYPE_1, "yaml", VERSION, "MS1", createdBy)));
+ template.setAllowedLoopType(LoopType.OPEN);
+ return template;
+ }
+
+ @Test
+ @Transactional
+ public void shouldSaveOrUpdateLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ LoopTemplate actualLoopTemplate =
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+
+ assertNotNull(actualLoopTemplate);
+ assertThat(loopTemplate.getName()).isEqualTo("TemplateName");
+ assertThat(loopTemplate.getAllowedLoopType()).isEqualTo(LoopType.OPEN);
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnAllLoopTemplates() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ List<LoopTemplate> loopTemplateList = loopTemplatesService.getAllLoopTemplates();
+
+ assertNotNull(loopTemplateList);
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnLoopTemplateNames() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ List<String> loopTemplateNames = loopTemplatesService.getLoopTemplateNames();
+
+ assertNotNull(loopTemplateNames);
+ assertEquals("TemplateName", loopTemplateNames.get(0));
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ LoopTemplate actualLoopTemplate = loopTemplatesService.getLoopTemplate("TemplateName");
+
+ assertNotNull(actualLoopTemplate);
+ assertThat(loopTemplate).isEqualTo(actualLoopTemplate);
+ assertThat(loopTemplate.getName()).isEqualTo(actualLoopTemplate.getName());
+ assertThat(loopTemplate.getMaximumInstancesAllowed())
+ .isEqualTo(actualLoopTemplate.getMaximumInstancesAllowed());
+ SortedSet<LoopTemplateLoopElementModel> loopElementModelsUsed =
+ loopTemplate.getLoopElementModelsUsed();
+ LoopTemplateLoopElementModel loopTemplateLoopElementModel = loopElementModelsUsed.first();
+ assertThat(loopTemplateLoopElementModel.getLoopElementModel().getName())
+ .isEqualTo("microService1");
+ assertThat(loopTemplateLoopElementModel.getLoopTemplate().getName())
+ .isEqualTo("TemplateName");
+ assertNull(actualLoopTemplate.getBlueprint());
+ assertNull(actualLoopTemplate.getModelService());
+ }
+
+ @Test
+ @Transactional
+ public void shouldDeleteLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ loopTemplatesService.deleteLoopTemplate("TemplateName");
+ LoopTemplate actualLoopTemplate = loopTemplatesService.getLoopTemplate("TemplateName");
+ assertNull(actualLoopTemplate);
+ }
+
+}
diff --git a/src/test/java/org/onap/clamp/loop/LoopToJsonTest.java b/src/test/java/org/onap/clamp/loop/LoopToJsonTest.java new file mode 100644 index 000000000..1d6940f83 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/LoopToJsonTest.java @@ -0,0 +1,172 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.loop; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import java.io.IOException; +import java.util.Random; +import org.junit.Test; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.log.LogType; +import org.onap.clamp.loop.log.LoopLog; +import org.onap.clamp.loop.service.Service; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; + +public class LoopToJsonTest { + + private Gson gson = new Gson(); + + private OperationalPolicy getOperationalPolicy(String configJson, String name) { + return new OperationalPolicy(name, null, gson.fromJson(configJson, JsonObject.class), + getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "Drools", "type1"), null, null, null); + } + + private Loop getLoop(String name, String blueprint, String globalPropertiesJson, + String dcaeId, String dcaeUrl, String dcaeBlueprintId) + throws JsonSyntaxException, IOException { + Loop loop = new Loop(name); + loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class)); + loop.setLastComputedState(LoopState.DESIGN); + loop.setDcaeDeploymentId(dcaeId); + loop.setDcaeDeploymentStatusUrl(dcaeUrl); + return loop; + } + + private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation, + String policyTosca, String jsonProperties, boolean shared) { + MicroServicePolicy microService = new MicroServicePolicy(name, new PolicyModel(modelType, policyTosca, "1.0.0"), + shared, + gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null); + microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class)); + return microService; + } + + private LoopElementModel getLoopElementModel(String yaml, String name, PolicyModel policyModel) { + LoopElementModel model = new LoopElementModel(); + model.setBlueprint(yaml); + model.setName(name); + model.addPolicyModel(policyModel); + model.setLoopElementType("OPERATIONAL_POLICY"); + return model; + } + + private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, String policyAcronym, + String policyVariant) { + return new PolicyModel(policyType, policyModelTosca, version, policyAcronym); + } + + private LoopTemplate getLoopTemplate(String name, String blueprint, Integer maxInstancesAllowed) { + LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null); + template.addLoopElementModel(getLoopElementModel("yaml", "microService1", + getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools", "type1"))); + return template; + } + + private LoopLog getLoopLog(LogType type, String message, Loop loop) { + LoopLog log = new LoopLog(message, type, "CLAMP", loop); + log.setId(Long.valueOf(new Random().nextInt())); + return log; + } + + /** + * This tests a GSON encode/decode. + * + * @throws IOException In case of failure + */ + @Test + public void loopGsonTest() throws IOException { + Loop loopTest = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "123456789", "https://dcaetest.org", "UUID-blueprint"); + OperationalPolicy opPolicy = this.getOperationalPolicy( + ResourceFileUtils.getResourceAsString("tosca/operational-policy-properties.json"), "GuardOpPolicyTest"); + loopTest.addOperationalPolicy(opPolicy); + MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "", + "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0", + "{\"param1\":\"value1\"}", true); + loopTest.addMicroServicePolicy(microServicePolicy); + LoopLog loopLog = getLoopLog(LogType.INFO, "test message", loopTest); + loopTest.addLog(loopLog); + LoopTemplate loopTemplate = getLoopTemplate("templateName", "yaml", 1); + loopTest.setLoopTemplate(loopTemplate); + + String jsonSerialized = JsonUtils.GSON_JPA_MODEL.toJson(loopTest); + assertThat(jsonSerialized).isNotNull().isNotEmpty(); + System.out.println(jsonSerialized); + Loop loopTestDeserialized = JsonUtils.GSON_JPA_MODEL.fromJson(jsonSerialized, Loop.class); + assertNotNull(loopTestDeserialized); + assertThat(loopTestDeserialized).isEqualToIgnoringGivenFields(loopTest, "svgRepresentation", "blueprint", + "components"); + assertThat(loopTestDeserialized.getComponent("DCAE").getState()) + .isEqualToComparingFieldByField(loopTest.getComponent("DCAE").getState()); + assertThat(loopTestDeserialized.getComponent("POLICY").getState()).isEqualToComparingOnlyGivenFields( + loopTest.getComponent("POLICY").getState(), "stateName", "description"); + // blueprint not exposed so wont be deserialized + + assertThat(loopTestDeserialized.getOperationalPolicies()).containsExactly(opPolicy); + assertThat(loopTestDeserialized.getMicroServicePolicies()).containsExactly(microServicePolicy); + assertThat(loopTestDeserialized.getLoopLogs()).containsExactly(loopLog); + assertThat((LoopLog) loopTestDeserialized.getLoopLogs().toArray()[0]).isEqualToIgnoringGivenFields(loopLog, + "loop"); + + // Verify the loop template + assertThat(loopTestDeserialized.getLoopTemplate()).isEqualTo(loopTemplate); + } + + /** + * This tests the service object GSON encode/decode. + * + * @throws IOException In case of issues + */ + @Test + public void loopServiceTest() throws IOException { + Loop loopTest2 = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}", + "123456789", "https://dcaetest.org", "UUID-blueprint"); + + JsonObject jsonModel = new GsonBuilder().create() + .fromJson(ResourceFileUtils.getResourceAsString("tosca/model-properties.json"), JsonObject.class); + Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(), + jsonModel.get("resourceDetails").getAsJsonObject(), "1.0"); + loopTest2.setModelService(service); + String jsonSerialized = JsonUtils.GSON_JPA_MODEL.toJson(loopTest2); + assertThat(jsonSerialized).isNotNull().isNotEmpty(); + System.out.println(jsonSerialized); + + Loop loopTestDeserialized = JsonUtils.GSON_JPA_MODEL.fromJson(jsonSerialized, Loop.class); + assertNotNull(loopTestDeserialized); + assertThat(loopTestDeserialized).isEqualToIgnoringGivenFields(loopTest2, "modelService", "svgRepresentation", + "blueprint", "components"); + } +} diff --git a/src/test/java/org/onap/clamp/loop/PolicyComponentTest.java b/src/test/java/org/onap/clamp/loop/PolicyComponentTest.java new file mode 100644 index 000000000..4d2bfe280 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/PolicyComponentTest.java @@ -0,0 +1,297 @@ +/*- + * ============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.loop; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.io.IOException; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.components.external.ExternalComponentState; +import org.onap.clamp.loop.components.external.PolicyComponent; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.clamp.policy.operational.OperationalPolicy; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PolicyComponentTest { + + /** + * Test the computeState method. + * oldState newState expectedFinalState + * NOT_SENT SENT_AND_DEPLOYED NOT_SENT + * NOT_SENT SENT NOT_SENT + * NOT_SENT NOT_SENT NOT_SENT + * NOT_SENT IN_ERROR IN_ERROR + */ + @Test + public void computeStateTestOriginalStateUnknown() { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + // policy found + deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + PolicyComponent policy = new PolicyComponent(); + + ExternalComponentState state = policy.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("SENT_AND_DEPLOYED"); + // policy found + not deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state2 = policy.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("SENT"); + // policy not found + not deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state4 = policy.computeState(exchange); + assertThat(state4.getStateName()).isEqualTo("NOT_SENT"); + // policy not found + deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state3 = policy.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("IN_ERROR"); + } + + /** + * Test the computeState method. + * oldState newState expectedFinalState + * NOT_SENT SENT_AND_DEPLOYED NOT_SENT + * NOT_SENT SENT NOT_SENT + * NOT_SENT NOT_SENT NOT_SENT + * NOT_SENT IN_ERROR IN_ERROR + */ + @Test + public void computeStateTestOriginalStateNotSent() { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + // policy found + deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + PolicyComponent policy = new PolicyComponent(); + ExternalComponentState notSent = new ExternalComponentState("NOT_SENT", + "The policies defined have NOT yet been created on the policy engine", 90); + policy.setState(notSent); + ExternalComponentState state = policy.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("NOT_SENT"); + // policy found + not deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state2 = policy.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("NOT_SENT"); + // policy not found + not deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state4 = policy.computeState(exchange); + assertThat(state4.getStateName()).isEqualTo("NOT_SENT"); + // policy not found + deployed + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state3 = policy.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("IN_ERROR"); + } + + + /** + * Test the computeState method. + * oldState newState expectedFinalState + * SENT SENT SENT + * SENT SENT_AND_DEPLOYED SENT + * SENT IN_ERROR IN_ERROR + * SENT NOT_SENT NOT_SENT + */ + @Test + public void computeStateTestOriginalStateSent() throws IOException { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + PolicyComponent policy = new PolicyComponent(); + ExternalComponentState sent = new ExternalComponentState("SENT", + "The policies defined have been created but NOT deployed on the policy engine", 50); + policy.setState(sent); + // new policy state SENT + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state = policy.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("SENT"); + // new policy state SENT_AND_DEPLOYED + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state2 = policy.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("SENT"); + // new policy state IN_ERROR + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state3 = policy.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("IN_ERROR"); + // new policy state NOT_SENT + policy.setState(sent); + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state4 = policy.computeState(exchange); + assertThat(state4.getStateName()).isEqualTo("NOT_SENT"); + } + + /** + * Test the computeState method. + * oldState newState expectedFinalState + * SENT_AND_DEPLOYED SENT_AND_DEPLOYED SENT_AND_DEPLOYED + * SENT_AND_DEPLOYED SENT SENT + * SENT_AND_DEPLOYED IN_ERROR IN_ERROR + * SENT_AND_DEPLOYED NOT_SENT NOT_SENT + */ + @Test + public void computeStateTestOriginalStateSentAndDeployed() throws IOException { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + PolicyComponent policy = new PolicyComponent(); + ExternalComponentState sendDeployed = new ExternalComponentState("SENT_AND_DEPLOYED", + "The policies defined have been created and deployed on the policy engine", 10); + policy.setState(sendDeployed); + // new policy state SENT_AND_DEPLOYED + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state = policy.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("SENT_AND_DEPLOYED"); + // new policy state SENT + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state2 = policy.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("SENT"); + // new policy state IN_ERROR + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state3 = policy.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("IN_ERROR"); + // new policy state NOT_SENT + policy.setState(sendDeployed); + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state4 = policy.computeState(exchange); + assertThat(state4.getStateName()).isEqualTo("NOT_SENT"); + } + + + /** + * Test the computeState method. + * oldState newState expectedFinalState + * IN_ERROR SENT_AND_DEPLOYED IN_ERROR + * IN_ERROR SENT IN_ERROR + * IN_ERROR IN_ERROR IN_ERROR + * IN_ERROR NOT_SENT IN_ERROR + */ + @Test + public void computeStateTestOriginalStateInError() throws IOException { + Exchange exchange = Mockito.mock(Exchange.class); + Message message = Mockito.mock(Message.class); + Exchange exchange2 = Mockito.mock(Exchange.class); + Mockito.when(exchange.getIn()).thenReturn(message); + Mockito.when(message.getExchange()).thenReturn(exchange2); + PolicyComponent policy = new PolicyComponent(); + ExternalComponentState inError = new ExternalComponentState("IN_ERROR", + "There was an error during the sending to policy, the policy engine may be corrupted or inconsistent", + 100); + policy.setState(inError); + // new policy state SENT_AND_DEPLOYED + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state = policy.computeState(exchange); + assertThat(state.getStateName()).isEqualTo("IN_ERROR"); + // new policy state SENT + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state2 = policy.computeState(exchange); + assertThat(state2.getStateName()).isEqualTo("IN_ERROR"); + // new policy state IN_ERROR + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true); + ExternalComponentState state3 = policy.computeState(exchange); + assertThat(state3.getStateName()).isEqualTo("IN_ERROR"); + // new policy state NOT_SENT + Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false); + Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false); + ExternalComponentState state4 = policy.computeState(exchange); + + assertThat(state4.getStateName()).isEqualTo("IN_ERROR"); + } + + /** + * Test the create policies payload PdpGroup test. + */ + @Test + public void createPoliciesPayloadPdpGroupTest() throws IOException { + Loop loopTest = new Loop("ControlLoopTest"); + PolicyModel policyModel1 = new PolicyModel("onap.policies.monitoring.test", null, "1.0.0"); + + MicroServicePolicy microServicePolicy = new MicroServicePolicy("configPolicyTest", policyModel1, true, + new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, "pdpGroup1", "pdpSubgroup1"); + loopTest.addMicroServicePolicy(microServicePolicy); + + MicroServicePolicy microServicePolicy2 = new MicroServicePolicy("configPolicyTest2", policyModel1, true, + new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, "pdpGroup2", "pdpSubgroup1"); + loopTest.addMicroServicePolicy(microServicePolicy2); + + PolicyModel policyModel2 = new PolicyModel("onap.policies.monitoring.test2", null, + "1.0.0"); + OperationalPolicy opPolicy = + new OperationalPolicy("opPolicy", new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), + new Gson().fromJson("{\"jsonschema\":\"schema\"}", JsonObject.class), policyModel2, null, + "pdpGroup2", + "pdpSubgroup2"); + + loopTest.addOperationalPolicy(opPolicy); + OperationalPolicy opLegacyPolicy = + new OperationalPolicy("opLegacyPolicy", new Gson().fromJson( + "{\"guard_policies\":[{\"policy-id\":\"guard1\"}]}", JsonObject.class), + new Gson().fromJson("{\"jsonschema\":\"schema\"}", JsonObject.class), policyModel2, null, + "pdpGroup2", + "pdpSubgroup2"); + + loopTest.addOperationalPolicy(opLegacyPolicy); + + LoopTemplate loopTemplate = new LoopTemplate("test", "yaml", 1, null); + loopTemplate.setDcaeBlueprintId("UUID-blueprint"); + loopTest.setLoopTemplate(loopTemplate); + + String payload = PolicyComponent.createPoliciesPayloadPdpGroup(loopTest, "POST"); + String expectedRes = ResourceFileUtils.getResourceAsString("tosca/pdp-group-policy-payload.json"); + + assertThat(payload).isEqualTo(expectedRes); + } +} diff --git a/src/test/java/org/onap/clamp/loop/PolicyModelServiceItCase.java b/src/test/java/org/onap/clamp/loop/PolicyModelServiceItCase.java new file mode 100644 index 000000000..6f6cad815 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/PolicyModelServiceItCase.java @@ -0,0 +1,311 @@ +/*- + * ============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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.stream.Collectors; +import javax.transaction.Transactional; +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.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.onap.clamp.loop.template.PolicyModelsService; +import org.onap.clamp.policy.pdpgroup.PdpGroup; +import org.onap.clamp.policy.pdpgroup.PdpSubgroup; +import org.onap.clamp.policy.pdpgroup.PolicyModelKey; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class PolicyModelServiceItCase { + + @Autowired + PolicyModelsService policyModelsService; + + @Autowired + PolicyModelsRepository policyModelsRepository; + + private static final String POLICY_MODEL_TYPE_1 = "org.onap.testos"; + private static final String POLICY_MODEL_TYPE_1_VERSION_1 = "1.0.0"; + + private static final String POLICY_MODEL_TYPE_2 = "org.onap.testos2"; + private static final String POLICY_MODEL_TYPE_3 = "org.onap.testos3"; + private static final String POLICY_MODEL_TYPE_2_VERSION_1 = "1.0.0"; + private static final String POLICY_MODEL_TYPE_3_VERSION_1 = "1.0.0"; + private static final String POLICY_MODEL_TYPE_2_VERSION_2 = "2.0.0"; + + private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, + String policyAcronym, String policyVariant, String createdBy) { + PolicyModel policyModel = new PolicyModel(); + policyModel.setCreatedBy(createdBy); + policyModel.setPolicyAcronym(policyAcronym); + policyModel.setPolicyModelTosca(policyModelTosca); + policyModel.setPolicyModelType(policyType); + policyModel.setUpdatedBy(createdBy); + policyModel.setVersion(version); + return policyModel; + } + + /** + * This test the create policy Model. + */ + @Test + @Transactional + public void shouldCreatePolicyModel() { + // given + PolicyModel policyModel = getPolicyModel(POLICY_MODEL_TYPE_1, "yaml", + POLICY_MODEL_TYPE_1_VERSION_1, "TEST", "VARIANT", "user"); + + // when + PolicyModel actualPolicyModel = policyModelsService.saveOrUpdatePolicyModel(policyModel); + + // then + assertThat(actualPolicyModel).isNotNull(); + assertThat(actualPolicyModel).isEqualTo(policyModelsRepository + .findById(new PolicyModelId(actualPolicyModel.getPolicyModelType(), + actualPolicyModel.getVersion())) + .get()); + assertThat(actualPolicyModel.getPolicyModelType()) + .isEqualTo(policyModel.getPolicyModelType()); + assertThat(actualPolicyModel.getCreatedBy()).isEqualTo("Not found"); + assertThat(actualPolicyModel.getCreatedDate()).isNotNull(); + assertThat(actualPolicyModel.getPolicyAcronym()).isEqualTo(policyModel.getPolicyAcronym()); + assertThat(actualPolicyModel.getPolicyModelTosca()) + .isEqualTo(policyModel.getPolicyModelTosca()); + assertThat(actualPolicyModel.getUpdatedBy()).isEqualTo("Not found"); + assertThat(actualPolicyModel.getUpdatedDate()).isNotNull(); + assertThat(actualPolicyModel.getVersion()).isEqualTo(policyModel.getVersion()); + + assertThat( + policyModelsService.getPolicyModel(POLICY_MODEL_TYPE_1, POLICY_MODEL_TYPE_1_VERSION_1)) + .isEqualToIgnoringGivenFields(policyModel, "createdDate", "updatedDate", + "createdBy", "updatedBy"); + } + + /** + * This tests a create Policy Model from Tosca. + * + * @throws IOException In case of failure + */ + @Test + @Transactional + public void shouldCreatePolicyModelFromTosca() throws IOException { + String toscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca_with_metadata.yaml"); + PolicyModel policyModel = policyModelsService.createNewPolicyModelFromTosca(toscaModelYaml); + + assertThat(policyModelsService.getAllPolicyModels()).contains(policyModel); + + assertThat(policyModelsService.getPolicyModelTosca(policyModel.getPolicyModelType(), + policyModel.getVersion())).contains(toscaModelYaml); + } + + /** + * This tests a update Policy Model. + * + * @throws IOException In case of failure + */ + @Test + @Transactional + public void shouldUpdatePolicyModel() throws IOException { + String toscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca_with_metadata.yaml"); + PolicyModel policyModel = policyModelsService.createNewPolicyModelFromTosca(toscaModelYaml); + String newToscaModelYaml = + ResourceFileUtils.getResourceAsString("tosca/tosca_metadata_clamp_possible_values.yaml"); + + PolicyModel updatedPolicyModel = policyModelsService.updatePolicyModelTosca( + policyModel.getPolicyModelType(), policyModel.getVersion(), newToscaModelYaml); + + assertThat(updatedPolicyModel.getPolicyModelTosca()).isEqualTo(newToscaModelYaml); + + } + + /** + * This tests a getAllPolicyModelTypes get. + */ + @Test + @Transactional + public void shouldReturnAllPolicyModelTypes() { + // given + PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + List<String> policyModelTypesList = policyModelsService.getAllPolicyModelTypes(); + + assertThat(policyModelTypesList).contains(policyModel1.getPolicyModelType(), + policyModel2.getPolicyModelType()); + } + + /** + * This tests a getAllPolicyModels get. + */ + @Test + @Transactional + public void shouldReturnAllPolicyModels() { + PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + + assertThat(policyModelsService.getAllPolicyModels()).contains(policyModel1, policyModel2); + } + + /** + * This tests a getAllPolicyModelsByType get. + */ + @Test + @Transactional + public void shouldReturnAllModelsByType() { + PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + + assertThat(policyModelsService.getAllPolicyModelsByType(POLICY_MODEL_TYPE_2)) + .contains(policyModel1, policyModel2); + } + + /** + * This tests the sorting of policyModel. + */ + @Test + @Transactional + public void shouldReturnSortedSet() { + PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + PolicyModel policyModel3 = getPolicyModel(POLICY_MODEL_TYPE_3, "yaml", + POLICY_MODEL_TYPE_3_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel3); + + SortedSet<PolicyModel> sortedSet = new TreeSet<>(); + policyModelsService.getAllPolicyModels().forEach(sortedSet::add); + List<PolicyModel> listToCheck = + sortedSet + .stream().filter(policy -> policy.equals(policyModel3) + || policy.equals(policyModel2) || policy.equals(policyModel1)) + .collect(Collectors.toList()); + assertThat(listToCheck.get(0)).isEqualByComparingTo(policyModel2); + assertThat(listToCheck.get(1)).isEqualByComparingTo(policyModel1); + assertThat(listToCheck.get(2)).isEqualByComparingTo(policyModel3); + } + + /** + * This tests the pdpgroup GSON encode/decode and saving. + */ + @Test + @Transactional + public void shouldAddPdpGroupInfo() { + PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_1, "yaml", + POLICY_MODEL_TYPE_1_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel1); + PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml", + POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel2); + PolicyModel policyModel3 = getPolicyModel(POLICY_MODEL_TYPE_3, "yaml", + POLICY_MODEL_TYPE_3_VERSION_1, "TEST", "VARIANT", "user"); + policyModelsService.saveOrUpdatePolicyModel(policyModel3); + + PolicyModelKey type1 = new PolicyModelKey("org.onap.testos", "1.0.0"); + PolicyModelKey type2 = new PolicyModelKey("org.onap.testos2", "2.0.0"); + + PdpSubgroup pdpSubgroup1 = new PdpSubgroup(); + pdpSubgroup1.setPdpType("subGroup1"); + List<PolicyModelKey> pdpTypeList = new LinkedList<PolicyModelKey>(); + pdpTypeList.add(type1); + pdpTypeList.add(type2); + pdpSubgroup1.setSupportedPolicyTypes(pdpTypeList); + + PolicyModelKey type3 = new PolicyModelKey("org.onap.testos3", "2.0.0"); + PdpSubgroup pdpSubgroup2 = new PdpSubgroup(); + pdpSubgroup2.setPdpType("subGroup2"); + List<PolicyModelKey> pdpTypeList2 = new LinkedList<PolicyModelKey>(); + pdpTypeList2.add(type2); + pdpTypeList2.add(type3); + pdpSubgroup2.setSupportedPolicyTypes(pdpTypeList2); + + List<PdpSubgroup> pdpSubgroupList = new LinkedList<PdpSubgroup>(); + pdpSubgroupList.add(pdpSubgroup1); + + PdpGroup pdpGroup1 = new PdpGroup(); + pdpGroup1.setName("pdpGroup1"); + pdpGroup1.setPdpGroupState("ACTIVE"); + pdpGroup1.setPdpSubgroups(pdpSubgroupList); + + List<PdpSubgroup> pdpSubgroupList2 = new LinkedList<PdpSubgroup>(); + pdpSubgroupList2.add(pdpSubgroup1); + pdpSubgroupList2.add(pdpSubgroup2); + PdpGroup pdpGroup2 = new PdpGroup(); + pdpGroup2.setName("pdpGroup2"); + pdpGroup2.setPdpGroupState("ACTIVE"); + pdpGroup2.setPdpSubgroups(pdpSubgroupList2); + + List<PdpGroup> pdpGroupList = new LinkedList<PdpGroup>(); + pdpGroupList.add(pdpGroup1); + pdpGroupList.add(pdpGroup2); + policyModelsService.updatePdpGroupInfo(pdpGroupList); + + JsonObject res1 = + policyModelsService.getPolicyModel("org.onap.testos", "1.0.0").getPolicyPdpGroup(); + String expectedRes1 = + "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},{\"pdpGroup2\":[\"subGroup1\"]}]}"; + JsonObject expectedJson1 = JsonUtils.GSON.fromJson(expectedRes1, JsonObject.class); + assertThat(res1).isEqualTo(expectedJson1); + + JsonObject res2 = + policyModelsService.getPolicyModel("org.onap.testos2", "2.0.0").getPolicyPdpGroup(); + String expectedRes2 = + "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},{\"pdpGroup2\":[\"subGroup1\",\"subGroup2\"]}]}"; + JsonObject expectedJson2 = JsonUtils.GSON.fromJson(expectedRes2, JsonObject.class); + assertThat(res2).isEqualTo(expectedJson2); + + JsonObject res3 = + policyModelsService.getPolicyModel("org.onap.testos3", "1.0.0").getPolicyPdpGroup(); + assertThat(res3).isNull(); + } +} diff --git a/src/test/java/org/onap/clamp/loop/ServiceTest.java b/src/test/java/org/onap/clamp/loop/ServiceTest.java new file mode 100644 index 000000000..2b6fab8b6 --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/ServiceTest.java @@ -0,0 +1,55 @@ +/*- + * ============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.loop; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; + +import org.junit.Test; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.loop.service.Service; + +public class ServiceTest { + + @Test + public void equalMethodTest() { + String serviceStr1 = "{\"name\": \"vLoadBalancerMS\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}"; + String serviceStr2 = "{\"name\": \"vLoadBalancerMS2\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}"; + String serviceStr3 = "{\"name\": \"vLoadBalancerMS\",\"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fc11\"}"; + String resourceStr = "{\"CP\": {}}"; + + Service service1 = new Service(JsonUtils.GSON.fromJson(serviceStr1, JsonObject.class), + JsonUtils.GSON.fromJson(resourceStr, JsonObject.class), "1.0"); + + Service service2 = new Service(JsonUtils.GSON.fromJson(serviceStr2, JsonObject.class), null, "1.0"); + + Service service3 = new Service(JsonUtils.GSON.fromJson(serviceStr3, JsonObject.class), + JsonUtils.GSON.fromJson(resourceStr, JsonObject.class), "1.0"); + + assertThat(service1.equals(service2)).isEqualTo(true); + assertThat(service1.equals(service3)).isEqualTo(false); + } + +} diff --git a/src/test/java/org/onap/clamp/loop/deploy/BlueprintInputParametersTest.java b/src/test/java/org/onap/clamp/loop/deploy/BlueprintInputParametersTest.java new file mode 100644 index 000000000..8a5b5876f --- /dev/null +++ b/src/test/java/org/onap/clamp/loop/deploy/BlueprintInputParametersTest.java @@ -0,0 +1,125 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Modifications copyright (c) 2019 Nokia + * Modifications Copyright (c) 2019 Samsung + * ================================================================================ + * 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.loop.deploy; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.util.LinkedHashSet; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.Loop; +import org.onap.clamp.loop.template.LoopElementModel; +import org.onap.clamp.loop.template.LoopTemplate; +import org.onap.clamp.policy.microservice.MicroServicePolicy; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; + +public class BlueprintInputParametersTest { + + /** + * getDeploymentParametersinJsonMultiBlueprintsTest. + * + * @throws IOException in case of failure + * @throws SdcToscaParserException in case of failure + */ + @Test + public void getDeploymentParametersinJsonMultiBlueprintsTest() throws IOException, SdcToscaParserException { + + + MicroServicePolicy umService1 = Mockito.mock(MicroServicePolicy.class); + Mockito.when(umService1.getName()).thenReturn("testName1"); + + LoopElementModel loopElement = Mockito.mock(LoopElementModel.class); + String blueprint1 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca.yaml"); + Mockito.when(loopElement.getBlueprint()).thenReturn(blueprint1); + Mockito.when(umService1.getLoopElementModel()).thenReturn(loopElement); + + MicroServicePolicy umService2 = Mockito.mock(MicroServicePolicy.class); + Mockito.when(umService2.getName()).thenReturn("testName2"); + + LoopElementModel loopElement2 = Mockito.mock(LoopElementModel.class); + String blueprint2 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca_2.yaml"); + Mockito.when(loopElement2.getBlueprint()).thenReturn(blueprint2); + Mockito.when(umService2.getLoopElementModel()).thenReturn(loopElement2); + + MicroServicePolicy umService3 = Mockito.mock(MicroServicePolicy.class); + Mockito.when(umService3.getName()).thenReturn("testName3"); + + LoopElementModel loopElement3 = Mockito.mock(LoopElementModel.class); + String blueprint3 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca_3.yaml"); + Mockito.when(loopElement3.getBlueprint()).thenReturn(blueprint3); + Mockito.when(umService3.getLoopElementModel()).thenReturn(loopElement3); + + LinkedHashSet<MicroServicePolicy> umServiceSet = new LinkedHashSet<>(); + umServiceSet.add(umService1); + umServiceSet.add(umService2); + umServiceSet.add(umService3); + Loop loop = Mockito.mock(Loop.class); + Mockito.when(loop.getMicroServicePolicies()).thenReturn(umServiceSet); + + LoopTemplate template = Mockito.mock(LoopTemplate.class); + Mockito.when(template.getUniqueBlueprint()).thenReturn(false); + Mockito.when(loop.getLoopTemplate()).thenReturn(template); + + JsonObject paramJson = DcaeDeployParameters.getDcaeDeploymentParametersInJson(loop); + + Assert.assertEquals(JsonUtils.GSON_JPA_MODEL.toJson(paramJson), + ResourceFileUtils.getResourceAsString( + "example/sdc/expected-result/deployment-parameters-multi-blueprints.json")); + } + + /** + * getDeploymentParametersInJsonSingleBlueprintTest. + * + * @throws IOException In case of failure + * @throws SdcToscaParserException In case of failure + */ + @Test + public void getDeploymentParametersInJsonSingleBlueprintTest() throws IOException, SdcToscaParserException { + Loop loop = Mockito.mock(Loop.class); + + MicroServicePolicy umService1 = Mockito.mock(MicroServicePolicy.class); + Mockito.when(umService1.getName()).thenReturn("testName1"); + LinkedHashSet<MicroServicePolicy> umServiceSet = new LinkedHashSet<MicroServicePolicy>(); + umServiceSet.add(umService1); + Mockito.when(loop.getMicroServicePolicies()).thenReturn(umServiceSet); + + LoopTemplate template = Mockito.mock(LoopTemplate.class); + Mockito.when(template.getUniqueBlueprint()).thenReturn(true); + String blueprint = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca.yaml"); + Mockito.when(template.getBlueprint()).thenReturn(blueprint); + Mockito.when(loop.getLoopTemplate()).thenReturn(template); + + JsonObject paramJson = DcaeDeployParameters.getDcaeDeploymentParametersInJson(loop); + + Assert.assertEquals(JsonUtils.GSON_JPA_MODEL.toJson(paramJson), + ResourceFileUtils.getResourceAsString( + "example/sdc/expected-result/deployment-parameters-single-blueprint.json")); + } +} diff --git a/src/test/java/org/onap/clamp/policy/downloader/PolicyEngineControllerTestItCase.java b/src/test/java/org/onap/clamp/policy/downloader/PolicyEngineControllerTestItCase.java new file mode 100644 index 000000000..51b93767f --- /dev/null +++ b/src/test/java/org/onap/clamp/policy/downloader/PolicyEngineControllerTestItCase.java @@ -0,0 +1,117 @@ +package org.onap.clamp.policy.downloader; +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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============================================ + * =================================================================== + * + */ + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import java.io.IOException; +import java.time.Instant; +import java.util.List; +import javax.transaction.Transactional; +import org.json.simple.parser.ParseException; +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.template.PolicyModel; +import org.onap.clamp.loop.template.PolicyModelId; +import org.onap.clamp.loop.template.PolicyModelsRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@ActiveProfiles({"clamp-default","clamp-policy-controller"}) +public class PolicyEngineControllerTestItCase { + + @Autowired + PolicyEngineController policyController; + + @Autowired + PolicyModelsRepository policyModelsRepository; + + /** + * This method tests a fake synchronization with the emulator. + * + * @throws JsonSyntaxException In case of issues + * @throws IOException In case of issues + * @throws InterruptedException In case of issues + */ + @Test + @Transactional + public void synchronizeAllPoliciesTest() throws JsonSyntaxException, IOException, InterruptedException { + policyController.synchronizeAllPolicies(); + Instant firstExecution = policyController.getLastInstantExecuted(); + assertThat(firstExecution).isNotNull(); + List<PolicyModel> policyModelsList = policyModelsRepository.findAll(); + assertThat(policyModelsList.size()).isGreaterThanOrEqualTo(5); + assertThat(policyModelsList).contains(new PolicyModel("onap.policies.controlloop.operational.common.Drools", + null, "1.0.0")); + assertThat(policyModelsList).contains(new PolicyModel("onap.policies.controlloop.operational.common.Apex", + null, "1.0.0")); + assertThat(policyModelsList) + .contains(new PolicyModel("onap.policies.controlloop.guard.common.FrequencyLimiter", null, "1.0.0")); + assertThat(policyModelsList) + .contains(new PolicyModel("onap.policies.controlloop.guard.common.Blacklist", null, "1.0.0")); + assertThat(policyModelsList) + .contains(new PolicyModel("onap.policies.controlloop.guard.common.MinMax", null, "2.0.0")); + + // Re-do it to check that there is no issue with duplicate key + policyController.synchronizeAllPolicies(); + Instant secondExecution = policyController.getLastInstantExecuted(); + assertThat(secondExecution).isNotNull(); + + assertThat(firstExecution).isBefore(secondExecution); + } + + @Test + @Transactional + public void downloadPdpGroupsTest() throws JsonSyntaxException, IOException, InterruptedException, ParseException { + PolicyModel policyModel1 = new PolicyModel("onap.policies.monitoring.test", null, "1.0.0"); + policyModelsRepository.saveAndFlush(policyModel1); + PolicyModel policyModel2 = new PolicyModel("onap.policies.controlloop.Operational", null, "1.0.0"); + policyModelsRepository.saveAndFlush(policyModel2); + + policyController.downloadPdpGroups(); + + List<PolicyModel> policyModelsList = policyModelsRepository.findAll(); + assertThat(policyModelsList.size()).isGreaterThanOrEqualTo(2); + + PolicyModel policy1 = policyModelsRepository + .getOne(new PolicyModelId("onap.policies.monitoring.test", "1.0.0")); + PolicyModel policy2 = policyModelsRepository + .getOne(new PolicyModelId("onap.policies.controlloop.Operational", "1.0.0")); + + String expectedRes1 = "{\"supportedPdpGroups\":[{\"monitoring\":[\"xacml\"]}]}"; + JsonObject expectedJson1 = JsonUtils.GSON.fromJson(expectedRes1, JsonObject.class); + assertThat(policy1.getPolicyPdpGroup()).isEqualTo(expectedJson1); + String expectedRes2 = "{\"supportedPdpGroups\":[{\"controlloop\":[\"apex\",\"drools\"]}]}"; + JsonObject expectedJson2 = JsonUtils.GSON.fromJson(expectedRes2, JsonObject.class); + assertThat(policy2.getPolicyPdpGroup()).isEqualTo(expectedJson2); + + } +} diff --git a/src/test/java/org/onap/clamp/policy/microservice/MicroServicePayloadTest.java b/src/test/java/org/onap/clamp/policy/microservice/MicroServicePayloadTest.java new file mode 100644 index 000000000..0bfb6ece0 --- /dev/null +++ b/src/test/java/org/onap/clamp/policy/microservice/MicroServicePayloadTest.java @@ -0,0 +1,46 @@ +/*- + * ============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.policy.microservice; + +import com.google.gson.JsonObject; +import java.io.IOException; +import org.junit.Test; +import org.onap.clamp.clds.util.JsonUtils; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.template.PolicyModel; +import org.skyscreamer.jsonassert.JSONAssert; + +public class MicroServicePayloadTest { + + @Test + public void testPayloadConstruction() throws IOException { + MicroServicePolicy policy = new MicroServicePolicy("testPolicy", new PolicyModel( + "onap.policies.monitoring.cdap.tca.hi.lo.app", + ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml"),"1.0.0"), false,null,null, null,null); + policy.setConfigurationsJson(JsonUtils.GSON.fromJson( + ResourceFileUtils.getResourceAsString("tosca/micro-service-policy-properties.json"), JsonObject.class)); + JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/micro-service-policy-payload.json"), + policy.createPolicyPayload(), false); + } +} diff --git a/src/test/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java b/src/test/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java new file mode 100644 index 000000000..322548bb4 --- /dev/null +++ b/src/test/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java @@ -0,0 +1,67 @@ +/*- + * ============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.policy.operational; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import java.io.IOException; +import org.junit.Test; +import org.onap.clamp.clds.util.ResourceFileUtils; +import org.onap.clamp.loop.service.Service; +import org.skyscreamer.jsonassert.JSONAssert; + +public class OperationalPolicyRepresentationBuilderTest { + + @Test + public void testOperationalPolicyPayloadConstruction() throws IOException { + JsonObject jsonModel = new GsonBuilder().create().fromJson(ResourceFileUtils + .getResourceAsString("tosca/model-properties-operational-policy.json"), JsonObject.class); + Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(), + jsonModel.get("resourceDetails").getAsJsonObject(), "1.0"); + + JsonObject jsonSchema = OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(service); + + assertThat(jsonSchema).isNotNull(); + + JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/operational-policy-json-schema.json"), + new GsonBuilder().create().toJson(jsonSchema), false); + } + + @Test + public void testOperationalPolicyPayloadConstructionForCds() throws IOException { + JsonObject jsonModel = new GsonBuilder().create() + .fromJson(ResourceFileUtils.getResourceAsString("tosca/model-properties-cds.json"), JsonObject.class); + Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(), + jsonModel.get("resourceDetails").getAsJsonObject(), + "1.0"); + + JsonObject jsonSchema = OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(service); + assertThat(jsonSchema).isNotNull(); + JSONAssert.assertEquals( + ResourceFileUtils.getResourceAsString("tosca/operational-policy-cds-payload-with-list.json"), + new GsonBuilder().create().toJson(jsonSchema), false); + } +} diff --git a/src/test/java/org/onap/clamp/policy/pdpgroup/PdpGroupTest.java b/src/test/java/org/onap/clamp/policy/pdpgroup/PdpGroupTest.java new file mode 100644 index 000000000..b6f7c5491 --- /dev/null +++ b/src/test/java/org/onap/clamp/policy/pdpgroup/PdpGroupTest.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.pdpgroup; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.junit.Test; + +public class PdpGroupTest { + + + @Test + public void testGetSupportedSubgroups() throws IOException { + PdpGroup pdpGroup1 = new PdpGroup(); + pdpGroup1.setName("pdpGroup1"); + pdpGroup1.setPdpGroupState("INACTIVE"); + assertThat(pdpGroup1.getSupportedSubgroups("test", "1.0.0")).isNull(); + + PdpGroup pdpGroup2 = new PdpGroup(); + pdpGroup2.setName("pdpGroup2"); + pdpGroup2.setPdpGroupState("ACTIVE"); + + PolicyModelKey type1 = new PolicyModelKey("type1", "1.0.0"); + PolicyModelKey type2 = new PolicyModelKey("type2", "2.0.0"); + + PdpSubgroup pdpSubgroup1 = new PdpSubgroup(); + pdpSubgroup1.setPdpType("subGroup1"); + List<PolicyModelKey> pdpTypeList = new LinkedList<PolicyModelKey>(); + pdpTypeList.add(type1); + pdpTypeList.add(type2); + pdpSubgroup1.setSupportedPolicyTypes(pdpTypeList); + + PolicyModelKey type3 = new PolicyModelKey("type3", "1.0.0"); + PdpSubgroup pdpSubgroup2 = new PdpSubgroup(); + pdpSubgroup2.setPdpType("subGroup2"); + List<PolicyModelKey> pdpTypeList2 = new LinkedList<PolicyModelKey>(); + pdpTypeList2.add(type2); + pdpTypeList2.add(type3); + pdpSubgroup2.setSupportedPolicyTypes(pdpTypeList2); + + List<PdpSubgroup> pdpSubgroupList = new LinkedList<PdpSubgroup>(); + pdpSubgroupList.add(pdpSubgroup1); + pdpSubgroupList.add(pdpSubgroup2); + pdpGroup2.setPdpSubgroups(pdpSubgroupList); + + JsonObject res1 = pdpGroup2.getSupportedSubgroups("type2", "2.0.0"); + assertThat(res1.get("pdpGroup2")).isNotNull(); + JsonArray resSubList = res1.getAsJsonArray("pdpGroup2"); + assertThat(resSubList.size()).isEqualTo(2); + assertThat(resSubList.toString().contains("subGroup1")).isTrue(); + assertThat(resSubList.toString().contains("subGroup2")).isTrue(); + + JsonObject res2 = pdpGroup2.getSupportedSubgroups("type1", "1.0.0"); + assertThat(res2.get("pdpGroup2")).isNotNull(); + JsonArray resSubList2 = res2.getAsJsonArray("pdpGroup2"); + assertThat(resSubList2.size()).isEqualTo(1); + + assertThat(pdpGroup2.getSupportedSubgroups("type3", "1.0.1")).isNull(); + } +} diff --git a/src/test/java/org/onap/clamp/policy/pdpgroup/PolicyModelKeyTest.java b/src/test/java/org/onap/clamp/policy/pdpgroup/PolicyModelKeyTest.java new file mode 100644 index 000000000..413ce60ab --- /dev/null +++ b/src/test/java/org/onap/clamp/policy/pdpgroup/PolicyModelKeyTest.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.policy.pdpgroup; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import org.junit.Test; + +public class PolicyModelKeyTest { + + @Test + public void testEqualsMethod() throws IOException { + PolicyModelKey key1 = new PolicyModelKey("name1","1.0.0"); + PolicyModelKey key2 = new PolicyModelKey(null,"1.0.0"); + PolicyModelKey key3 = new PolicyModelKey("name1",null); + + assertThat(key1.equals(null)).isFalse(); + assertThat(key1.equals("key2")).isFalse(); + + assertThat(key2.equals(key1)).isFalse(); + assertThat(key3.equals(key1)).isFalse(); + + PolicyModelKey key4 = new PolicyModelKey("name2","1.0.0"); + PolicyModelKey key5 = new PolicyModelKey("name1","2.0.0"); + assertThat(key1.equals(key4)).isFalse(); + assertThat(key1.equals(key5)).isFalse(); + + PolicyModelKey key6 = new PolicyModelKey("name(.*)","1.0.0"); + PolicyModelKey key7 = new PolicyModelKey("name1","1.0.0"); + assertThat(key1.equals(key6)).isTrue(); + assertThat(key1.equals(key7)).isTrue(); + } +} diff --git a/src/test/java/org/onap/clamp/tosca/DictionaryServiceItCase.java b/src/test/java/org/onap/clamp/tosca/DictionaryServiceItCase.java new file mode 100644 index 000000000..55d347ceb --- /dev/null +++ b/src/test/java/org/onap/clamp/tosca/DictionaryServiceItCase.java @@ -0,0 +1,247 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.tosca; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import javax.persistence.EntityNotFoundException; +import javax.transaction.Transactional; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.clamp.clds.Application; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class DictionaryServiceItCase { + + @Autowired + private DictionaryService dictionaryService; + + @Autowired + private DictionaryElementsRepository dictionaryElementsRepository; + + private DictionaryElement getDictionaryElement(String shortName, String name, + String description, String type, String subDictionaryName) { + + return new DictionaryElement(name, shortName, description, type, subDictionaryName); + + } + + private Dictionary getSimpleDictionaryExample() { + + Dictionary dictionary = new Dictionary("Dictionary1", 0, null); + + dictionary.addDictionaryElements(getDictionaryElement("DE1", "DictionaryElement1", + "DictionaryElement1", "string", null)); + + dictionary.addDictionaryElements(getDictionaryElement("DE2", "DictionaryElement2", + "DictionaryElement2", "number", null)); + + return dictionary; + } + + private Dictionary getSecondaryDictionaryExample() { + + Dictionary dictionary = new Dictionary("SecondaryDict", 1, "string"); + + dictionary.addDictionaryElements(getDictionaryElement("SDE1", "SecondaryDictElement1", + "SecondaryDictElement1", "string", null)); + + dictionary.addDictionaryElements(getDictionaryElement("SDE2", "SecondaryDictElement2", + "SecondaryDictElement2", "string", null)); + + return dictionary; + } + + /** + * Test to validate that Dictionary is created. + */ + @Test + @Transactional + public void shouldCreateDictionary() { + Dictionary dictionary = getSimpleDictionaryExample(); + Dictionary actualDictionary = dictionaryService.saveOrUpdateDictionary(dictionary); + assertNotNull(actualDictionary); + assertThat(actualDictionary).isEqualTo(dictionary); + assertThat(actualDictionary.getName()).isEqualTo(dictionary.getName()); + + assertThat(actualDictionary.getDictionaryElements()).contains( + dictionaryElementsRepository.findById("DE1").get(), + dictionaryElementsRepository.findById("DE2").get()); + } + + /** + * Test to validate a DictionaryElement is created for a Dictionary. + */ + @Test + @Transactional + public void shouldCreateorUpdateDictionaryElement() { + Dictionary dictionary = getSimpleDictionaryExample(); + Dictionary actualDictionary = dictionaryService.saveOrUpdateDictionary(dictionary); + DictionaryElement dictionaryElement = + getDictionaryElement("DictionaryElement3", "DE3", "DictionaryElement3", "date", null); + actualDictionary.addDictionaryElements(dictionaryElement); + Dictionary updatedDictionary = dictionaryService + .saveOrUpdateDictionaryElement(actualDictionary.getName(), actualDictionary); + assertNotNull(updatedDictionary); + assertTrue(updatedDictionary.getDictionaryElements().contains(dictionaryElement)); + assertThat(updatedDictionary.getName()).isEqualTo(actualDictionary.getName()); + // update the dictionary element. + dictionaryElement.setDescription("DictionaryElement3 New Description"); + Dictionary dictionary3 = new Dictionary("Dictionary1", 0, null); + dictionary3.addDictionaryElements(dictionaryElement); + Dictionary updatedDictionary2 = + dictionaryService.saveOrUpdateDictionaryElement(dictionary3.getName(), dictionary3); + + assertNotNull(updatedDictionary2); + assertTrue(updatedDictionary2.getDictionaryElements().contains(dictionaryElement)); + updatedDictionary2.getDictionaryElements().forEach(element -> { + if (element.equals(dictionaryElement)) { + assertTrue(element.getDescription().equals(dictionaryElement.getDescription())); + } + }); + + } + + /** + * Test to validate that All Dictionaries are retrieved. + */ + @Test + @Transactional + public void shouldReturnAllDictionaries() { + Dictionary dictionary = getSimpleDictionaryExample(); + Dictionary secondaryDictionary = getSecondaryDictionaryExample(); + dictionaryService.saveOrUpdateDictionary(dictionary); + dictionaryService.saveOrUpdateDictionary(secondaryDictionary); + + List<Dictionary> list = dictionaryService.getAllDictionaries(); + assertNotNull(list); + assertThat(list).contains(dictionary, secondaryDictionary); + } + + /** + * Test to validate one Dictionary is returned. + */ + @Test + @Transactional + public void shouldReturnOneDictionary() { + Dictionary dictionary = getSimpleDictionaryExample(); + dictionaryService.saveOrUpdateDictionary(dictionary); + + Dictionary returnedDictionary = dictionaryService.getDictionary("Dictionary1"); + assertNotNull(returnedDictionary); + assertThat(returnedDictionary).isEqualTo(dictionary); + assertThat(returnedDictionary.getDictionaryElements()) + .isEqualTo(dictionary.getDictionaryElements()); + } + + /** + * Test to validate one Dictionary is returned. + */ + @Test + @Transactional + public void shouldReturnEntityNotFoundException() { + try { + dictionaryService.getDictionary("Test"); + } catch (Exception e) { + assertThat(e).isInstanceOf(EntityNotFoundException.class); + assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Test")); + } + } + + /** + * Test to validate Dictionary is deleted. + */ + @Test + @Transactional + public void shouldDeleteDictionaryByObject() { + Dictionary dictionary = getSimpleDictionaryExample(); + Dictionary returnedDictionary = dictionaryService.saveOrUpdateDictionary(dictionary); + + dictionaryService.deleteDictionary(returnedDictionary); + try { + dictionaryService.getDictionary("Dictionary1"); + } catch (EntityNotFoundException e) { + assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Dictionary1")); + } + } + + /** + * Test to validate Dictionary is deleted by Name. + */ + @Test + @Transactional + public void shouldDeleteDictionaryByName() { + Dictionary dictionary = getSimpleDictionaryExample(); + dictionaryService.saveOrUpdateDictionary(dictionary); + dictionaryService.deleteDictionary(dictionary.getName()); + try { + dictionaryService.getDictionary("Dictionary1"); + } catch (EntityNotFoundException e) { + assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Dictionary1")); + } + } + + /** + * Test to validate DictionaryElements is deleted by Name. + */ + @Test + @Transactional + public void shouldDeleteDictionaryElementsByName() { + Dictionary dictionary = getSimpleDictionaryExample(); + dictionaryService.saveOrUpdateDictionary(dictionary); + DictionaryElement dictionaryElement = + dictionaryElementsRepository.findById("DE1").orElse(null); + assertNotNull(dictionaryElement); + dictionaryService.deleteDictionaryElement("Dictionary1", "DE1"); + dictionary = dictionaryService.getDictionary("Dictionary1"); + DictionaryElement deletedDictionaryElement = + dictionaryElementsRepository.findById("DE1").orElse(null); + assertThat(deletedDictionaryElement).isNotIn(dictionary.getDictionaryElements()); + } + + /** + * Test to validate all secondary level dictionary names are returned. + */ + @Test + @Transactional + public void shouldReturnAllSecondaryLevelDictionaryNames() { + Dictionary dictionary = getSecondaryDictionaryExample(); + dictionaryService.saveOrUpdateDictionary(dictionary); + + Dictionary dictionary2 = new Dictionary("SecondaryDict2", 1, "string"); + dictionaryService.saveOrUpdateDictionary(dictionary2); + List<String> secondaryDictionaryNames = + dictionaryService.getAllSecondaryLevelDictionaryNames(); + + assertNotNull(secondaryDictionaryNames); + assertThat(secondaryDictionaryNames).contains(dictionary.getName(), dictionary2.getName()); + } +} diff --git a/src/test/java/org/onap/clamp/util/PassDecoderTest.java b/src/test/java/org/onap/clamp/util/PassDecoderTest.java new file mode 100644 index 000000000..e5de8b0a8 --- /dev/null +++ b/src/test/java/org/onap/clamp/util/PassDecoderTest.java @@ -0,0 +1,52 @@ +/*- + * ============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.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class PassDecoderTest { + + private final String encrypted = "enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc"; + + @Test + public final void testDecryptionNoKeyfile() throws Exception { + String decodedPass = PassDecoder.decode(encrypted, null); + assertEquals(decodedPass, encrypted); + } + + @Test + public final void testDecryptionNoPassword() throws Exception { + String decodedPass = PassDecoder.decode(null, "classpath:clds/aaf/org.onap.clamp.keyfile"); + assertNull(decodedPass); + } + + @Test + public final void testDecryption() throws Exception { + String decodedPass = PassDecoder.decode(encrypted, "classpath:clds/aaf/org.onap.clamp.keyfile"); + assertEquals(decodedPass, "China in the Spring"); + } +} diff --git a/src/test/java/org/onap/clamp/util/SemanticVersioningTest.java b/src/test/java/org/onap/clamp/util/SemanticVersioningTest.java new file mode 100644 index 000000000..88f2bbe1b --- /dev/null +++ b/src/test/java/org/onap/clamp/util/SemanticVersioningTest.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2020 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.util; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class SemanticVersioningTest { + + /** + * compare test. + */ + @Test + public void compareTest() { + assertThat(SemanticVersioning.compare("1.0.0", "2.0.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("1.5.0", "2.0.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("1.5.0", "2.1.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("1.5.3", "2.0.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("2.5.3", "2.6.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("2.5", "2.5.1")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("2.5.0", "2.5.1")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("2.5.0.0", "2.5.1")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("2.5.1.0", "2.5.1")).isEqualTo(1); + + assertThat(SemanticVersioning.compare("2.0.0", "1.0.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.0.0", "1.5.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.1.0", "1.5.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.0.0", "1.5.3")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.6.0", "2.5.3")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.5.1", "2.5")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.5.1", "2.5.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("2.5.1", "2.5.0.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("1", "1.2.3.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("1.2", "1")).isEqualTo(1); + } + + /** + * Compare test. + */ + @Test + public void compareEqualsTest() { + assertThat(SemanticVersioning.compare("1.0.0", "1.0.0")).isEqualTo(0); + assertThat(SemanticVersioning.compare("1.0.0.0", "1.0.0")).isEqualTo(1); + assertThat(SemanticVersioning.compare("1.2.3", "1.2.3")).isEqualTo(0); + assertThat(SemanticVersioning.compare("1.2.3", "1.2.3.0")).isEqualTo(-1); + + } + + /** + * Compare with null. + */ + @Test + public void compareNullTest() { + assertThat(SemanticVersioning.compare(null, null)).isEqualTo(0); + assertThat(SemanticVersioning.compare(null, "1.0")).isEqualTo(-1); + assertThat(SemanticVersioning.compare("1.0", null)).isEqualTo(1); + } + + /** + * Increment major version test. + */ + @Test + public void incrementVersionTest() { + assertThat(SemanticVersioning.incrementMajorVersion("1.0")).isEqualTo("2.0.0"); + assertThat(SemanticVersioning.incrementMajorVersion("1.0.0")).isEqualTo("2.0.0"); + assertThat(SemanticVersioning.incrementMajorVersion("1")).isEqualTo("2.0.0"); + assertThat(SemanticVersioning.incrementMajorVersion("1.2.3")).isEqualTo("2.0.0"); + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 000000000..5a668dcf4 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,172 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-2018 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============================================ +# =================================================================== +# +### + +### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time). +### (See below for the parameter 'server.http.port' if you want to have both enabled) +### To have only HTTP, keep the lines server.ssl.* commented +### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location +server.port=${clamp.it.tests.http} +### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port') +#server.ssl.key-store=file:/tmp/mykey.jks +#server.ssl.key-store-password=pass +#server.ssl.key-password=pass + +### In order to be user friendly when HTTPS is enabled, +### you can add another HTTP port that will be automatically redirected to HTTPS +### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...) +#server.http-to-https-redirection.port=8090 + +### HTTP Example: +###-------------- +### server.port=8080 + +### HTTPS Example: +### -------------- +### server.port=8443 +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass + +### HTTP (Redirected to HTTPS) and HTTPS Example: +### -------------------------------------------- +### server.port=8443 <-- The HTTPS port +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass +### server.http-to-https-redirection.port=8090 <-- The HTTP port + +server.servlet.context-path=/ +#Modified engine-rest applicationpath +spring.profiles.active=clamp-default,clamp-default-user +spring.http.converters.preferred-json-mapper=gson + +#The max number of active threads in this pool +server.tomcat.max-threads=200 +#The minimum number of threads always kept alive +server.tomcat.min-Spare-Threads=25 +#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads +server.tomcat.max-idle-time=60000 + +#Servlet context parameters +server.context_parameters.p-name=value #context parameter with p-name as key and value as value. + +camel.springboot.consumer-template-cache-size=1000 +camel.springboot.producer-template-cache-size=1000 +# JMX enabled to have Camel Swagger runtime working +camel.springboot.jmx-enabled=true +camel.defaultthreadpool.poolsize=10 +camel.defaultthreadpool.maxpoolsize=20 +camel.defaultthreadpool.maxqueuesize=1000 +camel.defaultthreadpool.keepaliveTime=60 +camel.defaultthreadpool.rejectpolicy=CallerRuns +#camel.springboot.xmlRoutes = false +camel.springboot.xmlRoutes=classpath:/clds/camel/routes/*.xml +camel.springboot.xmlRests=classpath:/clds/camel/rest/*.xml +#camel.springboot.typeConversion = false + +#clds datasource connection details +spring.datasource.driverClassName=org.mariadb.jdbc.Driver +spring.datasource.url=jdbc:mariadb:sequential://localhost:3306,localhost:${docker.mariadb.port.host}/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3 +spring.datasource.username=clds +spring.datasource.password=sidnnd83K +spring.datasource.validationQuery=SELECT 1 +spring.datasource.validationQueryTimeout=20000 +spring.datasource.validationInterval=30000 +spring.datasource.testWhileIdle = true +spring.datasource.minIdle = 0 +spring.datasource.initialSize=0 +# Automatically test whether a connection provided is good or not +spring.datasource.testOnBorrow=true +spring.datasource.ignoreExceptionOnPreLoad=true + +spring.jpa.properties.javax.persistence.schema-generation.database.action=none +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +# disable Hibernate DDL generation because the schema will be generated from a sql script +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.ddl-auto=validate +spring.jpa.properties.hibernate.hbm2ddl.delimiter=; +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.use-new-id-generator-mappings=true + +# Whether to enable logging of SQL statements. +#spring.jpa.show-sql=true + +#Async Executor default Parameters +async.core.pool.size=10 +async.max.pool.size=20 +async.queue.capacity=500 + +#For EELF logback file +#com.att.eelf.logging.path= +clamp.config.logback.filename=logback-default.xml +#The log folder that will be used in logback.xml file +clamp.config.log.path=log +clamp.config.files.systemProperties=classpath:/system.properties +clamp.config.files.cldsUsers=classpath:/clds/clds-users.json +clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json +clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json + +# +# Configuration Settings for Policy Engine Components +clamp.config.policy.api.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.policy.api.userName=healthcheck +clamp.config.policy.api.password=zb!XztG34 +clamp.config.policy.pap.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.policy.pap.userName=healthcheck +clamp.config.policy.pap.password=zb!XztG34 + +# Sdc service properties +# +clamp.config.sdc.csarFolder = ${project.build.directory}/sdc-tests + +#DCAE Inventory Url Properties +clamp.config.dcae.inventory.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.dcae.intentory.retry.interval=100 +clamp.config.dcae.intentory.retry.limit=1 + +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + +#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! +clamp.config.security.permission.type.cl=permission-type-cl +clamp.config.security.permission.type.cl.manage=permission-type-cl-manage +clamp.config.security.permission.type.cl.event=permission-type-cl-event +clamp.config.security.permission.type.filter.vf=permission-type-filter-vf +clamp.config.security.permission.type.template=permission-type-template +clamp.config.security.permission.type.tosca=permission-type-tosca +#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties +clamp.config.security.permission.instance=dev +clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal +# Configuration settings for CDS +clamp.config.cds.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.cds.userName=ccsdkapps +clamp.config.cds.password=ccsdkapps + +## Tosca converter +clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json +clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml +clamp.config.tosca.converter.dictionary.support.enabled=true
\ No newline at end of file diff --git a/src/test/resources/clds/blueprint-with-microservice-chain.yaml b/src/test/resources/clds/blueprint-with-microservice-chain.yaml new file mode 100644 index 000000000..0e9e4bc8c --- /dev/null +++ b/src/test/resources/clds/blueprint-with-microservice-chain.yaml @@ -0,0 +1,202 @@ +tosca_definitions_version: cloudify_dsl_1_3 + +description: > + This blueprint deploys/manages the TCA module as a Docker container + +imports: + - http://www.getcloudify.org/spec/cloudify/3.4/types.yaml + - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.12/k8splugin_types.yaml + - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/dcaepolicyplugin/2.3.0/dcaepolicyplugin_types.yaml +inputs: + aaiEnrichmentHost: + type: string + default: "aai.onap.svc.cluster.local" + aaiEnrichmentPort: + type: string + default: "8443" + enableAAIEnrichment: + type: string + default: true + dmaap_host: + type: string + default: message-router.onap.svc.cluster.local + dmaap_port: + type: string + default: "3904" + enableRedisCaching: + type: string + default: false + redisHosts: + type: string + default: dcae-redis.onap.svc.cluster.local:6379 + tag_version: + type: string + default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.0-STAGING-latest" + consul_host: + type: string + default: consul-server.onap.svc.cluster.local + consul_port: + type: string + default: "8500" + cbs_host: + type: string + default: "config-binding-service.dcae.svc.cluster.local" + cbs_port: + type: string + default: "10000" + policy_id: + type: string + default: "none" + external_port: + type: string + description: Kubernetes node port on which CDAPgui is exposed + default: "32012" + policy_model_id: + type: string + default: "onap.policies.monitoring.cdap.tca.hi.lo.app" + +node_templates: + first_app: + type: dcae.nodes.ContainerizedServiceComponent + properties: + service_component_type: 'dcaegen2-analytics-tca' + application_config: {} + docker_config: {} + image: + get_input: tag_version + log_info: + log_directory: "/opt/app/TCAnalytics/logs" + relationships: + - target: tca_policy_1 + type: cloudify.relationships.depends_on + second_app: + type: dcae.nodes.ContainerizedServiceComponent + relationships: + - target: tca_policy_2 + type: cloudify.relationships.depends_on + - type: clamp_node.relationships.gets_input_from + target: first_app + properties: + service_component_type: 'dcaegen2-analytics-tca' + application_config: {} + docker_config: {} + image: + get_input: tag_version + log_info: + log_directory: "/opt/app/TCAnalytics/logs" + application_config: + app_config: + appDescription: DCAE Analytics Threshold Crossing Alert Application + appName: dcae-tca + tcaAlertsAbatementTableName: TCAAlertsAbatementTable + tcaAlertsAbatementTableTTLSeconds: '1728000' + tcaSubscriberOutputStreamName: TCASubscriberOutputStream + tcaVESAlertsTableName: TCAVESAlertsTable + tcaVESAlertsTableTTLSeconds: '1728000' + tcaVESMessageStatusTableName: TCAVESMessageStatusTable + tcaVESMessageStatusTableTTLSeconds: '86400' + thresholdCalculatorFlowletInstances: '2' + app_preferences: + aaiEnrichmentHost: + get_input: aaiEnrichmentHost + aaiEnrichmentIgnoreSSLCertificateErrors: 'true' + aaiEnrichmentPortNumber: '8443' + aaiEnrichmentProtocol: https + aaiEnrichmentUserName: dcae@dcae.onap.org + aaiEnrichmentUserPassword: demo123456! + aaiVMEnrichmentAPIPath: /aai/v11/search/nodes-query + aaiVNFEnrichmentAPIPath: /aai/v11/network/generic-vnfs/generic-vnf + enableAAIEnrichment: + get_input: enableAAIEnrichment + enableRedisCaching: + get_input: enableRedisCaching + redisHosts: + get_input: redisHosts + enableAlertCEFFormat: 'false' + publisherContentType: application/json + publisherHostName: + get_input: dmaap_host + publisherHostPort: + get_input: dmaap_port + publisherMaxBatchSize: '1' + publisherMaxRecoveryQueueSize: '100000' + publisherPollingInterval: '20000' + publisherProtocol: http + publisherTopicName: unauthenticated.DCAE_CL_OUTPUT + subscriberConsumerGroup: OpenDCAE-c12 + subscriberConsumerId: c12 + subscriberContentType: application/json + subscriberHostName: + get_input: dmaap_host + subscriberHostPort: + get_input: dmaap_port + subscriberMessageLimit: '-1' + subscriberPollingInterval: '30000' + subscriberProtocol: http + subscriberTimeoutMS: '-1' + subscriberTopicName: unauthenticated.VES_MEASUREMENT_OUTPUT + tca_policy: '' + service_component_type: dcaegen2-analytics_tca + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + DMAAPHOST: + { get_input: dmaap_host } + DMAAPPORT: + { get_input: dmaap_port } + DMAAPPUBTOPIC: "unauthenticated.DCAE_CL_OUTPUT" + DMAAPSUBTOPIC: "unauthenticated.VES_MEASUREMENT_OUTPUT" + AAIHOST: + { get_input: aaiEnrichmentHost } + AAIPORT: + { get_input: aaiEnrichmentPort } + CONSUL_HOST: + { get_input: consul_host } + CONSUL_PORT: + { get_input: consul_port } + CBS_HOST: + { get_input: cbs_host } + CBS_PORT: + { get_input: cbs_port } + CONFIG_BINDING_SERVICE: "config_binding_service" + ports: + - concat: ["11011:", { get_input: external_port }] + third_app: + type: dcae.nodes.ContainerizedServiceComponent + properties: + service_component_type: 'dcaegen2-analytics-tca' + application_config: {} + docker_config: {} + image: + get_input: tag_version + log_info: + log_directory: "/opt/app/TCAnalytics/logs" + relationships: + - target: tca_policy_3 + type: cloudify.relationships.depends_on + - type: clamp_node.relationships.gets_input_from + target: second_app + tca_policy_1: + type: dcae.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: + get_input: policy_model_id + tca_policy_2: + type: dcae.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: + get_input: policy_model_id + + tca_policy_3: + type: dcae.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: + get_input: policy_model_id diff --git a/src/test/resources/clds/clds-parse-exception.json b/src/test/resources/clds/clds-parse-exception.json new file mode 100644 index 000000000..1c06a3947 --- /dev/null +++ b/src/test/resources/clds/clds-parse-exception.json @@ -0,0 +1 @@ +This is not json
\ No newline at end of file diff --git a/src/test/resources/clds/clds-users-incomplete-permissions.json b/src/test/resources/clds/clds-users-incomplete-permissions.json new file mode 100644 index 000000000..9e3534ff4 --- /dev/null +++ b/src/test/resources/clds/clds-users-incomplete-permissions.json @@ -0,0 +1,14 @@ +[ + { + "user": "admin1", + "password": "5f4dcc3b5aa765d61d8327deb882cf99", + "permissions": [ + "permission-type-cl|dev|", + "permission-type-cl|dev", + "permission-type-cl-manage|dev|*", + "permission-type-filter-vf|dev|*", + "permission-type-template|dev|read", + "permission-type-template|dev|update" + ] + } +] diff --git a/src/test/resources/clds/clds-users-no-permission.json b/src/test/resources/clds/clds-users-no-permission.json new file mode 100644 index 000000000..ac91540f2 --- /dev/null +++ b/src/test/resources/clds/clds-users-no-permission.json @@ -0,0 +1,7 @@ +[ + { + "user": "admin1", + "permissions": [ + ] + } +] diff --git a/src/test/resources/clds/clds-users-two-users.json b/src/test/resources/clds/clds-users-two-users.json new file mode 100644 index 000000000..b3721946a --- /dev/null +++ b/src/test/resources/clds/clds-users-two-users.json @@ -0,0 +1,26 @@ +[ + { + "user": "admin1", + "password": "5f4dcc3b5aa765d61d8327deb882cf99", + "permissions": [ + "permission-type-cl|dev|read", + "permission-type-cl|dev|update", + "permission-type-cl-manage|dev|*", + "permission-type-filter-vf|dev|*", + "permission-type-template|dev|read", + "permission-type-template|dev|update" + ] + }, + { + "user": "admin2", + "password": "5f4dcc3b5aa765d61d8327deb882cf99", + "permissions": [ + "permission-type-cl|dev|read", + "permission-type-cl|dev|update", + "permission-type-cl-manage|dev|*", + "permission-type-filter-vf|dev|*", + "permission-type-template|dev|read", + "permission-type-template|dev|update" + ] + } +] diff --git a/src/test/resources/clds/new-microservice.yaml b/src/test/resources/clds/new-microservice.yaml new file mode 100644 index 000000000..70c1eda46 --- /dev/null +++ b/src/test/resources/clds/new-microservice.yaml @@ -0,0 +1,46 @@ +tosca_definitions_version: cloudify_dsl_1_3 + +imports: + - "http://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml" + - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R5/k8splugin/1.4.13/k8splugin_types.yaml" + - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R5/clamppolicyplugin/1.0.0/clamppolicyplugin_types.yaml" + +inputs: + tag_version: + type: string + description: docker image + policy_model_id: + type: 'string' + default: 'onap.policies.monitoring.dcae-pm-initiation-handler' + policy_id: + type: 'string' + default: 'onap.policies.monitoring.dcae-pm-initiation-handler' + +node_templates: + pmsh: + relationships: + - type: cloudify.relationships.depends_on + target: pmsh-policy + + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + ports: + - '8443:0' + - '8081:0' + properties: + image: + get_input: tag_version + replicas: 1 + service_component_type: "pmsh" + service_component_name_override: "pmsh" + type: dcae.nodes.ContainerizedServiceComponent + + pmsh-policy: + type: clamp.nodes.policy + properties: + policy_model_id: + get_input: policy_model_id + policy_id: + get_input: policy_id diff --git a/src/test/resources/clds/sdc-controller-config-NULL.json b/src/test/resources/clds/sdc-controller-config-NULL.json new file mode 100644 index 000000000..bf310c706 --- /dev/null +++ b/src/test/resources/clds/sdc-controller-config-NULL.json @@ -0,0 +1,11 @@ +{ + "user": "User", + "consumerGroup": "NULL", + "consumerId": "consumerId", + "environmentName": "environmentName", + "sdcAddress": "hostname:8080", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30, + "messageBusAddresses":["localhost"] +} diff --git a/src/test/resources/clds/sdc-controller-config-TLS.json b/src/test/resources/clds/sdc-controller-config-TLS.json new file mode 100644 index 000000000..99366b765 --- /dev/null +++ b/src/test/resources/clds/sdc-controller-config-TLS.json @@ -0,0 +1,14 @@ +{ + "user": "User", + "consumerGroup": "consumerGroup", + "consumerId": "consumerId", + "environmentName": "environmentName", + "sdcAddress": "hostname:8080", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30, + "activateServerTLSAuth": true, + "keyStorePassword":"bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "keyStorePath": "/test", + "messageBusAddresses":["localhost"] +} diff --git a/src/test/resources/clds/sdc-controller-config-bad.json b/src/test/resources/clds/sdc-controller-config-bad.json new file mode 100644 index 000000000..194ff5f4b --- /dev/null +++ b/src/test/resources/clds/sdc-controller-config-bad.json @@ -0,0 +1,13 @@ +{ + "sdc-connections": { + "sdc-controller1": { + "user": "testuser", + "consumerGroup": "consumerGroup", + "consumerId": "consumerId", + "environmentName": "environmentName", + "sdcAddress": "hostname1:8080", + "pollingInterval": 10, + "pollingTimeout": 30 + } + } +} diff --git a/src/test/resources/clds/sdc-controller-config-empty-encrypted.json b/src/test/resources/clds/sdc-controller-config-empty-encrypted.json new file mode 100644 index 000000000..2a70b9edc --- /dev/null +++ b/src/test/resources/clds/sdc-controller-config-empty-encrypted.json @@ -0,0 +1,14 @@ +{ + "user": "User", + "consumerGroup": "consumerGroup", + "consumerId": "consumerId", + "environmentName": "environmentName", + "sdcAddress": "hostname:8080", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30, + "activateServerTLSAuth": true, + "keyStorePassword":"", + "keyStorePath": "/test", + "messageBusAddresses":["localhost"] +} diff --git a/src/test/resources/clds/sdc-controllers-config-bad.json b/src/test/resources/clds/sdc-controllers-config-bad.json new file mode 100644 index 000000000..0b417b745 --- /dev/null +++ b/src/test/resources/clds/sdc-controllers-config-bad.json @@ -0,0 +1,26 @@ +{ + "sdc-connections":{, + "sdc-controller1":{ + "user": "User1", + "consumerGroup": "consumerGroup1", + "consumerId": "consumerId1", + "environmentName": "environmentName1", + "sdcAddress": "hostname1", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30 + + }, + "sdc-controller2":{ + "user": "User2", + "consumerGroup": "consumerGroup2", + "consumerId": "consumerId2", + "environmentName": "environmentName2", + "sdcAddress": "hostname2", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30 + + } + } +} diff --git a/src/test/resources/clds/sdc-controllers-config-missing-param.json b/src/test/resources/clds/sdc-controllers-config-missing-param.json new file mode 100644 index 000000000..d99ed5801 --- /dev/null +++ b/src/test/resources/clds/sdc-controllers-config-missing-param.json @@ -0,0 +1,13 @@ +{ + "sdc-connections": { + "sdc-controller1": { + "user": "testuser", + "consumerGroup": "consumerGroup", + "consumerId": "consumerId", + "environmentName": "environmentName", + "sdcAddress": "hostname1", + "pollingInterval": 10, + "pollingTimeout": 30 + } + } +} diff --git a/src/test/resources/clds/sdc-controllers-config.json b/src/test/resources/clds/sdc-controllers-config.json new file mode 100644 index 000000000..ce56fef27 --- /dev/null +++ b/src/test/resources/clds/sdc-controllers-config.json @@ -0,0 +1,27 @@ +{ + "sdc-connections":{ + "sdc-controller1":{ + "user": "User1", + "consumerGroup": "consumerGroup1", + "consumerId": "consumerId1", + "environmentName": "environmentName1", + "sdcAddress": "localhost:${docker.http-cache.port.host}", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30, + "messageBusAddresses":["localhost"] + }, + "sdc-controller2":{ + "user": "User2", + "consumerGroup": "consumerGroup2", + "consumerId": "consumerId2", + "environmentName": "environmentName2", + "sdcAddress": "localhost:${docker.http-cache.port.host}", + "password": "bb3871669d893c7fb8aaacda31b77b4f537E67A081C2726889548ED7BC4C2DE6", + "pollingInterval":10, + "pollingTimeout":30, + "messageBusAddresses":["localhost"] + + } + } +} diff --git a/src/test/resources/clds/single-microservice-fragment-invalid.yaml b/src/test/resources/clds/single-microservice-fragment-invalid.yaml new file mode 100644 index 000000000..2c1680717 --- /dev/null +++ b/src/test/resources/clds/single-microservice-fragment-invalid.yaml @@ -0,0 +1,25 @@ +second_app: + type: dcae.nodes.ContainerizedServiceComponentUsingDmaap + properties: + service_component_type: dcaegen2-analytics-tca + service_component_name_override: second_app + image: { get_input: second_app_docker_image } + name: second_app + policy_id: + policy_model_id: "type1" + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + grpc_server.host: "first_app.onap" + dmaap_ip: {get_input: dmaap_ip} + dmapp_topic: {get_input: dmaap_topic} + policy_id: {get_input: policy_id} + ports: + - 8080:8080 + relationships: + - type: cloudify.relationships.connected_to + target: first_app + - type: clamp_node.relationships.gets_input_from + target: first_app
\ No newline at end of file diff --git a/src/test/resources/clds/single-microservice-fragment-valid-with-version.yaml b/src/test/resources/clds/single-microservice-fragment-valid-with-version.yaml new file mode 100644 index 000000000..ae31fb16a --- /dev/null +++ b/src/test/resources/clds/single-microservice-fragment-valid-with-version.yaml @@ -0,0 +1,21 @@ +second_app: + type: dcae.nodes.ContainerizedServiceComponentUsingDmaap + properties: + service_component_type: dcaegen2-analytics-tca + service_component_name_override: second_app + image: { get_input: second_app_docker_image } + name: second_app + policy_id: + policy_model_id: "type1" + policy_model_version: "10.0.0" + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + grpc_server.host: "first_app.onap" + dmaap_ip: {get_input: dmaap_ip} + dmapp_topic: {get_input: dmaap_topic} + policy_id: {get_input: policy_id} + ports: + - 8080:8080 diff --git a/src/test/resources/clds/single-microservice-fragment-without-name.yaml b/src/test/resources/clds/single-microservice-fragment-without-name.yaml new file mode 100644 index 000000000..f9ac53cac --- /dev/null +++ b/src/test/resources/clds/single-microservice-fragment-without-name.yaml @@ -0,0 +1,22 @@ +second_app: + type: dcae.nodes.ContainerizedServiceComponentUsingDmaap + properties: + service_component_type: dcaegen2-analytics-tca + service_component_name_override: second_app + image: { get_input: second_app_docker_image } + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + grpc_server.host: "first_app.onap" + dmaap_ip: {get_input: dmaap_ip} + dmapp_topic: {get_input: dmaap_topic} + policy_id: {get_input: policy_id} + ports: + - 8080:8080 + relationships: + - type: cloudify.relationships.connected_to + target: first_app + - type: clamp_node.relationships.gets_input_from + target: first_app
\ No newline at end of file diff --git a/src/test/resources/clds/single-microservice-fragment-without-properties.yaml b/src/test/resources/clds/single-microservice-fragment-without-properties.yaml new file mode 100644 index 000000000..a34ccc6d4 --- /dev/null +++ b/src/test/resources/clds/single-microservice-fragment-without-properties.yaml @@ -0,0 +1,18 @@ +second_app: + type: dcae.nodes.ContainerizedServiceComponentUsingDmaap + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + grpc_server.host: "first_app.onap" + dmaap_ip: {get_input: dmaap_ip} + dmapp_topic: {get_input: dmaap_topic} + policy_id: {get_input: policy_id} + ports: + - 8080:8080 + relationships: + - type: cloudify.relationships.connected_to + target: first_app + - type: clamp_node.relationships.gets_input_from + target: first_app
\ No newline at end of file diff --git a/src/test/resources/clds/single-microservice-fragment-without-relationships.yaml b/src/test/resources/clds/single-microservice-fragment-without-relationships.yaml new file mode 100644 index 000000000..0354acd69 --- /dev/null +++ b/src/test/resources/clds/single-microservice-fragment-without-relationships.yaml @@ -0,0 +1,18 @@ +second_app: + type: dcae.nodes.ContainerizedServiceComponentUsingDmaap + properties: + service_component_type: dcaegen2-analytics-tca + service_component_name_override: second_app + image: { get_input: second_app_docker_image } + name: second_app + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + grpc_server.host: "first_app.onap" + dmaap_ip: {get_input: dmaap_ip} + dmapp_topic: {get_input: dmaap_topic} + policy_id: {get_input: policy_id} + ports: + - 8080:8080
\ No newline at end of file diff --git a/src/test/resources/clds/templates/dcae-deployment-template.json b/src/test/resources/clds/templates/dcae-deployment-template.json new file mode 100644 index 000000000..d4891747e --- /dev/null +++ b/src/test/resources/clds/templates/dcae-deployment-template.json @@ -0,0 +1,9 @@ +{ + "serviceTypeId": "???", + "inputs": { + "aaiEnrichmentHost": "10.0.1.1", + "enableAAIEnrichment": "true", + "subscriberHostName": "10.0.11.1", + "publisherHostName": "10.0.11.1" + } +} diff --git a/src/test/resources/clds/templates/dcae-template.json b/src/test/resources/clds/templates/dcae-template.json new file mode 100644 index 000000000..b76baf2d4 --- /dev/null +++ b/src/test/resources/clds/templates/dcae-template.json @@ -0,0 +1,26 @@ +{ + "properties": { + "service_name": "", + "service_ids": [ + ], + "vnf_ids": [ + ], + "location_ids": [ + ] + }, + "template": { + "tca": { + "dcae": { + "inputTopic": "", + "outputTopic": "", + "closedLoopControlName": "", + "closedLoopEventClient": "configuration.dcae.microservice.tca.xml", + "policyName": "", + "policyScope": "DCAE", + "policyVersion": "v0.0.1", + "serviceConfigurations": { + } + } + } + } +} diff --git a/src/test/resources/clds/templates/globalProperties.json b/src/test/resources/clds/templates/globalProperties.json new file mode 100644 index 000000000..067063ea2 --- /dev/null +++ b/src/test/resources/clds/templates/globalProperties.json @@ -0,0 +1,104 @@ +{ + "tca": { + "tname": "New_Set", + "tcaInt": "1", + "tcaVio": "1", + "eventName": { + "vLoadBalancer": "vLoadBalancer", + "vFirewallBroadcastPackets": "vFirewallBroadcastPackets", + "Measurement_vGMUX":"Measurement_vGMUX" + }, + "fieldPathM": { + "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value": "packetLossRate", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta":"receivedTotalPacketsDelta" + }, + "operator": { + ">": "GREATER", + ">=": "GREATER_OR_EQUAL", + "=": "EQUAL", + "<=": "LESS_OR_EQUAL", + "<": "LESS" + }, + "opsPolicy": { + "POLICY_test_X": "POLICY_test_X", + "POLICY_test_Y": "POLICY_test_Y" + }, + "controlLoopSchemaType": { + "": "", + "VM": "VM", + "VNF": "VNF" + }, + "closedLoopEventStatus": { + "": "", + "ONSET": "ONSET", + "ABATED": "ABATED" + } + }, + "global": { + "actionSet": { + "vnfRecipe": "VNF" + }, + "location": { + "DC1": "Data Center 1", + "DC2": "Data Center 2", + "DC3": "Data Center 3" + } + }, + "policy": { + "pname": "0", + "timeout": 345, + "vnfRecipe": { + "": "", + "Restart": "Restart", + "Rebuild": "Rebuild", + "Migrate": "Migrate", + "HealthCheck": "Health Check", + "ModifyConfig": "Modify Config", + "VF Module Create":"VF Module Create", + "VF Module Delete":"VF Module Delete", + "Reroute":"Reroute" + }, + "maxRetries": "3", + "retryTimeLimit": 180, + "resource": { + "vCTS": "vCTS", + "v3CDB": "v3CDB", + "vUDR": "vUDR", + "vCOM": "vCOM", + "vRAR": "vRAR", + "vLCS": "vLCS", + "vUDR-BE": "vUDR-BE", + "vDBE": "vDBE" + }, + "parentPolicyConditions": { + "Failure_Retries": "Failure: Max Retries Exceeded", + "Failure_Timeout": "Failure: Time Limit Exceeded", + "Failure_Guard": "Failure: Guard", + "Failure_Exception": "Failure: Exception", + "Failure": "Failure: Other", + "Success": "Success" + } + }, + "shared": { + "byService": { + "": { + "vf": { + "": "" + }, + "location": { + "": "" + }, + "alarmCondition": { + "": "" + } + } + }, + "byVf": { + "": { + "vfc": { + "": "" + } + } + } + } +} diff --git a/src/test/resources/clds/templates/sdc-decode-service_ids.json b/src/test/resources/clds/templates/sdc-decode-service_ids.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/src/test/resources/clds/templates/sdc-decode-service_ids.json @@ -0,0 +1 @@ +{}
\ No newline at end of file diff --git a/src/test/resources/clds/templates/sdc-template.json b/src/test/resources/clds/templates/sdc-template.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/src/test/resources/clds/templates/sdc-template.json @@ -0,0 +1 @@ +{}
\ No newline at end of file diff --git a/src/test/resources/clds/templates/tca-policy-template.json b/src/test/resources/clds/templates/tca-policy-template.json new file mode 100644 index 000000000..559aacb29 --- /dev/null +++ b/src/test/resources/clds/templates/tca-policy-template.json @@ -0,0 +1,19 @@ +{ + "service": "tca_policy", + "version": "1.1.0", + "location": "SampleServiceLocation", + "configName": "SampleConfigName", + "uuid": "test", + "policyScope": "CLAMP", + "templateVersion": "OpenSource.version.1", + "policyName": "MicroService", + "description": "MicroService Policy", + "priority": "1", + "riskType": "SampleRiskType", + "riskLevel": "1", + "guard": "False", + "content": { + "tca_policy": { + } + } +} diff --git a/src/test/resources/clds/templates/tca-template.json b/src/test/resources/clds/templates/tca-template.json new file mode 100644 index 000000000..892fc0d62 --- /dev/null +++ b/src/test/resources/clds/templates/tca-template.json @@ -0,0 +1,14 @@ +{ + "domain": "measurementsForVfScaling", + "metricsPerEventName": [ + { + "eventName": "???", + "controlLoopSchemaType": "VNF", + "policyScope": "DCAE", + "policyName": "???", + "policyVersion": "v0.0.1", + "thresholds": [ + ] + } + ] +} diff --git a/src/test/resources/clds/templates/tca-thresholds-template.json b/src/test/resources/clds/templates/tca-thresholds-template.json new file mode 100644 index 000000000..b67e96321 --- /dev/null +++ b/src/test/resources/clds/templates/tca-thresholds-template.json @@ -0,0 +1,9 @@ +{ + "closedLoopControlName": "???", + "version": "1.0.2", + "fieldPath": "?????", + "thresholdValue": 0, + "direction": "???", + "severity": "MAJOR", + "closedLoopEventStatus": "???" +} diff --git a/src/test/resources/clds/templates/ui-location-default.json b/src/test/resources/clds/templates/ui-location-default.json new file mode 100644 index 000000000..c0043d988 --- /dev/null +++ b/src/test/resources/clds/templates/ui-location-default.json @@ -0,0 +1,5 @@ +{ + "DC1": "Data Center 1", + "DC2": "Data Center 2", + "DC3": "Data Center 3" +} diff --git a/src/test/resources/clds/util/file.xml b/src/test/resources/clds/util/file.xml new file mode 100644 index 000000000..81560bab4 --- /dev/null +++ b/src/test/resources/clds/util/file.xml @@ -0,0 +1,6 @@ +<note> + <to>Tove</to> + <from>Jani</from> + <heading>Reminder</heading> + <body>Message body</body> +</note> diff --git a/src/test/resources/example/cds-response/vFW-CDS-modify-config-wf-expected-result.json b/src/test/resources/example/cds-response/vFW-CDS-modify-config-wf-expected-result.json new file mode 100644 index 000000000..2b6493176 --- /dev/null +++ b/src/test/resources/example/cds-response/vFW-CDS-modify-config-wf-expected-result.json @@ -0,0 +1,30 @@ +{ + "inputs": { + "modify-config-properties": { + "type": "object", + "properties": { + "service-instance-id": { + "type": "string", + "input-param": true + }, + "update-active-streams": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "dt-data" + } + }, + "generic-vnf.vnf-id": { + "type": "string", + "input-param": true + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/cds-response/vFW-CDS-modify-config-workflow.json b/src/test/resources/example/cds-response/vFW-CDS-modify-config-workflow.json new file mode 100644 index 000000000..115d79b1f --- /dev/null +++ b/src/test/resources/example/cds-response/vFW-CDS-modify-config-workflow.json @@ -0,0 +1,78 @@ +{ + "blueprintName": "vFW-CDS", + "version": "1.0.0", + "workFlowData": { + "workFlowName": "modify-config", + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "modify-config-properties": { + "description": "Dynamic PropertyDefinition for workflow(modify-config).", + "required": true, + "type": "dt-modify-config-properties" + } + } + }, + "dataTypes": { + "dt-modify-config-properties": { + "description": "Dynamic DataType definition for workflow(modify-config).", + "version": "1.0.0", + "properties": { + "vpg_onap_private_ip_0": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + }, + "service-instance.service-instance-id": { + "type": "string" + }, + "vnf-id": { + "type": "string" + }, + "data": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "dt-data" + } + }, + "service-instance-id": { + "type": "string", + "input-param": true + }, + "update-active-streams": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "dt-data" + } + }, + "generic-vnf.vnf-id": { + "type": "string", + "input-param": true + } + }, + "derived_from": "tosca.datatypes.Dynamic" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json b/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json new file mode 100644 index 000000000..07d851f38 --- /dev/null +++ b/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json @@ -0,0 +1,40 @@ +{ + "inputs": { + "template-prefix-with-complex-type": { + "type": "list", + "properties": { + "prefix-id": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + } + }, + "resource-assignment-properties": { + "type": "object", + "properties": { + "private1-prefix-id": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-workflow.json b/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-workflow.json new file mode 100644 index 000000000..7f76c6cae --- /dev/null +++ b/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-workflow.json @@ -0,0 +1,80 @@ +{ + "blueprintName": "vFW-CDS", + "version": "1.0.0", + "workFlowData": { + "workFlowName": "resource-assignment", + "inputs": { + "template-prefix": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "template-prefix-with-complex-type": { + "required": true, + "type": "list", + "entry_schema": { + "type": "dt-template-prefix-properties" + } + }, + "resource-assignment-properties": { + "description": "Dynamic PropertyDefinition for workflow(resource-assignment).", + "required": true, + "type": "dt-resource-assignment-properties" + } + }, + "outputs": { + "meshed-template": { + "type": "json", + "value": { + "get_attribute": [ + "resource-assignment", + "assignment-params" + ] + } + } + } + }, + "dataTypes": { + "dt-resource-assignment-properties": { + "description": "Dynamic DataType definition for workflow(resource-assignment).", + "version": "1.0.0", + "properties": { + "private1-prefix-id": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-template-prefix-properties": { + "description": "Dynamic DataType definition for workflow(template-prefix).", + "version": "1.0.0", + "properties": { + "prefix-id": { + "description": "", + "required": false, + "type": "string", + "input-param": true, + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/sdc/blueprint-dcae/tca-guilin.yaml b/src/test/resources/example/sdc/blueprint-dcae/tca-guilin.yaml new file mode 100644 index 000000000..e7d967a26 --- /dev/null +++ b/src/test/resources/example/sdc/blueprint-dcae/tca-guilin.yaml @@ -0,0 +1,141 @@ +# ============LICENSE_START==================================================== +# ============================================================================= +# Copyright (C) 2019-2020 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====================================================== +#k8s-tca-gen2-v3.yaml + +tosca_definitions_version: cloudify_dsl_1_3 +imports: + - https://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml + - plugin:k8splugin?version=3.4.2 + - plugin:clamppolicyplugin?version=1.1.0 +inputs: + service_name: + type: string + default: 'dcae-tcagen2' + log_directory: + type: string + default: "/opt/logs/dcae-analytics-tca" + replicas: + type: integer + description: number of instances + default: 1 + spring.data.mongodb.uri: + type: string + default: "mongodb://dcae-mongohost/dcae-tcagen2" + tag_version: + type: string + default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.analytics.tca-gen2.dcae-analytics-tca-web:1.2.1" + tca.aai.password: + type: string + default: "DCAE" + tca.aai.url: + type: string + default: "http://aai.onap.svc.cluster.local" + tca.aai.username: + type: string + default: "DCAE" + tca_handle_in_subscribe_url: + type: string + default: "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.VES_MEASUREMENT_OUTPUT" + tca_handle_out_publish_url: + type: string + default: "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.DCAE_CL_OUTPUT" + tca_consumer_group: + type: string + default: "cg1" + policy_model_id: + type: string + default: "onap.policies.monitoring.tcagen2" + policy_id: + type: string + default: "onap.restart.tca" +node_templates: + docker.tca: + type: dcae.nodes.ContainerizedServiceComponent + relationships: + - target: tcagen2_policy + type: cloudify.relationships.depends_on + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + ports: + - concat: ["9091:", "0"] + properties: + application_config: + service_calls: [] + streams_publishes: + tca_handle_out: + dmaap_info: + topic_url: + get_input: tca_handle_out_publish_url + type: message_router + streams_subscribes: + tca_handle_in: + dmaap_info: + topic_url: + get_input: tca_handle_in_subscribe_url + type: message_router + spring.data.mongodb.uri: + get_input: spring.data.mongodb.uri + streams_subscribes.tca_handle_in.consumer_group: + get_input: tca_consumer_group + streams_subscribes.tca_handle_in.consumer_ids[0]: c0 + streams_subscribes.tca_handle_in.consumer_ids[1]: c1 + streams_subscribes.tca_handle_in.message_limit: 50000 + streams_subscribes.tca_handle_in.polling.auto_adjusting.max: 60000 + streams_subscribes.tca_handle_in.polling.auto_adjusting.min: 30000 + streams_subscribes.tca_handle_in.polling.auto_adjusting.step_down: 30000 + streams_subscribes.tca_handle_in.polling.auto_adjusting.step_up: 10000 + streams_subscribes.tca_handle_in.polling.fixed_rate: 0 + streams_subscribes.tca_handle_in.timeout: -1 + tca.aai.enable_enrichment: true + tca.aai.generic_vnf_path: aai/v11/network/generic-vnfs/generic-vnf + tca.aai.node_query_path: aai/v11/search/nodes-query + tca.aai.password: + get_input: tca.aai.password + tca.aai.url: + get_input: tca.aai.url + tca.aai.username: + get_input: tca.aai.username + tca.policy: '{"domain":"measurementsForVfScaling","metricsPerEventName":[{"eventName":"vFirewallBroadcastPackets","controlLoopSchemaType":"VM","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"LESS_OR_EQUAL","severity":"MAJOR","closedLoopEventStatus":"ONSET"},{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":700,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"vLoadBalancer","controlLoopSchemaType":"VM","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"Measurement_vGMUX","controlLoopSchemaType":"VNF","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"EQUAL","severity":"MAJOR","closedLoopEventStatus":"ABATED"},{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"GREATER","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]}]}' + tca.processing_batch_size: 10000 + tca.enable_abatement: true + tca.enable_ecomp_logging: true + docker_config: + healthcheck: + endpoint: /actuator/health + interval: 30s + timeout: 10s + type: http + image: + get_input: tag_version + log_info: + log_directory: + get_input: log_directory + tls_info: + use_tls: true + cert_directory: '/etc/tca-gen2/ssl' + replicas: + get_input: replicas + service_component_type: { get_input: service_name } + tcagen2_policy: + type: clamp.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: + get_input: policy_model_id diff --git a/src/test/resources/example/sdc/blueprint-dcae/tca.yaml b/src/test/resources/example/sdc/blueprint-dcae/tca.yaml new file mode 100644 index 000000000..0cb9cdb68 --- /dev/null +++ b/src/test/resources/example/sdc/blueprint-dcae/tca.yaml @@ -0,0 +1,105 @@ +tosca_definitions_version: cloudify_dsl_1_3 +imports: +- http://www.getcloudify.org/spec/cloudify/3.4/types.yaml +- https://onap.org:8443/repository/solutioning01-mte2-raw/type_files/docker/2.2.0/node-type.yaml +- https://onap.org:8443/repository/solutioning01-mte2-raw/type_files/relationship/1.0.0/node-type.yaml +- http://onap.org:8081/repository/solutioning01-mte2-raw/type_files/dmaap/dmaap_mr.yaml +inputs: + location_id: + type: string + service_id: + type: string + policy_id: + type: string +node_templates: + policy_0: + type: dcae.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: "onap.policies.monitoring.cdap.tca.hi.lo.app" + cdap_host_host: + type: dcae.nodes.StreamingAnalytics.SelectedCDAPInfrastructure + properties: + location_id: + get_input: location_id + scn_override: cdap_broker.solutioning-central.dcae.onap.org + interfaces: + cloudify.interfaces.lifecycle: { + } + tca_tca: + type: dcae.nodes.MicroService.cdap + properties: + app_config: + appDescription: DCAE Analytics Threshold Crossing Alert Application + appName: dcae-tca + tcaSubscriberOutputStreamName: TCASubscriberOutputStream + tcaVESAlertsTableName: TCAVESAlertsTable + tcaVESAlertsTableTTLSeconds: '1728000' + tcaVESMessageStatusTableName: TCAVESMessageStatusTable + tcaVESMessageStatusTableTTLSeconds: '86400' + thresholdCalculatorFlowletInstances: '2' + app_preferences: + publisherContentType: application/json + publisherHostName: mrlocal-mtnjftle01.onap.org + publisherHostPort: '3905' + publisherMaxBatchSize: '10' + publisherMaxRecoveryQueueSize: '100000' + publisherPollingInterval: '20000' + publisherProtocol: https + publisherTopicName: org.onap.dcae.dmaap.mtnje2.DcaeTestVESPub + publisherUserName: test@tca.af.dcae.onap.org + publisherUserPassword: password + subscriberConsumerGroup: OpenDCAE-c12 + subscriberConsumerId: c12 + subscriberContentType: application/json + subscriberHostName: mrlocal-mtnjftle01.onap.org + subscriberHostPort: '3905' + subscriberMessageLimit: '-1' + subscriberPollingInterval: '20000' + subscriberProtocol: https + subscriberTimeoutMS: '-1' + subscriberTopicName: org.onap.dcae.dmaap.mtnje2.DcaeTestVESSub + subscriberUserName: test@tca.af.dcae.onap.org + subscriberUserPassword: password + tca_policy: null + artifact_name: dcae-analytics-tca + artifact_version: 1.0.0 + connections: + streams_publishes: [ + ] + streams_subscribes: [ + ] + jar_url: http://somejar + location_id: + get_input: location_id + namespace: cdap_tca_hi_lo + programs: + - program_id: TCAVESCollectorFlow + program_type: flows + - program_id: TCADMaaPMRSubscriberWorker + program_type: workers + - program_id: TCADMaaPMRPublisherWorker + program_type: workers + service_component_type: cdap_app_tca + service_id: + get_input: service_id + streamname: TCASubscriberOutputStream + relationships: + - target: topic0 + type: dcae.relationships.subscribe_to_events + - target: topic1 + type: dcae.relationships.publish_events + - target: cdap_host_host + type: dcae.relationships.component_contained_in + - target: policy_0 + type: dcae.relationships.depends_on + topic0: + type: dcae.nodes.Topic + properties: + topic_name: '' + topic1: + type: dcae.nodes.Topic + properties: + topic_name: '' + diff --git a/src/test/resources/example/sdc/blueprint-dcae/tca_2.yaml b/src/test/resources/example/sdc/blueprint-dcae/tca_2.yaml new file mode 100644 index 000000000..00ebfe7fe --- /dev/null +++ b/src/test/resources/example/sdc/blueprint-dcae/tca_2.yaml @@ -0,0 +1,174 @@ +# +# ============LICENSE_START==================================================== +# ============================================================================= +# 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====================================================== + +tosca_definitions_version: cloudify_dsl_1_3 + +description: > + This blueprint deploys/manages the TCA module as a Docker container + +imports: + - http://www.getcloudify.org/spec/cloudify/3.4/types.yaml + - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.12/k8splugin_types.yaml +# - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/dcaepolicyplugin/2.3.0/dcaepolicyplugin_types.yaml + - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/clamppolicyplugin/1.0.0/clamppolicyplugin_types.yaml +inputs: + aaiEnrichmentHost: + type: string + default: "aai.onap.svc.cluster.local" + aaiEnrichmentPort: + type: string + default: "8443" + enableAAIEnrichment: + type: string + default: true + dmaap_host: + type: string + default: message-router.onap + dmaap_port: + type: string + default: "3904" + enableRedisCaching: + type: string + default: false + redisHosts: + type: string + default: dcae-redis.onap.svc.cluster.local:6379 + tag_version: + type: string + default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.1" + consul_host: + type: string + default: consul-server.onap + consul_port: + type: string + default: "8500" + cbs_host: + type: string + default: "config-binding-servicel" + cbs_port: + type: string + default: "10000" + policy_id: + type: string + default: "onap.restart.tca" + external_port: + type: string + description: Kubernetes node port on which CDAPgui is exposed + default: "32012" + policy_model_id: + type: string + default: "onap.policies.monitoring.cdap.tca.hi.lo.app" +node_templates: + tca_k8s: + type: dcae.nodes.ContainerizedServiceComponent + relationships: + - target: tca_policy + type: cloudify.relationships.depends_on + properties: + service_component_type: 'dcaegen2-analytics-tca' + application_config: {} + docker_config: {} + image: + get_input: tag_version + log_info: + log_directory: "/opt/app/TCAnalytics/logs" + application_config: + app_config: + appDescription: DCAE Analytics Threshold Crossing Alert Application + appName: dcae-tca + tcaAlertsAbatementTableName: TCAAlertsAbatementTable + tcaAlertsAbatementTableTTLSeconds: '1728000' + tcaSubscriberOutputStreamName: TCASubscriberOutputStream + tcaVESAlertsTableName: TCAVESAlertsTable + tcaVESAlertsTableTTLSeconds: '1728000' + tcaVESMessageStatusTableName: TCAVESMessageStatusTable + tcaVESMessageStatusTableTTLSeconds: '86400' + thresholdCalculatorFlowletInstances: '2' + app_preferences: + aaiEnrichmentHost: + get_input: aaiEnrichmentHost + aaiEnrichmentIgnoreSSLCertificateErrors: 'true' + aaiEnrichmentPortNumber: '8443' + aaiEnrichmentProtocol: https + aaiEnrichmentUserName: dcae@dcae.onap.org + aaiEnrichmentUserPassword: demo123456! + aaiVMEnrichmentAPIPath: /aai/v11/search/nodes-query + aaiVNFEnrichmentAPIPath: /aai/v11/network/generic-vnfs/generic-vnf + enableAAIEnrichment: + get_input: enableAAIEnrichment + enableRedisCaching: + get_input: enableRedisCaching + redisHosts: + get_input: redisHosts + enableAlertCEFFormat: 'false' + publisherContentType: application/json + publisherHostName: + get_input: dmaap_host + publisherHostPort: + get_input: dmaap_port + publisherMaxBatchSize: '1' + publisherMaxRecoveryQueueSize: '100000' + publisherPollingInterval: '20000' + publisherProtocol: http + publisherTopicName: unauthenticated.DCAE_CL_OUTPUT + subscriberConsumerGroup: OpenDCAE-clamp + subscriberConsumerId: c12 + subscriberContentType: application/json + subscriberHostName: + get_input: dmaap_host + subscriberHostPort: + get_input: dmaap_port + subscriberMessageLimit: '-1' + subscriberPollingInterval: '30000' + subscriberProtocol: http + subscriberTimeoutMS: '-1' + subscriberTopicName: unauthenticated.VES_MEASUREMENT_OUTPUT +# tca_policy: '{"domain":"measurementsForVfScaling","metricsPerEventName":[{"eventName":"vFirewallBroadcastPackets","controlLoopSchemaType":"VNF","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"LESS_OR_EQUAL","severity":"MAJOR","closedLoopEventStatus":"ONSET"},{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":700,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"vLoadBalancer","controlLoopSchemaType":"VM","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"Measurement_vGMUX","controlLoopSchemaType":"VNF","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"EQUAL","severity":"MAJOR","closedLoopEventStatus":"ABATED"},{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"GREATER","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]}]}' + service_component_type: dcaegen2-analytics_tca + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + DMAAPHOST: + { get_input: dmaap_host } + DMAAPPORT: + { get_input: dmaap_port } + DMAAPPUBTOPIC: "unauthenticated.DCAE_CL_OUTPUT" + DMAAPSUBTOPIC: "unauthenticated.VES_MEASUREMENT_OUTPUT" + AAIHOST: + { get_input: aaiEnrichmentHost } + AAIPORT: + { get_input: aaiEnrichmentPort } + CONSUL_HOST: + { get_input: consul_host } + CONSUL_PORT: + { get_input: consul_port } + CBS_HOST: + { get_input: cbs_host } + CBS_PORT: + { get_input: cbs_port } + CONFIG_BINDING_SERVICE: "config_binding_service" + ports: + - concat: ["11011:", { get_input: external_port }] + tca_policy: + type: clamp.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: "onap.policies.monitoring.cdap.tca.hi.lo.app" diff --git a/src/test/resources/example/sdc/blueprint-dcae/tca_3.yaml b/src/test/resources/example/sdc/blueprint-dcae/tca_3.yaml new file mode 100644 index 000000000..929f36367 --- /dev/null +++ b/src/test/resources/example/sdc/blueprint-dcae/tca_3.yaml @@ -0,0 +1,171 @@ +# +# ============LICENSE_START==================================================== +# ============================================================================= +# 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====================================================== + +tosca_definitions_version: cloudify_dsl_1_3 + +description: > + This blueprint deploys/manages the TCA module as a Docker container + +imports: + - https://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml + - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R6/k8splugin/1.7.2/k8splugin_types.yaml" + - "https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R6/clamppolicyplugin/1.1.0/clamppolicyplugin_types.yaml" +inputs: + aaiEnrichmentHost: + type: string + default: "aai.onap.svc.cluster.local" + aaiEnrichmentPort: + type: string + default: "8443" + enableAAIEnrichment: + type: string + default: "true" + dmaap_host: + type: string + default: "message-router.onap.svc.cluster.local" + dmaap_port: + type: string + default: "3904" + enableRedisCaching: + type: string + default: "false" + redisHosts: + type: string + default: "dcae-redis.onap.svc.cluster.local:6379" + tag_version: + type: string + default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.2.2" + consul_host: + type: string + default: "consul-server.onap" + consul_port: + type: string + default: "8500" + cbs_host: + type: string + default: "config-binding-service" + cbs_port: + type: string + default: "10000" + policy_id: + type: string + default: "onap.restart.tca" + external_port: + type: string + description: Kubernetes node port on which CDAPgui is exposed + default: "32012" + policy_model_id: + type: string + default: "onap.policies.monitoring.cdap.tca.hi.lo.app" +node_templates: + tca_k8s: + type: dcae.nodes.ContainerizedServiceComponent + relationships: + - target: tca_policy + type: cloudify.relationships.depends_on + properties: + service_component_type: 'dcaegen2-analytics-tca' + application_config: {} + docker_config: {} + image: + get_input: tag_version + log_info: + log_directory: "/opt/app/TCAnalytics/logs" + application_config: + app_config: + appDescription: DCAE Analytics Threshold Crossing Alert Application + appName: dcae-tca + tcaAlertsAbatementTableName: TCAAlertsAbatementTable + tcaAlertsAbatementTableTTLSeconds: '1728000' + tcaSubscriberOutputStreamName: TCASubscriberOutputStream + tcaVESAlertsTableName: TCAVESAlertsTable + tcaVESAlertsTableTTLSeconds: '1728000' + tcaVESMessageStatusTableName: TCAVESMessageStatusTable + tcaVESMessageStatusTableTTLSeconds: '86400' + thresholdCalculatorFlowletInstances: '2' + app_preferences: + aaiEnrichmentHost: + get_input: aaiEnrichmentHost + aaiEnrichmentIgnoreSSLCertificateErrors: 'true' + aaiEnrichmentPortNumber: '8443' + aaiEnrichmentProtocol: https + aaiEnrichmentUserName: dcae@dcae.onap.org + aaiEnrichmentUserPassword: demo123456! + aaiVMEnrichmentAPIPath: /aai/v11/search/nodes-query + aaiVNFEnrichmentAPIPath: /aai/v11/network/generic-vnfs/generic-vnf + enableAAIEnrichment: + get_input: enableAAIEnrichment + enableRedisCaching: + get_input: enableRedisCaching + redisHosts: + get_input: redisHosts + enableAlertCEFFormat: 'false' + publisherContentType: application/json + publisherHostName: + get_input: dmaap_host + publisherHostPort: + get_input: dmaap_port + publisherMaxBatchSize: '1' + publisherMaxRecoveryQueueSize: '100000' + publisherPollingInterval: '20000' + publisherProtocol: http + publisherTopicName: unauthenticated.DCAE_CL_OUTPUT + subscriberConsumerGroup: OpenDCAE-clamp + subscriberConsumerId: c12 + subscriberContentType: application/json + subscriberHostName: + get_input: dmaap_host + subscriberHostPort: + get_input: dmaap_port + subscriberMessageLimit: '-1' + subscriberPollingInterval: '30000' + subscriberProtocol: http + subscriberTimeoutMS: '-1' + subscriberTopicName: unauthenticated.VES_MEASUREMENT_OUTPUT + #tca_policy: '{"domain":"measurementsForVfScaling","metricsPerEventName":[{"eventName":"vFirewallBroadcastPackets","controlLoopSchemaType":"VM","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"LESS_OR_EQUAL","severity":"MAJOR","closedLoopEventStatus":"ONSET"},{"closedLoopControlName":"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":700,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"vLoadBalancer","controlLoopSchemaType":"VM","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta","thresholdValue":300,"direction":"GREATER_OR_EQUAL","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]},{"eventName":"Measurement_vGMUX","controlLoopSchemaType":"VNF","policyScope":"DCAE","policyName":"DCAE.Config_tca-hi-lo","policyVersion":"v0.0.1","thresholds":[{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"EQUAL","severity":"MAJOR","closedLoopEventStatus":"ABATED"},{"closedLoopControlName":"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e","version":"1.0.2","fieldPath":"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value","thresholdValue":0,"direction":"GREATER","severity":"CRITICAL","closedLoopEventStatus":"ONSET"}]}]}' + tca_policy: '' + service_component_type: dcaegen2-analytics_tca + interfaces: + cloudify.interfaces.lifecycle: + start: + inputs: + envs: + DMAAPHOST: + { get_input: dmaap_host } + DMAAPPORT: "3904" + DMAAPPUBTOPIC: "unauthenticated.DCAE_CL_OUTPUT" + DMAAPSUBTOPIC: "unauthenticated.VES_MEASUREMENT_OUTPUT" + AAIHOST: + { get_input: aaiEnrichmentHost } + AAIPORT: "8443" + CONSUL_HOST: + { get_input: consul_host } + CONSUL_PORT: "8500" + CBS_HOST: + { get_input: cbs_host } + CBS_PORT: "10000" + CONFIG_BINDING_SERVICE: "config_binding_service" + ports: + - concat: ["11011:", { get_input: external_port }] + tca_policy: + type: clamp.nodes.policy + properties: + policy_id: + get_input: policy_id + policy_model_id: + get_input: policy_model_id diff --git a/src/test/resources/example/sdc/expected-result/deployment-parameters-multi-blueprints.json b/src/test/resources/example/sdc/expected-result/deployment-parameters-multi-blueprints.json new file mode 100644 index 000000000..58f4cf3b2 --- /dev/null +++ b/src/test/resources/example/sdc/expected-result/deployment-parameters-multi-blueprints.json @@ -0,0 +1,43 @@ +{ + "dcaeDeployParameters": { + "testName1": { + "location_id": "", + "service_id": "", + "policy_id": "testName1" + }, + "testName2": { + "aaiEnrichmentHost": "aai.onap.svc.cluster.local", + "aaiEnrichmentPort": "8443", + "enableAAIEnrichment": true, + "dmaap_host": "message-router.onap", + "dmaap_port": "3904", + "enableRedisCaching": false, + "redisHosts": "dcae-redis.onap.svc.cluster.local:6379", + "tag_version": "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.1", + "consul_host": "consul-server.onap", + "consul_port": "8500", + "cbs_host": "config-binding-servicel", + "cbs_port": "10000", + "external_port": "32012", + "policy_model_id": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "policy_id": "testName2" + }, + "testName3": { + "aaiEnrichmentHost": "aai.onap.svc.cluster.local", + "aaiEnrichmentPort": "8443", + "enableAAIEnrichment": "true", + "dmaap_host": "message-router.onap.svc.cluster.local", + "dmaap_port": "3904", + "enableRedisCaching": "false", + "redisHosts": "dcae-redis.onap.svc.cluster.local:6379", + "tag_version": "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.2.2", + "consul_host": "consul-server.onap", + "consul_port": "8500", + "cbs_host": "config-binding-service", + "cbs_port": "10000", + "external_port": "32012", + "policy_model_id": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "policy_id": "testName3" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/sdc/expected-result/deployment-parameters-single-blueprint.json b/src/test/resources/example/sdc/expected-result/deployment-parameters-single-blueprint.json new file mode 100644 index 000000000..7140a4748 --- /dev/null +++ b/src/test/resources/example/sdc/expected-result/deployment-parameters-single-blueprint.json @@ -0,0 +1,9 @@ +{ + "dcaeDeployParameters": { + "uniqueBlueprintParameters": { + "location_id": "", + "service_id": "", + "policy_id": "testName1" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/example/sdc/expected-result/policy-data.yaml b/src/test/resources/example/sdc/expected-result/policy-data.yaml new file mode 100644 index 000000000..3cf5e975c --- /dev/null +++ b/src/test/resources/example/sdc/expected-result/policy-data.yaml @@ -0,0 +1,2859 @@ +# +# 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. +# +tosca_definitions_version: tosca_simple_yaml_1_1 +imports: +- data.yml +policy_types: + tosca.policies.Root: + description: The TOSCA Policy Type all other TOSCA Policy Types derive from + tosca.policies.Placement: + derived_from: tosca.policies.Root + description: The TOSCA Policy Type definition that is used to govern placement of TOSCA nodes or groups of nodes. + tosca.policies.Scaling: + derived_from: tosca.policies.Root + description: The TOSCA Policy Type definition that is used to govern scaling of TOSCA nodes or groups of nodes. + tosca.policies.Update: + derived_from: tosca.policies.Root + description: The TOSCA Policy Type definition that is used to govern update of TOSCA nodes or groups of nodes. + tosca.policies.Performance: + derived_from: tosca.policies.Root + description: The TOSCA Policy Type definition that is used to declare performance requirements for TOSCA nodes or groups of nodes. + org.openecomp.policies.placement.Antilocate: + derived_from: tosca.policies.Placement + description: My placement policy for separation based upon container type value + properties: + name: + type: string + description: The name of the policy + required: false + status: SUPPORTED + container_type: + type: string + description: container type + required: false + status: SUPPORTED + constraints: + - valid_values: + - host + - region + - compute + org.openecomp.policies.placement.Colocate: + derived_from: tosca.policies.Placement + description: Keep associated nodes (groups of nodes) based upon affinity value + properties: + name: + type: string + description: The name of the policy + required: false + status: SUPPORTED + affinity: + type: string + description: affinity + required: true + status: SUPPORTED + constraints: + - valid_values: + - host + - region + - compute + org.openecomp.policies.placement.valet.Diversity: + derived_from: tosca.policies.Placement + description: Valet Diversity + properties: + level: + type: string + description: diversity + required: false + default: host + status: SUPPORTED + constraints: + - valid_values: + - host + - rack + org.openecomp.policies.placement.valet.Exclusivity: + derived_from: tosca.policies.Placement + description: Valet Exclusivity + properties: + level: + type: string + description: exclusivity + required: false + default: host + status: SUPPORTED + constraints: + - valid_values: + - host + - rack + org.openecomp.policies.placement.valet.Affinity: + derived_from: tosca.policies.Placement + description: Valet Affinity + properties: + level: + type: string + description: affinity + required: false + default: host + status: SUPPORTED + constraints: + - valid_values: + - host + - rack + org.openecomp.policies.scaling.Fixed: + derived_from: tosca.policies.Scaling + properties: + quantity: + description: the exact number of instances to keep up + type: integer + required: true + org.openecomp.policies.External: + derived_from: tosca.policies.Root + description: externally managed policy (for example, type="network assignment", source="Policy Manager", name="route target") + properties: + source: + type: string + description: The name of the server that exposes the policy with predefined type and name. + required: false + type: + type: string + description: The type (category) of the policy same as it is defined in the source. + required: false + name: + type: string + description: The name of the policy, that related to specific type, same as it is defined in the source. + required: false + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: A base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: map + description: TCA Policy JSON + entry_schema: + type: onap.datatypes.monitoring.tca_policy + tosca.policies.nfv.InstantiationLevels: + derived_from: tosca.policies.Root + description: The InstantiationLevels type is a policy type representing all the instantiation levels of resources to be instantiated within a deployment flavour and including default instantiation level in term of the number of VNFC instances to be created as defined in ETSI GS NFV-IFA 011 [1]. + properties: + levels: + type: map + description: Describes the various levels of resources that can be used to instantiate the VNF using this flavour. + required: true + entry_schema: + type: tosca.datatypes.nfv.InstantiationLevel + default_level: + type: string + description: The default instantiation level for this flavour. + required: false + tosca.policies.nfv.VduInstantiationLevels: + derived_from: tosca.policies.Root + description: The VduInstantiationLevels type is a policy type representing all the instantiation levels of resources to be instantiated within a deployment flavour in term of the number of VNFC instances to be created from each vdu.Compute. as defined in ETSI GS NFV-IFA 011 [1] + properties: + levels: + type: map + description: Describes the Vdu.Compute levels of resources that can be used to instantiate the VNF using this flavour + required: true + entry_schema: + type: tosca.datatypes.nfv.VduLevel + targets: + - tosca.nodes.nfv.Vdu.Compute + tosca.policies.nfv.VirtualLinkInstantiationLevels: + derived_from: tosca.policies.Root + description: The VirtualLinkInstantiationLevels type is a policy type representing all the instantiation levels of virtual link resources to be instantiated within a deployment flavour as defined in ETSI GS NFV-IFA 011 [1]. + properties: + levels: + type: map + description: Describes the virtual link levels of resources that can be used to instantiate the VNF using this flavour. + required: true + entry_schema: + type: tosca.datatypes.nfv.VirtualLinkBitrateLevel + targets: + - tosca.nodes.nfv.VnfVirtualLink + tosca.policies.nfv.ScalingAspects: + derived_from: tosca.policies.Root + description: The ScalingAspects type is a policy type representing the scaling aspects used for horizontal scaling as defined in ETSI GS NFV-IFA 011 [1]. + properties: + aspects: + type: map + description: Describe maximum scale level for total number of scaling steps that can be applied to a particular aspect + required: true + entry_schema: + type: tosca.datatypes.nfv.ScalingAspect + tosca.policies.nfv.VduScalingAspectDeltas: + derived_from: tosca.policies.Root + description: The VduScalingAspectDeltas type is a policy type representing the Vdu.Compute detail of an aspect deltas used for horizontal scaling, as defined in ETSI GS NFV-IFA 011 [1]. + properties: + aspect: + type: string + description: Represents the scaling aspect to which this policy applies + required: true + deltas: + type: map + description: Describes the Vdu.Compute scaling deltas to be applied for every scaling steps of a particular aspect. + required: true + entry_schema: + type: tosca.datatypes.nfv.VduLevel + targets: + - tosca.nodes.nfv.Vdu.Compute + tosca.policies.nfv.VirtualLinkBitrateScalingAspectDeltas: + derived_from: tosca.policies.Root + description: The VirtualLinkBitrateScalingAspectDeltas type is a policy type representing the VnfVirtualLink detail of an aspect deltas used for horizontal scaling, as defined in ETSI GS NFV-IFA 011 [1]. + properties: + aspect: + type: string + description: Represents the scaling aspect to which this policy applies. + required: true + deltas: + type: map + description: Describes the VnfVirtualLink scaling deltas to be applied for every scaling steps of a particular aspect. + required: true + entry_schema: + type: tosca.datatypes.nfv.VirtualLinkBitrateLevel + targets: + - tosca.nodes.nfv.VnfVirtualLink + tosca.policies.nfv.VduInitialDelta: + derived_from: tosca.policies.Root + description: The VduInitialDelta type is a policy type representing the Vdu.Compute detail of an initial delta used for horizontal scaling, as defined in ETSI GS NFV-IFA 011 [1]. + properties: + initial_delta: + type: tosca.datatypes.nfv.VduLevel + description: Represents the initial minimum size of the VNF. + required: true + targets: + - tosca.nodes.nfv.Vdu.Compute + tosca.policies.nfv.VirtualLinkBitrateInitialDelta: + derived_from: tosca.policies.Root + description: The VirtualLinkBitrateInitialDelta type is a policy type representing the VnfVirtualLink detail of an initial deltas used for horizontal scaling, as defined in ETSI GS NFV-IFA 011 [1]. + properties: + initial_delta: + type: tosca.datatypes.nfv.VirtualLinkBitrateLevel + description: Represents the initial minimum size of the VNF. + required: true + targets: + - tosca.nodes.nfv.VnfVirtualLink + tosca.policies.nfv.SecurityGroupRule: + derived_from: tosca.policies.Root + description: The SecurityGroupRule type is a policy type specified the matching criteria for the ingress and/or egress traffic to/from visited connection points as defined in ETSI GS NFV-IFA 011 [1]. + properties: + description: + type: string + description: Human readable description of the security group rule. + required: false + direction: + type: string + description: The direction in which the security group rule is applied. The direction of 'ingress' or 'egress' is specified against the associated CP. I.e., 'ingress' means the packets entering a CP, while 'egress' means the packets sent out of a CP. + required: false + constraints: + - valid_values: + - ingress + - egress + default: ingress + ether_type: + type: string + description: Indicates the protocol carried over the Ethernet layer. + required: false + constraints: + - valid_values: + - ipv4 + - ipv6 + default: ipv4 + protocol: + type: string + description: Indicates the protocol carried over the IP layer. Permitted values include any protocol defined in the IANA protocol registry, e.g. TCP, UDP, ICMP, etc. + required: false + constraints: + - valid_values: + - hopopt + - icmp + - igmp + - ggp + - ipv4 + - st + - tcp + - cbt + - egp + - igp + - bbn_rcc_mon + - nvp_ii + - pup + - argus + - emcon + - xnet + - chaos + - udp + - mux + - dcn_meas + - hmp + - prm + - xns_idp + - trunk_1 + - trunk_2 + - leaf_1 + - leaf_2 + - rdp + - irtp + - iso_tp4 + - netblt + - mfe_nsp + - merit_inp + - dccp + - 3pc + - idpr + - xtp + - ddp + - idpr_cmtp + - tp++ + - il + - ipv6 + - sdrp + - ipv6_route + - ipv6_frag + - idrp + - rsvp + - gre + - dsr + - bna + - esp + - ah + - i_nlsp + - swipe + - narp + - mobile + - tlsp + - skip + - ipv6_icmp + - ipv6_no_nxt + - ipv6_opts + - cftp + - sat_expak + - kryptolan + - rvd + - ippc + - sat_mon + - visa + - ipcv + - cpnx + - cphb + - wsn + - pvp + - br_sat_mon + - sun_nd + - wb_mon + - wb_expak + - iso_ip + - vmtp + - secure_vmtp + - vines + - ttp + - iptm + - nsfnet_igp + - dgp + - tcf + - eigrp + - ospfigp + - sprite_rpc + - larp + - mtp + - ax.25 + - ipip + - micp + - scc_sp + - etherip + - encap + - gmtp + - ifmp + - pnni + - pim + - aris + - scps + - qnx + - a/n + - ip_comp + - snp + - compaq_peer + - ipx_in_ip + - vrrp + - pgm + - l2tp + - ddx + - iatp + - stp + - srp + - uti + - smp + - sm + - ptp + - isis + - fire + - crtp + - crudp + - sscopmce + - iplt + - sps + - pipe + - sctp + - fc + - rsvp_e2e_ignore + - mobility + - udp_lite + - mpls_in_ip + - manet + - hip + - shim6 + - wesp + - rohc + default: tcp + port_range_min: + type: integer + description: Indicates minimum port number in the range that is matched by the security group rule. If a value is provided at design-time, this value may be overridden at run-time based on other deployment requirements or constraints. + required: false + constraints: + - greater_or_equal: 0 + - less_or_equal: 65535 + default: 0 + port_range_max: + type: integer + description: Indicates maximum port number in the range that is matched by the security group rule. If a value is provided at design-time, this value may be overridden at run-time based on other deployment requirements or constraints. + required: false + constraints: + - greater_or_equal: 0 + - less_or_equal: 65535 + default: 65535 + targets: + - tosca.nodes.nfv.VduCp + - tosca.nodes.nfv.VnfExtCp + tosca.policies.nfv.SupportedVnfInterface: + derived_from: tosca.policies.Root + description: this policy type represents interfaces produced by a VNF, the details to access them and the applicable connection points to use to access these interfaces + properties: + interface_name: + type: string + description: Identifies an interface produced by the VNF. + required: true + constraints: + - valid_values: + - vnf_indicator + - vnf_configuration + details: + type: tosca.datatypes.nfv.InterfaceDetails + description: Provide additional data to access the interface endpoint + required: false + targets: + - tosca.nodes.nfv.VnfExtCp + - tosca.nodes.nfv.VduCp +data_types: + tosca.datatypes.Root: + description: The TOSCA root Data Type all other TOSCA base Data Types derive from + integer: + derived_from: tosca.datatypes.Root + string: + derived_from: tosca.datatypes.Root + boolean: + derived_from: tosca.datatypes.Root + float: + derived_from: tosca.datatypes.Root + list: + derived_from: tosca.datatypes.Root + map: + derived_from: tosca.datatypes.Root + json: + derived_from: tosca.datatypes.Root + scalar-unit: + derived_from: tosca.datatypes.Root + scalar-unit.size: + derived_from: scalar-unit + scalar-unit.time: + derived_from: scalar-unit + scalar-unit.frequency: + derived_from: scalar-unit + tosca.datatypes.Credential: + derived_from: tosca.datatypes.Root + properties: + protocol: + type: string + required: false + token_type: + type: string + default: password + token: + type: string + keys: + type: map + required: false + entry_schema: + type: string + user: + type: string + required: false + org.openecomp.datatypes.PortMirroringConnectionPointDescription: + derived_from: tosca.datatypes.Root + properties: + nf_naming_code: + type: string + nfc_naming_code: + type: string + network_role: + type: string + pps_capacity: + type: string + nf_type: + type: string + description: deprecated + nfc_type: + type: string + description: deprecated + tosca.datatypes.TimeInterval: + derived_from: tosca.datatypes.Root + properties: + start_time: + type: timestamp + required: true + end_time: + type: timestamp + required: true + tosca.datatypes.network.NetworkInfo: + derived_from: tosca.datatypes.Root + properties: + network_name: + type: string + network_id: + type: string + addresses: + type: list + entry_schema: + type: string + tosca.datatypes.network.PortInfo: + derived_from: tosca.datatypes.Root + properties: + port_name: + type: string + port_id: + type: string + network_id: + type: string + mac_address: + type: string + addresses: + type: list + entry_schema: + type: string + tosca.datatypes.network.PortDef: + derived_from: integer + constraints: + - in_range: + - 1 + - 65535 + tosca.datatypes.network.PortSpec: + derived_from: tosca.datatypes.Root + properties: + protocol: + type: string + required: true + default: tcp + constraints: + - valid_values: + - udp + - tcp + - igmp + target: + type: tosca.datatypes.network.PortDef + target_range: + type: range + constraints: + - in_range: + - 1 + - 65535 + source: + type: tosca.datatypes.network.PortDef + source_range: + type: range + constraints: + - in_range: + - 1 + - 65535 + org.openecomp.datatypes.heat.network.AddressPair: + derived_from: tosca.datatypes.Root + description: MAC/IP address pairs + properties: + mac_address: + type: string + description: MAC address + required: false + status: SUPPORTED + ip_address: + type: string + description: IP address + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.subnet.HostRoute: + derived_from: tosca.datatypes.Root + description: Host route info for the subnet + properties: + destination: + type: string + description: The destination for static route + required: false + status: SUPPORTED + nexthop: + type: string + description: The next hop for the destination + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.AllocationPool: + derived_from: tosca.datatypes.Root + description: The start and end addresses for the allocation pool + properties: + start: + type: string + description: Start address for the allocation pool + required: false + status: SUPPORTED + end: + type: string + description: End address for the allocation pool + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.neutron.Subnet: + derived_from: tosca.datatypes.Root + description: A subnet represents an IP address block that can be used for assigning IP addresses to virtual instances + properties: + tenant_id: + type: string + description: The ID of the tenant who owns the network + required: false + status: SUPPORTED + enable_dhcp: + type: boolean + description: Set to true if DHCP is enabled and false if DHCP is disabled + required: false + default: true + status: SUPPORTED + ipv6_address_mode: + type: string + description: IPv6 address mode + required: false + status: SUPPORTED + constraints: + - valid_values: + - dhcpv6-stateful + - dhcpv6-stateless + - slaac + ipv6_ra_mode: + type: string + description: IPv6 RA (Router Advertisement) mode + required: false + status: SUPPORTED + constraints: + - valid_values: + - dhcpv6-stateful + - dhcpv6-stateless + - slaac + value_specs: + type: map + description: Extra parameters to include in the request + required: false + default: {} + status: SUPPORTED + entry_schema: + type: string + allocation_pools: + type: list + description: The start and end addresses for the allocation pools + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.network.AllocationPool + subnetpool: + type: string + description: The name or ID of the subnet pool + required: false + status: SUPPORTED + dns_nameservers: + type: list + description: A specified set of DNS name servers to be used + required: false + default: [] + status: SUPPORTED + entry_schema: + type: string + host_routes: + type: list + description: The gateway IP address + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.network.subnet.HostRoute + ip_version: + type: integer + description: The gateway IP address + required: false + default: 4 + status: SUPPORTED + constraints: + - valid_values: + - '4' + - '6' + name: + type: string + description: The name of the subnet + required: false + status: SUPPORTED + prefixlen: + type: integer + description: Prefix length for subnet allocation from subnet pool + required: false + status: SUPPORTED + constraints: + - greater_or_equal: 0 + cidr: + type: string + description: The CIDR + required: false + status: SUPPORTED + gateway_ip: + type: string + description: The gateway IP address + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.novaServer.network.PortExtraProperties: + derived_from: tosca.datatypes.Root + description: Nova server network expand properties for port + properties: + port_security_enabled: + type: boolean + description: Flag to enable/disable port security on the port + required: false + status: SUPPORTED + mac_address: + type: string + description: MAC address to give to this port + required: false + status: SUPPORTED + admin_state_up: + type: boolean + description: The administrative state of this port + required: false + default: true + status: SUPPORTED + qos_policy: + type: string + description: The name or ID of QoS policy to attach to this port + required: false + status: SUPPORTED + allowed_address_pairs: + type: list + description: Additional MAC/IP address pairs allowed to pass through the port + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.network.AddressPair + binding:vnic_type: + type: string + description: The vnic type to be bound on the neutron port + required: false + status: SUPPORTED + constraints: + - valid_values: + - macvtap + - direct + - normal + value_specs: + type: map + description: Extra parameters to include in the request + required: false + default: {} + status: SUPPORTED + entry_schema: + type: string + org.openecomp.datatypes.heat.novaServer.network.AddressInfo: + derived_from: tosca.datatypes.network.NetworkInfo + description: Network addresses with corresponding port id + properties: + port_id: + type: string + description: Port id + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.neutron.port.FixedIps: + derived_from: tosca.datatypes.Root + description: subnet/ip_address + properties: + subnet: + type: string + description: Subnet in which to allocate the IP address for this port + required: false + status: SUPPORTED + ip_address: + type: string + description: IP address desired in the subnet for this port + required: false + status: SUPPORTED + subnet_id: + type: string + description: Subnet in which to allocate the IP address for this port + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.FileInfo: + derived_from: tosca.datatypes.Root + description: Heat File Info + properties: + file: + type: string + description: The required URI string (relative or absolute) which can be used to locate the file + required: true + status: SUPPORTED + file_type: + type: string + description: The type of the file + required: true + status: SUPPORTED + constraints: + - valid_values: + - base + - env + - volume + - network + org.openecomp.datatypes.heat.contrail.network.rule.PortPairs: + derived_from: tosca.datatypes.Root + description: source and destination port pairs + properties: + start_port: + type: string + description: Start port + required: false + status: SUPPORTED + end_port: + type: string + description: End port + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrail.network.rule.Rule: + derived_from: tosca.datatypes.Root + description: policy rule + properties: + src_ports: + type: list + description: Source ports + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrail.network.rule.PortPairs + protocol: + type: string + description: Protocol + required: false + status: SUPPORTED + dst_addresses: + type: list + description: Destination addresses + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrail.network.rule.VirtualNetwork + apply_service: + type: string + description: Service to apply + required: false + status: SUPPORTED + dst_ports: + type: list + description: Destination ports + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrail.network.rule.PortPairs + src_addresses: + type: list + description: Source addresses + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrail.network.rule.VirtualNetwork + direction: + type: string + description: Direction + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrail.network.rule.RuleList: + derived_from: tosca.datatypes.Root + description: list of policy rules + properties: + policy_rule: + type: list + description: Contrail network rule + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrail.network.rule.Rule + org.openecomp.datatypes.heat.contrail.network.rule.VirtualNetwork: + derived_from: tosca.datatypes.Root + description: source and destination addresses + properties: + virtual_network: + type: string + description: Virtual network + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.neutron.SecurityRules.Rule: + derived_from: tosca.datatypes.Root + description: Rules Pairs + properties: + remote_group_id: + type: string + description: The remote group ID to be associated with this security group rule + required: false + status: SUPPORTED + protocol: + type: string + description: The protocol that is matched by the security group rule + required: false + status: SUPPORTED + constraints: + - valid_values: + - tcp + - udp + - icmp + ethertype: + type: string + description: Ethertype of the traffic + required: false + default: IPv4 + status: SUPPORTED + constraints: + - valid_values: + - IPv4 + - IPv6 + port_range_max: + type: integer + description: 'The maximum port number in the range that is matched by the + security group rule. ' + required: false + status: SUPPORTED + constraints: + - in_range: + - 0 + - 65535 + remote_ip_prefix: + type: string + description: The remote IP prefix (CIDR) to be associated with this security group rule + required: false + status: SUPPORTED + remote_mode: + type: string + description: Whether to specify a remote group or a remote IP prefix + required: false + default: remote_ip_prefix + status: SUPPORTED + constraints: + - valid_values: + - remote_ip_prefix + - remote_group_id + direction: + type: string + description: The direction in which the security group rule is applied + required: false + default: ingress + status: SUPPORTED + constraints: + - valid_values: + - egress + - ingress + port_range_min: + type: integer + description: The minimum port number in the range that is matched by the security group rule. + required: false + status: SUPPORTED + constraints: + - in_range: + - 0 + - 65535 + org.openecomp.datatypes.heat.substitution.SubstitutionFiltering: + derived_from: tosca.datatypes.Root + description: Substitution Filter + properties: + substitute_service_template: + type: string + description: Substitute Service Template + required: true + status: SUPPORTED + index_value: + type: integer + description: Index value of the substitution service template runtime instance + required: false + default: 0 + status: SUPPORTED + constraints: + - greater_or_equal: 0 + count: + type: string + description: Count + required: false + default: 1 + status: SUPPORTED + scaling_enabled: + type: boolean + description: Indicates whether service scaling is enabled + required: false + default: true + status: SUPPORTED + mandatory: + type: boolean + description: Mandatory + required: false + default: true + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.RefDataSequence: + derived_from: tosca.datatypes.Root + description: network policy refs data sequence + properties: + network_policy_refs_data_sequence_major: + type: integer + description: Network Policy ref data sequence Major + required: false + status: SUPPORTED + network_policy_refs_data_sequence_minor: + type: integer + description: Network Policy ref data sequence Minor + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.RefData: + derived_from: tosca.datatypes.Root + description: network policy refs data + properties: + network_policy_refs_data_sequence: + type: org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.RefDataSequence + description: Network Policy ref data sequence + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.ref.data.IpamSubnet: + derived_from: tosca.datatypes.Root + description: Network Ipam Ref Data Subnet + properties: + network_ipam_refs_data_ipam_subnets_subnet_ip_prefix_len: + type: string + description: Network ipam refs data ipam subnets ip prefix len + required: false + status: SUPPORTED + network_ipam_refs_data_ipam_subnets_subnet_ip_prefix: + type: string + description: Network ipam refs data ipam subnets ip prefix + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.ref.data.IpamSubnetList: + derived_from: tosca.datatypes.Root + description: Network Ipam Ref Data Subnet List + properties: + network_ipam_refs_data_ipam_subnets_subnet: + type: org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.ref.data.IpamSubnet + description: Network ipam refs data ipam subnets + required: false + status: SUPPORTED + network_ipam_refs_data_ipam_subnets_addr_from_start: + type: string + description: Network ipam refs data ipam subnets addr from start + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.IpamRefData: + derived_from: tosca.datatypes.Root + description: Network Ipam Ref Data + properties: + network_ipam_refs_data_ipam_subnets: + type: list + description: Network ipam refs data ipam subnets + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.virtual.network.rule.ref.data.IpamSubnetList + org.openecomp.datatypes.heat.contrailV2.network.rule.SrcVirtualNetwork: + derived_from: tosca.datatypes.Root + description: source addresses + properties: + network_policy_entries_policy_rule_src_addresses_virtual_network: + type: string + description: Source addresses Virtual network + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.network.rule.DstVirtualNetwork: + derived_from: tosca.datatypes.Root + description: destination addresses + properties: + network_policy_entries_policy_rule_dst_addresses_virtual_network: + type: string + description: Destination addresses Virtual network + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.network.rule.DstPortPairs: + derived_from: tosca.datatypes.Root + description: destination port pairs + properties: + network_policy_entries_policy_rule_dst_ports_start_port: + type: string + description: Start port + required: false + status: SUPPORTED + network_policy_entries_policy_rule_dst_ports_end_port: + type: string + description: End port + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.network.rule.SrcPortPairs: + derived_from: tosca.datatypes.Root + description: source port pairs + properties: + network_policy_entries_policy_rule_src_ports_start_port: + type: string + description: Start port + required: false + status: SUPPORTED + network_policy_entries_policy_rule_src_ports_end_port: + type: string + description: End port + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.network.rule.ActionList: + derived_from: tosca.datatypes.Root + description: Action List + properties: + network_policy_entries_policy_rule_action_list_simple_action: + type: string + description: Simple Action + required: false + status: SUPPORTED + network_policy_entries_policy_rule_action_list_apply_service: + type: list + description: Apply Service + required: false + status: SUPPORTED + entry_schema: + type: string + org.openecomp.datatypes.heat.contrailV2.network.rule.Rule: + derived_from: tosca.datatypes.Root + description: policy rule + properties: + network_policy_entries_policy_rule_dst_addresses: + type: list + description: Destination addresses + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.DstVirtualNetwork + network_policy_entries_policy_rule_dst_ports: + type: list + description: Destination ports + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.DstPortPairs + network_policy_entries_policy_rule_protocol: + type: string + description: Protocol + required: false + status: SUPPORTED + network_policy_entries_policy_rule_src_addresses: + type: list + description: Source addresses + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.SrcVirtualNetwork + network_policy_entries_policy_rule_direction: + type: string + description: Direction + required: false + status: SUPPORTED + network_policy_entries_policy_rule_src_ports: + type: list + description: Source ports + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.SrcPortPairs + network_policy_entries_policy_rule_action_list: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.ActionList + description: Action list + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.network.rule.RuleList: + derived_from: tosca.datatypes.Root + description: list of policy rules + properties: + network_policy_entries_policy_rule: + type: list + description: Contrail network rule + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.network.rule.Rule + org.openecomp.datatypes.heat.network.contrail.port.StaticRoute: + derived_from: tosca.datatypes.Root + description: static route + properties: + prefix: + type: string + description: Route prefix + required: false + status: SUPPORTED + next_hop: + type: string + description: Next hop + required: false + status: SUPPORTED + next_hop_type: + type: string + description: Next hop type + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.contrail.AddressPair: + derived_from: tosca.datatypes.Root + description: Address Pair + properties: + address_mode: + type: string + description: Address mode active-active or active-standy + required: false + status: SUPPORTED + constraints: + - valid_values: + - active-active + - active-standby + prefix: + type: string + description: IP address prefix + required: false + status: SUPPORTED + mac_address: + type: string + description: Mac address + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.network.contrail.InterfaceData: + derived_from: tosca.datatypes.Root + description: Interface Data + properties: + static_routes: + type: list + description: An ordered list of static routes to be added to this interface + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.network.contrail.port.StaticRoute + virtual_network: + type: string + description: Virtual Network for this interface + required: true + status: SUPPORTED + allowed_address_pairs: + type: list + description: List of allowed address pair for this interface + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.network.contrail.AddressPair + ip_address: + type: string + description: IP for this interface + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.machine.interface.Properties: + derived_from: tosca.datatypes.Root + description: Virtual Machine Interface Properties. + properties: + virtual_machine_interface_properties_service_interface_type: + type: string + description: Service Interface Type. + required: false + status: SUPPORTED + org.openecomp.datatypes.Root: + derived_from: tosca.datatypes.Root + description: | + The ECOMP root Data Type all other Data Types derive from + properties: + supplemental_data: + type: map + entry_schema: + description: | + A placeholder for missing properties that would be included in future ecomp model versions. fromat <key>:<value> + type: string + org.openecomp.datatypes.AssignmentRequirements: + derived_from: org.openecomp.datatypes.Root + properties: + is_required: + description: | + "true" indicates that assignment is required + type: boolean + default: false + required: true + count: + description: number of assignments required + type: integer + required: false + org.openecomp.datatypes.network.SubnetAssignments: + derived_from: org.openecomp.datatypes.Root + properties: + ip_network_address_plan: + type: string + required: false + description: Reference to EIPAM, VLAN or other address plan ID used to assign subnets to this network + dhcp_enabled: + type: boolean + required: false + description: \"true\" indicates the network has 1 or more policies + ip_version: + type: integer + constraints: + - valid_values: + - 4 + - 6 + required: true + description: The IP version of the subnet + cidr_mask: + type: integer + required: true + description: The default subnet CIDR mask + min_subnets_count: + type: integer + default: 1 + required: true + description: Quantity of subnets that must be initially assigned + org.openecomp.datatypes.network.IPv4SubnetAssignments: + derived_from: org.openecomp.datatypes.network.SubnetAssignments + properties: + use_ipv4: + type: boolean + required: true + description: Indicates IPv4 subnet assignments + org.openecomp.datatypes.network.IPv6SubnetAssignments: + derived_from: org.openecomp.datatypes.network.SubnetAssignments + properties: + use_ipv6: + type: boolean + required: true + description: Indicates IPv6 subnet assignments + org.openecomp.datatypes.network.NetworkAssignments: + derived_from: org.openecomp.datatypes.Root + properties: + ecomp_generated_network_assignment: + type: boolean + required: true + default: false + description: | + \"true\" indicates that the network assignments will be auto-generated by ECOMP \"false\" indicates operator-supplied Network assignments file upload is required (e.g. VID will present prompt to operator to upload operator-supplied Network assignments file). + is_shared_network: + type: boolean + required: true + description: \"true\" means this network is shared by multiple Openstack tenants + is_external_network: + type: boolean + required: true + default: false + description: | + \"true\" means this Contrail external network + ipv4_subnet_default_assignment: + type: org.openecomp.datatypes.network.IPv4SubnetAssignments + required: true + description: IPv4 defualt subnet assignments + ipv6_subnet_default_assignment: + type: org.openecomp.datatypes.network.IPv6SubnetAssignments + required: true + description: IPv6 defualt subnet assignments + related_networks: + type: list + required: false + description: Related Networks List. + entry_schema: + type: org.openecomp.datatypes.network.RelatedNetworksAssignments + is_trunked: + type: boolean + required: true + description: \"true\" indicates that network is trunked + default: false + org.openecomp.datatypes.network.ProviderNetwork: + derived_from: org.openecomp.datatypes.Root + properties: + is_provider_network: + type: boolean + required: true + description: \"true\" indicates that this a Neutron provider type of network + physical_network_name: + type: string + required: false + constraints: + - valid_values: + - Physnet41 + - Physnet42 + - Physnet43 + - Physnet44 + - Physnet21 + - Physnet22 + - sriovnet1 + - sriovnet2 + - oam + description: | + Identifies the NUMA processor cluster to which this physical network interface belongs. NUMA instance correlates to the first digit of the Physical Network Name suffix (e.g. \"01\" = NUMA 0, \"11\" = NUMA 1) + numa: + type: string + required: false + constraints: + - valid_values: + - NUMA 0 + - NUMA 1 + description: | + PNIC instance within the NUMA processor cluster PNIC Instance correlates to the second digit of the Physical Network Name suffix (e.g. "01" = PNIC 1, "02" = "PNIC 2) + pnic_instance: + type: integer + required: false + description: PNIC instance within the NUMA processor cluster + org.openecomp.datatypes.network.NetworkFlows: + derived_from: org.openecomp.datatypes.Root + properties: + is_network_policy: + type: boolean + required: false + default: false + description: \"true\" indicates the network has 1 or more policies + network_policy: + type: string + required: false + description: 'Identifies the specific Cloud network policy that must be applied + to this network (source: from Policy Manager).' + is_bound_to_vpn: + type: boolean + required: false + default: false + description: \"true\" indicates the network has 1 or more vpn bindings + vpn_binding: + type: string + required: false + description: 'Identifies the specific VPN Binding entry in A&AI that must + be applied when creating this network (source: A&AI)' + org.openecomp.datatypes.network.VlanRequirements: + derived_from: org.openecomp.datatypes.Root + properties: + vlan_range_plan: + type: string + required: true + description: reference to a vlan range plan + vlan_type: + type: string + required: true + constraints: + - valid_values: + - c-tag + - s-tag + description: identifies the vlan type (e.g., c-tag) + vlan_count: + type: integer + required: true + description: identifies the number of vlan tags to assign to the CP from the plan + org.openecomp.datatypes.network.IpRequirements: + derived_from: org.openecomp.datatypes.Root + properties: + ip_version: + type: integer + required: true + constraints: + - valid_values: + - 4 + - 6 + ip_count: + description: identifies the number of ip address to assign to the CP from the plan + type: integer + required: false + floating_ip_count: + type: integer + required: false + subnet_role: + type: string + required: false + assingment_method: + type: string + required: true + constraints: + - valid_values: + - fixed + - dhcp + dhcp_enabled: + type: boolean + required: false + ip_count_required: + description: identifies the number of ip address to assign to the CP from the plan + type: org.openecomp.datatypes.AssignmentRequirements + required: false + floating_ip_count_required: + type: org.openecomp.datatypes.AssignmentRequirements + required: false + ip_address_plan_name: + type: string + required: false + vrf_name: + type: string + required: false + org.openecomp.datatypes.network.MacAssignments: + derived_from: org.openecomp.datatypes.Root + properties: + mac_range_plan: + type: string + required: true + description: reference to a MAC address range plan + mac_count: + type: integer + required: true + description: identifies the number of MAC addresses to assign to the CP from the plan + org.openecomp.datatypes.EcompHoming: + derived_from: org.openecomp.datatypes.Root + properties: + ecomp_selected_instance_node_target: + type: boolean + required: true + default: false + description: | + \"true\" indicates that the target deployment node for this instance will be auto-selected by ECOMP \"false\" indicates operator-supplied instance target deployment node required (e.g. VID will present a prompt to operator and collect the operator-selected target node for the deployment of this Network instance). + homing_policy: + type: string + required: false + description: Referenc to a service level homing policy that ECOMP will use for instance deployment target node + instance_node_target: + type: string + required: false + description: Instance target deployment node + org.openecomp.datatypes.EcompNaming: + derived_from: org.openecomp.datatypes.Root + properties: + ecomp_generated_naming: + type: boolean + required: true + default: true + description: | + \"true\" indicates that the name for the instance will be auto-generated by ECOMP. \"false\" indicates operator-supplied name required (e.g. VID will present prompt to operator and collect the operator-supplied instance name). + naming_policy: + type: string + required: false + description: Referenc to naming policy that ECOMP will use when the name is auto-generated + org.openecomp.datatypes.network.MacRequirements: + derived_from: org.openecomp.datatypes.Root + properties: + mac_range_plan: + description: reference to a MAC address range plan + type: string + required: false + mac_count: + description: identifies the number of MAC addresses to assign to the CP from the plan + type: integer + required: false + mac_count_required: + description: identifies the number of MAC addresses to assign to the CP from the plan + type: org.openecomp.datatypes.AssignmentRequirements + org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.AddressPairIp: + derived_from: tosca.datatypes.Root + description: Virtual Machine Sub Interface Address Pair IP. + properties: + ip_prefix: + type: string + description: IP Prefix. + required: false + status: SUPPORTED + ip_prefix_len: + type: integer + description: IP Prefix Len. + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.MacAddress: + derived_from: tosca.datatypes.Root + description: Virtual Machine Sub Interface Mac Address. + properties: + mac_address: + type: list + description: Mac Addresses List. + required: false + status: SUPPORTED + entry_schema: + type: string + org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.Properties: + derived_from: tosca.datatypes.Root + description: Virtual Machine Sub Interface VLAN Properties. + properties: + sub_interface_vlan_tag: + type: string + description: Sub Interface VLAN Tag. + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.AddressPair: + derived_from: tosca.datatypes.Root + description: Virtual Machine Sub Interface Address Pair. + properties: + address_mode: + type: string + description: Address Mode. + required: false + status: SUPPORTED + ip: + type: org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.AddressPairIp + description: IP. + required: false + status: SUPPORTED + mac: + type: string + description: Mac. + required: false + status: SUPPORTED + org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.AddressPairs: + derived_from: tosca.datatypes.Root + description: Virtual Machine Sub Interface Address Pairs. + properties: + allowed_address_pair: + type: list + description: Addresses pair List. + required: false + status: SUPPORTED + entry_schema: + type: org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.AddressPair + org.openecomp.datatypes.Naming: + derived_from: org.openecomp.datatypes.Root + properties: + ecomp_generated_naming: + description: | + "true" indicates that the name for the instance will be auto-generated by ECOMP. "false" indicates operator-supplied name required (e.g. VID will present prompt to operator and collect the operator-supplied instance name). + type: boolean + default: true + required: true + naming_policy: + description: Reference to naming policy that ECOMP will use when the name is auto-generated + type: string + required: false + instance_name: + description: indicates operator-supplied name required (e.g. VID will present prompt to operator and collect the operator-supplied instance name). + type: string + required: false + org.openecomp.datatypes.flavors.ComputeFlavor: + derived_from: tosca.datatypes.Root + properties: + num_cpus: + type: integer + disk_size: + type: scalar-unit.size + mem_size: + type: scalar-unit.size + org.openecomp.datatypes.flavors.LicenseFlavor: + derived_from: tosca.datatypes.Root + properties: + feature_group_uuid: + type: string + org.openecomp.datatypes.flavors.VendorInfo: + derived_from: tosca.datatypes.Root + properties: + manufacturer_reference_number: + type: string + vendor_model: + type: string + org.openecomp.datatypes.flavors.DeploymentFlavor: + derived_from: tosca.datatypes.Root + properties: + sp_part_number: + type: string + vendor_info: + type: org.openecomp.datatypes.flavors.VendorInfo + compute_flavor: + type: org.openecomp.datatypes.flavors.ComputeFlavor + license_flavor: + type: org.openecomp.datatypes.flavors.LicenseFlavor + required: false + org.openecomp.datatypes.ImageInfo: + derived_from: tosca.datatypes.Root + properties: + software_version: + type: string + file_name: + type: string + file_hash: + type: string + description: checksum/signature + file_hash_type: + type: string + required: false + default: md5 + org.openecomp.datatypes.network.RelatedNetworksAssignments: + derived_from: org.openecomp.datatypes.Root + properties: + related_network_role: + type: string + description: The network role of the related network, sharing provider network. + required: false + tosca.datatypes.nfv.VnfcAdditionalConfigurableProperties: + derived_from: tosca.datatypes.Root + description: VnfcAdditionalConfigurableProperties type is an empty base type for deriving data types for describing additional configurable properties for a given VNFC. + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfcConfigurableProperties: + derived_from: tosca.datatypes.Root + description: Defines the configurable properties of a VNFC + properties: + additional_vnfc_configurable_properties: + type: tosca.datatypes.nfv.VnfcAdditionalConfigurableProperties + description: Describes additional configuration for VNFC that can be modified using the ModifyVnfInfo operation + required: false + tosca.datatypes.nfv.RequestedAdditionalCapability: + derived_from: tosca.datatypes.Root + description: describes requested additional capability for a particular VDU + properties: + requested_additional_capability_name: + type: string + description: Identifies a requested additional capability for the VDU. + required: true + support_mandatory: + type: boolean + description: Indicates whether the requested additional capability is mandatory for successful operation. + required: true + min_requested_additional_capability_version: + type: string + description: Identifies the minimum version of the requested additional capability. + required: false + preferred_requested_additional_capability_version: + type: string + description: Identifies the preferred version of the requested additional capability. + required: false + target_performance_parameters: + type: map + description: Identifies specific attributes, dependent on the requested additional capability type. + required: true + entry_schema: + type: string + tosca.datatypes.nfv.VirtualMemory: + derived_from: tosca.datatypes.Root + description: supports the specification of requirements related to virtual memory of a virtual compute resource + properties: + virtual_mem_size: + type: scalar-unit.size + description: Amount of virtual memory. + required: true + virtual_mem_oversubscription_policy: + type: string + description: The memory core oversubscription policy in terms of virtual memory to physical memory on the platform. + required: false + vdu_mem_requirements: + type: map + description: The hardware platform specific VDU memory requirements. A map of strings that contains a set of key-value pairs that describes hardware platform specific VDU memory requirements. + required: false + entry_schema: + type: string + numa_enabled: + type: boolean + description: It specifies the memory allocation to be cognisant of the relevant process/core allocation. + required: false + default: false + tosca.datatypes.nfv.VirtualCpuPinning: + derived_from: tosca.datatypes.Root + description: Supports the specification of requirements related to the virtual CPU pinning configuration of a virtual compute resource + properties: + virtual_cpu_pinning_policy: + type: string + description: 'Indicates the policy for CPU pinning. The policy can take values + of "static" or "dynamic". In case of "dynamic" the allocation of virtual + CPU cores to logical CPU cores is decided by the VIM. (e.g.: SMT (Simultaneous + Multi-Threading) requirements). In case of "static" the allocation is requested + to be according to the virtual_cpu_pinning_rule.' + required: false + constraints: + - valid_values: + - static + - dynamic + virtual_cpu_pinning_rule: + type: list + description: Provides the list of rules for allocating virtual CPU cores to logical CPU cores/threads + required: false + entry_schema: + type: string + tosca.datatypes.nfv.VirtualCpu: + derived_from: tosca.datatypes.Root + description: Supports the specification of requirements related to virtual CPU(s) of a virtual compute resource + properties: + cpu_architecture: + type: string + description: CPU architecture type. Examples are x86, ARM + required: false + num_virtual_cpu: + type: integer + description: Number of virtual CPUs + required: true + constraints: + - greater_than: 0 + virtual_cpu_clock: + type: scalar-unit.frequency + description: Minimum virtual CPU clock rate + required: false + virtual_cpu_oversubscription_policy: + type: string + description: CPU core oversubscription policy e.g. the relation of virtual CPU cores to physical CPU cores/threads. + required: false + vdu_cpu_requirements: + type: map + description: The hardware platform specific VDU CPU requirements. A map of strings that contains a set of key-value pairs describing VDU CPU specific hardware platform requirements. + required: false + entry_schema: + type: string + virtual_cpu_pinning: + type: tosca.datatypes.nfv.VirtualCpuPinning + description: The virtual CPU pinning configuration for the virtualised compute resource. + required: false + tosca.datatypes.nfv.LogicalNodeData: + derived_from: tosca.datatypes.Root + description: Describes compute, memory and I/O requirements associated with a particular VDU. + properties: + logical_node_requirements: + type: map + description: The logical node-level compute, memory and I/O requirements. A map of strings that contains a set of key-value pairs that describes hardware platform specific deployment requirements, including the number of CPU cores on this logical node, a memory configuration specific to a logical node or a requirement related to the association of an I/O device with the logical node. + required: false + entry_schema: + type: string + tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements: + derived_from: tosca.datatypes.Root + description: Describes requirements on a virtual network interface + properties: + name: + type: string + description: Provides a human readable name for the requirement. + required: false + description: + type: string + description: Provides a human readable description of the requirement. + required: false + support_mandatory: + type: boolean + description: Indicates whether fulfilling the constraint is mandatory (TRUE) for successful operation or desirable (FALSE). + required: true + network_interface_requirements: + type: map + description: The network interface requirements. A map of strings that contain a set of key-value pairs that describes the hardware platform specific network interface deployment requirements. + required: true + entry_schema: + type: string + nic_io_requirements: + type: tosca.datatypes.nfv.LogicalNodeData + description: references (couples) the CP with any logical node I/O requirements (for network devices) that may have been created. Linking these attributes is necessary so that so that I/O requirements that need to be articulated at the logical node level can be associated with the network interface requirements associated with the CP. + required: false + tosca.datatypes.nfv.injectFile: + derived_from: tosca.datatypes.Root + properties: + source_path: + type: string + required: true + dest_path: + type: string + required: true + tosca.datatypes.nfv.L2AddressData: + derived_from: tosca.datatypes.Root + description: Describes the information on the MAC addresses to be assigned to a connection point. + properties: + mac_address_assignment: + type: boolean + description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility + required: true + tosca.datatypes.nfv.L3AddressData: + derived_from: tosca.datatypes.Root + description: Provides information about Layer 3 level addressing scheme and parameters applicable to a CP + properties: + ip_address_assignment: + type: boolean + description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility + required: true + floating_ip_activated: + type: boolean + description: Specifies if the floating IP scheme is activated on the Connection Point or not + required: true + ip_address_type: + type: string + description: Defines address type. The address type should be aligned with the address type supported by the layer_protocols properties of the parent VnfExtCp + required: false + constraints: + - valid_values: + - ipv4 + - ipv6 + number_of_ip_address: + type: integer + description: Minimum number of IP addresses to be assigned + required: false + constraints: + - greater_than: 0 + fixed_ip_address: + type: list + entry_schema: + type: string + required: false + tosca.datatypes.nfv.AddressData: + derived_from: tosca.datatypes.Root + description: Describes information about the addressing scheme and parameters applicable to a CP + properties: + address_type: + type: string + description: Describes the type of the address to be assigned to a connection point. The content type shall be aligned with the address type supported by the layerProtocol property of the connection point + required: true + constraints: + - valid_values: + - mac_address + - ip_address + l2_address_data: + type: tosca.datatypes.nfv.L2AddressData + description: Provides the information on the MAC addresses to be assigned to a connection point. + required: false + l3_address_data: + type: tosca.datatypes.nfv.L3AddressData + description: Provides the information on the IP addresses to be assigned to a connection point + required: false + tosca.datatypes.nfv.ConnectivityType: + derived_from: tosca.datatypes.Root + description: describes additional connectivity information of a virtualLink + properties: + layer_protocols: + type: list + description: Identifies the protocol a virtualLink gives access to (ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire).The top layer protocol of the virtualLink protocol stack shall always be provided. The lower layer protocols may be included when there are specific requirements on these layers. + required: true + entry_schema: + type: string + constraints: + - valid_values: + - ethernet + - mpls + - odu2 + - ipv4 + - ipv6 + - pseudo-wire + flow_pattern: + type: string + description: Identifies the flow pattern of the connectivity + required: false + constraints: + - valid_values: + - line + - tree + - mesh + tosca.datatypes.nfv.VlFlavour: + derived_from: tosca.datatypes.Root + properties: + flavourId: + type: string + tosca.datatypes.nfv.ext.AddressPairs: + properties: + ip: + type: string + required: false + mac: + type: string + required: false + tosca.datatypes.nfv.ext.FloatingIP: + properties: + external_network: + type: string + required: false + ip_address: + type: string + required: false + tosca.datatypes.nfv.ext.LocationInfo: + properties: + availability_zone: + type: string + required: false + vimid: + type: integer + required: false + tenant: + type: string + required: false + tosca.datatypes.nfv.ext.HostRouteInfo: + properties: + destination: + type: string + required: false + nexthop: + type: string + required: false + tosca.datatypes.nfv.ext.InjectData: + properties: + file_name: + type: string + required: false + file_data: + type: string + required: false + tosca.datatypes.nfv.ext.zte.WatchDog: + properties: + enable_delay: + type: integer + required: false + action: + type: string + required: false + tosca.datatypes.nfv.ext.LocalAffinityOrAntiAffinityRule: + properties: + scope: + type: string + required: false + affinity_antiaffinity: + type: string + required: false + tosca.datatypes.nfv.VduProfile: + derived_from: tosca.datatypes.Root + description: describes additional instantiation data for a given Vdu.Compute used in a specific deployment flavour. + properties: + min_number_of_instances: + type: integer + description: Minimum number of instances of the VNFC based on this Vdu.Compute that is permitted to exist for a particular VNF deployment flavour. + required: true + constraints: + - greater_or_equal: 0 + max_number_of_instances: + type: integer + description: Maximum number of instances of the VNFC based on this Vdu.Compute that is permitted to exist for a particular VNF deployment flavour. + required: true + constraints: + - greater_or_equal: 0 + watchdog: + type: string + required: true + vmBootUpTimeOut: + type: integer + required: false + tosca.datatypes.nfv.LinkBitrateRequirements: + derived_from: tosca.datatypes.Root + description: describes the requirements in terms of bitrate for a virtual link + properties: + root: + type: integer + description: Specifies the throughput requirement in bits per second of the link (e.g. bitrate of E-Line, root bitrate of E-Tree, aggregate capacity of E-LAN). + required: true + constraints: + - greater_or_equal: 0 + leaf: + type: integer + description: Specifies the throughput requirement in bits per second of leaf connections to the link when applicable to the connectivity type (e.g. for E-Tree and E LAN branches). + required: false + constraints: + - greater_or_equal: 0 + tosca.datatypes.nfv.Qos: + derived_from: tosca.datatypes.Root + description: describes QoS data for a given VL used in a VNF deployment flavour + properties: + latency: + type: scalar-unit.time + description: Specifies the maximum latency + required: true + constraints: + - greater_than: 0 s + packet_delay_variation: + type: scalar-unit.time + description: Specifies the maximum jitter + required: true + constraints: + - greater_or_equal: 0 s + packet_loss_ratio: + type: float + description: Specifies the maximum packet loss ratio + required: false + constraints: + - in_range: + - 0.0 + - 1.0 + tosca.datatypes.nfv.IpAllocationPool: + derived_from: tosca.datatypes.Root + description: Specifies a range of IP addresses + properties: + start_ip_address: + type: string + description: The IP address to be used as the first one in a pool of addresses derived from the cidr block full IP range + required: true + end_ip_address: + type: string + description: The IP address to be used as the last one in a pool of addresses derived from the cidr block full IP range + required: true + tosca.datatypes.nfv.L2ProtocolData: + derived_from: tosca.datatypes.Root + description: describes L2 protocol data for a given virtual link used in a specific VNF deployment flavour. + properties: + name: + type: string + description: Identifies the network name associated with this L2 protocol. + required: false + network_type: + type: string + description: Specifies the network type for this L2 protocol.The value may be overridden at run-time. + required: false + constraints: + - valid_values: + - flat + - vlan + - vxlan + - gre + vlan_transparent: + type: boolean + description: Specifies whether to support VLAN transparency for this L2 protocol or not. + required: false + default: false + mtu: + type: integer + description: Specifies the maximum transmission unit (MTU) value for this L2 protocol. + required: false + constraints: + - greater_than: 0 + segmentation_id: + type: integer + required: false + physical_network: + type: string + required: false + tosca.datatypes.nfv.L3ProtocolData: + derived_from: tosca.datatypes.Root + description: describes L3 protocol data for a given virtual link used in a specific VNF deployment flavour. + properties: + name: + type: string + description: Identifies the network name associated with this L3 protocol. + required: false + ip_version: + type: string + description: Specifies IP version of this L3 protocol.The value of the ip_version property shall be consistent with the value of the layer_protocol in the connectivity_type property of the virtual link node. + required: true + constraints: + - valid_values: + - ipv4 + - ipv6 + cidr: + type: string + description: Specifies the CIDR (Classless Inter-Domain Routing) of this L3 protocol. The value may be overridden at run-time. + required: true + ip_allocation_pools: + type: list + description: Specifies the allocation pools with start and end IP addresses for this L3 protocol. The value may be overridden at run-time. + required: false + entry_schema: + type: tosca.datatypes.nfv.IpAllocationPool + gateway_ip: + type: string + description: Specifies the gateway IP address for this L3 protocol. The value may be overridden at run-time. + required: false + dhcp_enabled: + type: boolean + description: Indicates whether DHCP (Dynamic Host Configuration Protocol) is enabled or disabled for this L3 protocol. The value may be overridden at run-time. + required: false + ipv6_address_mode: + type: string + description: Specifies IPv6 address mode. May be present when the value of the ipVersion attribute is "ipv6" and shall be absent otherwise. The value may be overridden at run-time. + required: false + constraints: + - valid_values: + - slaac + - dhcpv6-stateful + - dhcpv6-stateless + tosca.datatypes.nfv.VirtualLinkProtocolData: + derived_from: tosca.datatypes.Root + description: describes one protocol layer and associated protocol data for a given virtual link used in a specific VNF deployment flavour + properties: + associated_layer_protocol: + type: string + description: Identifies one of the protocols a virtualLink gives access to (ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire) as specified by the connectivity_type property. + required: true + constraints: + - valid_values: + - ethernet + - mpls + - odu2 + - ipv4 + - ipv6 + - pseudo-wire + l2_protocol_data: + type: tosca.datatypes.nfv.L2ProtocolData + description: Specifies the L2 protocol data for a virtual link. Shall be present when the associatedLayerProtocol attribute indicates a L2 protocol and shall be absent otherwise. + required: false + l3_protocol_data: + type: tosca.datatypes.nfv.L3ProtocolData + description: Specifies the L3 protocol data for this virtual link. Shall be present when the associatedLayerProtocol attribute indicates a L3 protocol and shall be absent otherwise. + required: false + tosca.datatypes.nfv.VlProfile: + derived_from: tosca.datatypes.Root + description: Describes additional instantiation data for a given VL used in a specific VNF deployment flavour. + properties: + max_bitrate_requirements: + type: tosca.datatypes.nfv.LinkBitrateRequirements + description: Specifies the maximum bitrate requirements for a VL instantiated according to this profile. + required: true + min_bitrate_requirements: + type: tosca.datatypes.nfv.LinkBitrateRequirements + description: Specifies the minimum bitrate requirements for a VL instantiated according to this profile. + required: true + qos: + type: tosca.datatypes.nfv.Qos + description: Specifies the QoS requirements of a VL instantiated according to this profile. + required: false + virtual_link_protocol_data: + type: list + description: Specifies the protocol data for a virtual link. + required: false + entry_schema: + type: tosca.datatypes.nfv.VirtualLinkProtocolData + tosca.datatypes.nfv.VduLevel: + derived_from: tosca.datatypes.Root + description: Indicates for a given Vdu.Compute in a given level the number of instances to deploy + properties: + number_of_instances: + type: integer + description: Number of instances of VNFC based on this VDU to deploy for this level. + required: true + constraints: + - greater_or_equal: 0 + tosca.datatypes.nfv.ScaleInfo: + derived_from: tosca.datatypes.Root + description: Indicates for a given scaleAspect the corresponding scaleLevel + properties: + scale_level: + type: integer + description: The scale level for a particular aspect + required: true + constraints: + - greater_or_equal: 0 + tosca.datatypes.nfv.ScalingAspect: + derived_from: tosca.datatypes.Root + properties: + name: + type: string + required: true + description: + type: string + required: true + max_scale_level: + type: integer + required: true + constraints: + - greater_or_equal: 0 + step_deltas: + type: list + required: false + entry_schema: + type: string + tosca.datatypes.nfv.InstantiationLevel: + derived_from: tosca.datatypes.Root + description: Describes the scale level for each aspect that corresponds to a given level of resources to be instantiated within a deployment flavour in term of the number VNFC instances + properties: + description: + type: string + description: Human readable description of the level + required: true + scale_info: + type: map + description: Represents for each aspect the scale level that corresponds to this instantiation level. scale_info shall be present if the VNF supports scaling. + required: false + entry_schema: + type: tosca.datatypes.nfv.ScaleInfo + tosca.datatypes.nfv.VnfInstantiateOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the InstantiateVnf operation. + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfScaleOperationConfiguration: + derived_from: tosca.datatypes.Root + description: Represents information that affect the invocation of the ScaleVnf operation + properties: + scaling_by_more_than_one_step_supported: + type: boolean + description: Signals whether passing a value larger than one in the numScalingSteps parameter of the ScaleVnf operation is supported by this VNF. + required: false + default: false + tosca.datatypes.nfv.VnfScaleToLevelOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the ScaleVnfToLevel operation + properties: + arbitrary_target_levels_supported: + type: boolean + description: Signals whether scaling according to the parameter "scaleInfo" is supported by this VNF + required: true + tosca.datatypes.nfv.VnfHealOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the HealVnf operation + properties: + causes: + type: list + description: Supported "cause" parameter values + required: false + entry_schema: + type: string + tosca.datatypes.nfv.VnfTerminateOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the TerminateVnf + properties: + min_graceful_termination_timeout: + type: scalar-unit.time + description: Minimum timeout value for graceful termination of a VNF instance + required: true + max_recommended_graceful_termination_timeout: + type: scalar-unit.time + description: Maximum recommended timeout value that can be needed to gracefully terminate a VNF instance of a particular type under certain conditions, such as maximum load condition. This is provided by VNF provider as information for the operator facilitating the selection of optimal timeout value. This value is not used as constraint + required: false + tosca.datatypes.nfv.VnfOperateOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the OperateVnf operation + properties: + min_graceful_stop_timeout: + type: scalar-unit.time + description: Minimum timeout value for graceful stop of a VNF instance + required: true + max_recommended_graceful_stop_timeout: + type: scalar-unit.time + description: Maximum recommended timeout value that can be needed to gracefully stop a VNF instance of a particular type under certain conditions, such as maximum load condition. This is provided by VNF provider as information for the operator facilitating the selection of optimal timeout value. This value is not used as constraint + required: false + tosca.datatypes.nfv.VnfChangeFlavourOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the ChangeVnfFlavour operation + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfProfile: + derived_from: tosca.datatypes.Root + description: describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF. + properties: + instantiation_level: + type: string + description: Identifier of the instantiation level of the VNF DF to be used for instantiation. If not present, the default instantiation level as declared in the VNFD shall be used. + required: false + min_number_of_instances: + type: integer + description: Minimum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile. + required: true + constraints: + - greater_or_equal: 0 + max_number_of_instances: + type: integer + description: Maximum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile. + required: true + constraints: + - greater_or_equal: 0 + tosca.datatypes.nfv.UriAuthority: + derived_from: tosca.datatypes.Root + description: information that corresponds to the authority component of a URI as specified in IETF RFC 3986 [8] + properties: + user_info: + type: string + description: user_info field of the authority component of a URI + required: false + host: + type: string + description: host field of the authority component of a URI + required: false + port: + type: string + description: port field of the authority component of a URI + required: false + tosca.datatypes.nfv.UriComponents: + derived_from: tosca.datatypes.Root + description: information used to build a URI that complies with IETF RFC 3986 [8]. + properties: + scheme: + type: string + description: scheme component of a URI. + required: true + authority: + type: tosca.datatypes.nfv.UriAuthority + description: Authority component of a URI + required: false + path: + type: string + description: path component of a URI. + required: false + query: + type: string + description: query component of a URI. + required: false + fragment: + type: string + description: fragment component of a URI. + required: false + tosca.datatypes.nfv.InterfaceDetails: + derived_from: tosca.datatypes.Root + description: information used to access an interface exposed by a VNF + properties: + uri_components: + type: tosca.datatypes.nfv.UriComponents + description: Provides components to build a Uniform Ressource Identifier (URI) where to access the interface end point. + required: false + interface_specific_data: + type: map + description: Provides additional details that are specific to the type of interface considered. + required: false + entry_schema: + type: string + tosca.datatypes.nfv.VirtualLinkMonitoringParameter: + derived_from: tosca.datatypes.Root + description: Represents information on virtualised resource related performance metrics applicable to the VNF. + properties: + name: + type: string + description: Human readable name of the monitoring parameter + required: true + performance_metric: + type: string + description: Identifies a performance metric derived from those defined in ETSI GS NFV-IFA 027.The packetOutgoingVirtualLink and packetIncomingVirtualLink metrics shall be obtained by aggregation the PacketOutgoing and PacketIncoming measurements defined in clause 7.1 of GS NFV-IFA 027 of all virtual link ports attached to the virtual link to which the metrics apply. + required: true + constraints: + - valid_values: + - packet_outgoing_virtual_link + - packet_incoming_virtual_link + collection_period: + type: scalar-unit.time + description: Describes the recommended periodicity at which to collect the performance information. + required: false + constraints: + - greater_than: 0 s + tosca.datatypes.nfv.VnfcMonitoringParameter: + derived_from: tosca.datatypes.Root + description: Represents information on virtualised resource related performance metrics applicable to the VNF. + properties: + name: + type: string + description: Human readable name of the monitoring parameter + required: true + performance_metric: + type: string + description: Identifies the performance metric, according to ETSI GS NFV-IFA 027. + required: true + constraints: + - valid_values: + - v_cpu_usage_mean_vnf + - v_cpu_usage_peak_vnf + - v_memory_usage_mean_vnf + - v_memory_usage_peak_vnf + - v_disk_usage_mean_vnf + - v_disk_usage_peak_vnf + - byte_incoming_vnf_int_cp + - byte_outgoing_vnf_int_cp + - packet_incoming_vnf_int_cp + - packet_outgoing_vnf_int_cp + collection_period: + type: scalar-unit.time + description: Describes the recommended periodicity at which to collect the performance information. + required: false + constraints: + - greater_than: 0 s + tosca.datatypes.nfv.VnfChangeExtConnectivityOperationConfiguration: + derived_from: tosca.datatypes.Root + description: represents information that affect the invocation of the ChangeExtVnfConnectivity operation + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfMonitoringParameter: + derived_from: tosca.datatypes.Root + description: Represents information on virtualised resource related performance metrics applicable to the VNF. + properties: + name: + type: string + description: Human readable name of the monitoring parameter + required: true + performance_metric: + type: string + description: Identifies the performance metric, according to ETSI GS NFV-IFA 027. + required: true + constraints: + - valid_values: + - v_cpu_usage_mean_vnf + - v_cpu_usage_peak_vnf + - v_memory_usage_mean_vnf + - v_memory_usage_peak_vnf + - v_disk_usage_mean_vnf + - v_disk_usage_peak_vnf + - byte_incoming_vnf_ext_cp + - byte_outgoing_vnf_ext_cp + - packet_incoming_vnf_ext_cp + - packet_outgoing_vnf_ext_cp + collection_period: + type: scalar-unit.time + description: Describes the recommended periodicity at which to collect the performance information. + required: false + constraints: + - greater_than: 0 s + tosca.datatypes.nfv.VnfLcmOperationsConfiguration: + derived_from: tosca.datatypes.Root + description: Represents information to configure lifecycle management operations + properties: + instantiate: + type: tosca.datatypes.nfv.VnfInstantiateOperationConfiguration + description: Configuration parameters for the InstantiateVnf operation + required: false + scale: + type: tosca.datatypes.nfv.VnfScaleOperationConfiguration + description: Configuration parameters for the ScaleVnf operation + required: false + scale_to_level: + type: tosca.datatypes.nfv.VnfScaleToLevelOperationConfiguration + description: Configuration parameters for the ScaleVnfToLevel operation + required: false + change_flavour: + type: tosca.datatypes.nfv.VnfChangeFlavourOperationConfiguration + description: Configuration parameters for the changeVnfFlavourOpConfig operation + required: false + heal: + type: tosca.datatypes.nfv.VnfHealOperationConfiguration + description: Configuration parameters for the HealVnf operation + required: false + terminate: + type: tosca.datatypes.nfv.VnfTerminateOperationConfiguration + description: Configuration parameters for the TerminateVnf operation + required: false + operate: + type: tosca.datatypes.nfv.VnfOperateOperationConfiguration + description: Configuration parameters for the OperateVnf operation + required: false + change_ext_connectivity: + type: tosca.datatypes.nfv.VnfChangeExtConnectivityOperationConfiguration + description: Configuration parameters for the changeExtVnfConnectivityOpConfig operation + required: false + tosca.datatypes.nfv.CpProtocolData: + derived_from: tosca.datatypes.Root + description: Describes and associates the protocol layer that a CP uses together with other protocol and connection point information + properties: + associated_layer_protocol: + type: string + required: true + description: One of the values of the property layer_protocols of the CP + constraints: + - valid_values: + - ethernet + - mpls + - odu2 + - ipv4 + - ipv6 + - pseudo-wire + address_data: + type: list + description: Provides information on the addresses to be assigned to the CP + entry_schema: + type: tosca.datatypes.nfv.AddressData + required: false + tosca.datatypes.nfv.VnfAdditionalConfigurableProperties: + derived_from: tosca.datatypes.Root + description: is an empty base type for deriving data types for describing additional configurable properties for a given VNF + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfConfigurableProperties: + derived_from: tosca.datatypes.Root + description: indicates configuration properties for a given VNF (e.g. related to auto scaling and auto healing). + properties: + is_autoscale_enabled: + type: boolean + description: It permits to enable (TRUE)/disable (FALSE) the auto-scaling functionality. If the properties is not present for configuring, then VNF property is not supported + required: false + is_autoheal_enabled: + type: boolean + description: It permits to enable (TRUE)/disable (FALSE) the auto-healing functionality. If the properties is not present for configuring, then VNF property is not supported + required: false + additional_configurable_properties: + description: It provides VNF specific configurable properties that can be modified using the ModifyVnfInfo operation + required: false + type: tosca.datatypes.nfv.VnfAdditionalConfigurableProperties + tosca.datatypes.nfv.VnfInfoModifiableAttributesExtensions: + derived_from: tosca.datatypes.Root + description: is an empty base type for deriving data types for describing VNF-specific extension + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfInfoModifiableAttributesMetadata: + derived_from: tosca.datatypes.Root + description: is an empty base type for deriving data types for describing VNF-specific metadata + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VnfInfoModifiableAttributes: + derived_from: tosca.datatypes.Root + description: Describes VNF-specific extension and metadata for a given VNF + properties: + extensions: + type: tosca.datatypes.nfv.VnfInfoModifiableAttributesExtensions + description: \"Extension\" properties of VnfInfo that are writeable + required: false + metadata: + type: tosca.datatypes.nfv.VnfInfoModifiableAttributesMetadata + description: \"Metadata\" properties of VnfInfo that are writeable + required: false + tosca.datatypes.nfv.VirtualLinkBitrateLevel: + derived_from: tosca.datatypes.Root + description: Describes bitrate requirements applicable to the virtual link instantiated from a particicular VnfVirtualLink + properties: + description: + type: string + required: false + bitrate_requirements: + type: tosca.datatypes.nfv.LinkBitrateRequirements + description: Virtual link bitrate requirements for an instantiation level or bitrate delta for a scaling step + required: true + tosca.datatypes.nfv.VnfOperationAdditionalParameters: + derived_from: tosca.datatypes.Root + description: Is an empty base type for deriving data type for describing VNF-specific parameters to be passed when invoking lifecycle management operations + properties: + description: + type: string + required: false + tosca.datatypes.nfv.VirtualFileStorageData: + derived_from: tosca.datatypes.Root + description: VirtualFileStorageData describes file storage requirements associated with compute resources in a particular VDU + properties: + size_of_storage: + type: scalar-unit.size + description: Size of virtualized storage resource + required: true + file_system_protocol: + type: string + description: The shared file system protocol (e.g. NFS, CIFS) + required: true + tosca.datatypes.nfv.VirtualObjectStorageData: + derived_from: tosca.datatypes.Root + description: VirtualObjectStorageData describes object storage requirements associated with compute resources in a particular VDU + properties: + max_size_of_storage: + type: scalar-unit.size + description: Maximum size of virtualized storage resource + required: false + tosca.datatypes.nfv.VirtualBlockStorageData: + derived_from: tosca.datatypes.Root + description: VirtualBlockStorageData describes block storage requirements associated with compute resources in a particular VDU, either as a local disk or as virtual attached storage + properties: + size_of_storage: + type: scalar-unit.size + description: Size of virtualised storage resource + required: true + vdu_storage_requirements: + type: map + description: The hardware platform specific storage requirements. A map of strings that contains a set of key-value pairs that represents the hardware platform specific storage deployment requirements. + required: false + entry_schema: + type: string + rdma_enabled: + type: boolean + description: Indicates if the storage support RDMA + required: false + default: false + tosca.datatypes.nfv.SwImageData: + derived_from: tosca.datatypes.Root + description: describes information related to a software image artifact + properties: + name: + type: string + description: Name of this software image + required: true + version: + type: string + description: Version of this software image + required: true + checksum: + type: string + description: Checksum of the software image file + required: true + container_format: + type: string + description: The container format describes the container file format in which software image is provided + required: true + constraints: + - valid_values: + - aki + - ami + - ari + - bare + - docker + - ova + - ovf + disk_format: + type: string + description: The disk format of a software image is the format of the underlying disk image + required: true + constraints: + - valid_values: + - aki + - ami + - ari + - iso + - qcow2 + - raw + - vdi + - vhd + - vhdx + - vmdk + min_disk: + type: scalar-unit.size + description: The minimal disk size requirement for this software image + required: true + min_ram: + type: scalar-unit.size + description: The minimal RAM requirement for this software image + required: false + size: + type: scalar-unit.size + description: The size of this software image + required: true + operating_system: + type: string + description: Identifies the operating system used in the software image + required: false + supported_virtualisation_environments: + type: list + description: Identifies the virtualisation environments (e.g. hypervisor) compatible with this software image + required: false + entry_schema: + type: string + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + constraints: + - valid_values: + - VM + - VNF + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + required: true + type: string + eventName: + description: Event name to which thresholds need to be applied + required: true + type: string + policyName: + description: TCA Policy Scope Name + required: true + type: string + policyScope: + description: TCA Policy Scope + required: true + type: string + policyVersion: + description: TCA Policy Scope Version + required: true + type: string + thresholds: + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + required: true + type: list + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + constraints: + - equal: measurementsForVfScaling + default: measurementsForVfScaling + description: Domain name to which TCA needs to be applied + required: true + type: string + metricsPerEventName: + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + required: true + type: list + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + description: Closed Loop Control Name associated with the threshold + required: true + type: string + closedLoopEventStatus: + constraints: + - valid_values: + - ONSET + - ABATED + description: Closed Loop Event Status of the threshold + required: true + type: string + direction: + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + description: Direction of the threshold + required: true + type: string + fieldPath: + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + description: Json field Path as per CEF message which needs to be analyzed for TCA + required: true + type: string + severity: + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + description: Threshold Event Severity + required: true + type: string + thresholdValue: + description: Threshold value for the field Path inside CEF message + required: true + type: integer + version: + description: Version number associated with the threshold + required: true + type: string diff --git a/src/test/resources/example/sdc/service-Simsfoimap0112.csar b/src/test/resources/example/sdc/service-Simsfoimap0112.csar Binary files differnew file mode 100644 index 000000000..8c16d31ee --- /dev/null +++ b/src/test/resources/example/sdc/service-Simsfoimap0112.csar diff --git a/src/test/resources/example/sdc/service-without-policy.csar b/src/test/resources/example/sdc/service-without-policy.csar Binary files differnew file mode 100644 index 000000000..20c4eef65 --- /dev/null +++ b/src/test/resources/example/sdc/service-without-policy.csar diff --git a/src/test/resources/example/sdc/service_Vloadbalancerms_cds.csar b/src/test/resources/example/sdc/service_Vloadbalancerms_cds.csar Binary files differnew file mode 100644 index 000000000..ff337993a --- /dev/null +++ b/src/test/resources/example/sdc/service_Vloadbalancerms_cds.csar diff --git a/src/test/resources/example/sdc/service_Vloadbalancerms_no_cds.csar b/src/test/resources/example/sdc/service_Vloadbalancerms_no_cds.csar Binary files differnew file mode 100644 index 000000000..3330dd1e8 --- /dev/null +++ b/src/test/resources/example/sdc/service_Vloadbalancerms_no_cds.csar diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.file b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.file new file mode 100644 index 000000000..9e616dfea --- /dev/null +++ b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.file @@ -0,0 +1,96 @@ +{ + "blueprintName": "baseconfiguration", + "version": "1.0.0", + "workFlowData": { + "workFlowName": "resource-assignment", + "inputs": { + "resource-assignment-properties": { + "required": true, + "type": "dt-resource-assignment-properties" + } + }, + "outputs": { + "response-property": { + "type": "string", + "value": "executed" + }, + "template-properties": { + "type": "json", + "value": { + "get_attribute": [ + "resource-assignment", + "assignment-params" + ] + } + } + } + }, + "dataTypes": { + "dt-resource-assignment-properties": { + "description": "This is Dynamically generated data type for workflow activate", + "version": "1.0.0", + "metadata": null, + "attributes": null, + "properties": { + "request-id": { + "required": true, + "type": "string", + "input-param": true + }, + "service-instance-id": { + "required": true, + "type": "string", + "input-param": true + }, + "vnf-id": { + "required": true, + "type": "string" + }, + "action-name": { + "required": true, + "type": "string" + }, + "scope-type": { + "required": true, + "type": "string" + }, + "hostname": { + "required": true, + "type": "string", + "input-param": true + }, + "request-info": { + "required": true, + "type": "dt-request-info-properties", + "input-param": true + }, + "vnf_name": { + "required": true, + "type": "string" + } + }, + "constraints": null, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-request-info-properties": { + "description": "This is Dynamically generated data type for workflow activate", + "version": "1.0.0", + "metadata": null, + "attributes": null, + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + }, + "constraints": null, + "derived_from": "tosca.datatypes.Dynamic" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.header b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.file b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.file new file mode 100644 index 000000000..58975d86a --- /dev/null +++ b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.file @@ -0,0 +1,12 @@ +{ + "blueprintName": "baseconfiguration", + "version": "1.0.0", + "workflows": [ + "resource-assignment", + "activate", + "activate-restconf", + "activate-cli", + "assign-activate", + "imperative-test-wf" + ] +}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.header b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/.file new file mode 100644 index 000000000..7f5b897bf --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/.file @@ -0,0 +1,46 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.operational.common.Drools: + version: 1.0.0 + description: Operational Policy for Control Loops using the Drools PDP + derived_from: onapy.policies.controlloop.Operational + properties: + # Omitted for brevity, see Section 1 + + onap.policies.controlloop.operational.common.Apex: + version: 1.0.0 + description: Operational Policy for Control Loops using the APEX PDP + derived_from: onap.policies.controlloop.Operational + properties: + # Omitted for brevity, see Section 1 + + onap.policies.controlloop.guard.common.FrequencyLimiter: + version: 1.0.0 + description: Supports limiting the frequency of actions being taken by a Actor. + derived_from: onap.policies.controlloop.Guard + properties: + # Omitted for brevity, see Section 1 + + onap.policies.controlloop.guard.common.Blacklist: + version: 1.0.0 + description: Supports blacklist of VNF's from performing control loop actions on. + derived_from: onap.policies.controlloop.Guard + properties: + # Omitted for brevity, see Section 1 + + onap.policies.controlloop.guard.common.MinMax: + version: 1.0.0 + description: Supports Min/Max number of VF Modules + derived_from: onap.policies.controlloop.Guard + properties: + # Omitted for brevity, see Section 1 + + onap.policies.controlloop.guard.common.MinMax: + version: 2.0.0 + description: Supports Min/Max number of VF Modules + derived_from: onap.policies.controlloop.Guard + properties: + # Omitted for brevity, see Section 1 + +data_types: + # Any bespoke data types referenced by policy type definitions[] diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.file new file mode 100644 index 000000000..79e79f0fe --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.file @@ -0,0 +1,38 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.guard.Common: + derived_from: tosca.policies.Root + version: 1.0.0 + description: | + This is the base Policy Type for Guard policies that guard the execution of Operational + Policies. + properties: + actor: + type: string + description: Specifies the Actor the guard applies to. + required: true + operation: + type: string + description: Specified the operation that the actor is performing the guard applies to. + required: true + timeRange: + type: tosca.datatypes.TimeInterval + description: | + An optional range of time during the day the guard policy is valid for. + required: false + id: + type: string + description: The Control Loop id this applies to. + required: false + onap.policies.controlloop.guard.common.Blacklist: + derived_from: onap.policies.controlloop.guard.Common + type_version: 1.0.0 + version: 1.0.0 + description: Supports blacklist of entity id's from performing control loop actions on. + properties: + blacklist: + type: list + description: List of entity id's + required: true + entry_schema: + type: string
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file new file mode 100644 index 000000000..163027e46 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file @@ -0,0 +1,47 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.guard.Common: + derived_from: tosca.policies.Root + version: 1.0.0 + description: | + This is the base Policy Type for Guard policies that guard the execution of Operational + Policies. + properties: + actor: + type: string + description: Specifies the Actor the guard applies to. + required: true + operation: + type: string + description: Specified the operation that the actor is performing the guard applies to. + required: true + timeRange: + type: tosca.datatypes.TimeInterval + description: | + An optional range of time during the day the guard policy is valid for. + required: false + id: + type: string + description: The Control Loop id this applies to. + required: false + onap.policies.controlloop.guard.common.FrequencyLimiter: + derived_from: onap.policies.controlloop.guard.Common + type_version: 1.0.0 + version: 1.0.0 + description: Supports limiting the frequency of actions being taken by a Actor. + properties: + timeWindow: + type: integer + description: The time window to count the actions against. + required: true + timeUnits: + type: string + description: The units of time the window is counting. + constraints: + - valid_values: ["second", "minute", "hour", "day", "week", "month", "year"] + limit: + type: integer + description: The limit + required: true + constraints: + - greater_than: 0
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.file new file mode 100644 index 000000000..778efae9e --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.file @@ -0,0 +1,80 @@ +{ + "tosca_definitions_version": "tosca_simple_yaml_1_1_0", + "policy_types": { + "onap.policies.controlloop.guard.Common": { + "properties": { + "id": { + "name": "id", + "type": "string", + "typeVersion": "0.0.0", + "description": "The Control Loop id this applies to.", + "required": false, + "constraints": [], + "metadata": {} + }, + "actor": { + "name": "actor", + "type": "string", + "typeVersion": "0.0.0", + "description": "Specifies the Actor the guard applies to.", + "required": true, + "constraints": [], + "metadata": {} + }, + "operation": { + "name": "operation", + "type": "string", + "typeVersion": "0.0.0", + "description": "Specified the operation that the actor is performing the guard applies to.", + "required": true, + "constraints": [], + "metadata": {} + }, + "timeRange": { + "name": "timeRange", + "type": "tosca.datatypes.TimeInterval", + "typeVersion": "0.0.0", + "description": "An optional range of time during the day the guard policy is valid for.\n", + "required": false, + "constraints": [], + "metadata": {} + } + }, + "name": "onap.policies.controlloop.guard.Common", + "version": "1.0.0", + "derived_from": "tosca.policies.Root", + "metadata": {}, + "description": "This is the base Policy Type for Guard policies that guard the execution of Operational\nPolicies.\n" + }, + "onap.policies.controlloop.guard.common.MinMax": { + "properties": { + "min": { + "name": "min", + "type": "integer", + "typeVersion": "0.0.0", + "description": "The minimum instances of this entity", + "required": true, + "constraints": [], + "metadata": {} + }, + "max": { + "name": "max", + "type": "integer", + "typeVersion": "0.0.0", + "description": "The maximum instances of this entity", + "required": false, + "constraints": [], + "metadata": {} + } + }, + "name": "onap.policies.controlloop.guard.common.MinMax", + "version": "1.0.0", + "derived_from": "onap.policies.controlloop.guard.Common", + "metadata": {}, + "description": "Supports Min/Max number of entity for scaling operations" + } + }, + "name": "ToscaServiceTemplateSimple", + "version": "1.0.0", + "metadata": {} +}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.file new file mode 100644 index 000000000..78bdde746 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.file @@ -0,0 +1,40 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.guard.Common: + derived_from: tosca.policies.Root + version: 1.0.0 + description: | + This is the base Policy Type for Guard policies that guard the execution of Operational + Policies. + properties: + actor: + type: string + description: Specifies the Actor the guard applies to. + required: true + operation: + type: string + description: Specified the operation that the actor is performing the guard applies to. + required: true + timeRange: + type: tosca.datatypes.TimeInterval + description: | + An optional range of time during the day the guard policy is valid for. + required: false + id: + type: string + description: The Control Loop id this applies to. + required: false + onap.policies.controlloop.guard.common.MinMax: + derived_from: onap.policies.controlloop.guard.Common + type_version: 1.0.0 + version: 1.0.0 + description: Supports Min/Max number of entity for scaling operations + properties: + min: + type: integer + required: true + description: The minimum instances of this entity + max: + type: integer + required: false + description: The maximum instances of this entity
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.file new file mode 100644 index 000000000..14ae7acd8 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.file @@ -0,0 +1,360 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.operational.Common: + properties: + abatement: + name: abatement + type: boolean + typeVersion: 0.0.0 + description: Whether an abatement event message will be expected for + the control loop from DCAE. + default: 'false' + required: true + constraints: [ + ] + metadata: { + } + operations: + name: operations + type: list + typeVersion: 0.0.0 + description: List of operations to be performed when Control Loop + is triggered. + required: true + constraints: [ + ] + entry_schema: + type: onap.datatype.controlloop.Operation + typeVersion: 0.0.0 + constraints: [ + ] + metadata: { + } + trigger: + name: trigger + type: string + typeVersion: 0.0.0 + description: Initial operation to execute upon receiving an Onset + event message for the Control Loop. + required: true + constraints: [ + ] + metadata: { + } + timeout: + name: timeout + type: integer + typeVersion: 0.0.0 + description: | + Overall timeout for executing all the operations. This timeout should equal or exceed the total + timeout for each operation listed. + required: true + constraints: [ + ] + metadata: { + } + id: + name: id + type: string + typeVersion: 0.0.0 + description: The unique control loop id. + required: true + constraints: [ + ] + metadata: { + } + name: onap.policies.controlloop.operational.Common + version: 1.0.0 + derived_from: tosca.policies.Root + metadata: { + } + description: | + Operational Policy for Control Loop execution. Originated in Frankfurt to support TOSCA Compliant + Policy Types. This does NOT support the legacy Policy YAML policy type. + onap.policies.controlloop.operational.common.Apex: + properties: + engineServiceParameters: + name: engineServiceParameters + type: string + typeVersion: 0.0.0 + description: The engine parameters like name, instanceCount, policy + implementation, parameters etc. + required: true + constraints: [ + ] + metadata: { + } + eventOutputParameters: + name: eventOutputParameters + type: string + typeVersion: 0.0.0 + description: The event output parameters. + required: true + constraints: [ + ] + metadata: { + } + javaProperties: + name: javaProperties + type: string + typeVersion: 0.0.0 + description: Name/value pairs of properties to be set for APEX if + needed. + required: false + constraints: [ + ] + metadata: { + } + eventInputParameters: + name: eventInputParameters + type: string + typeVersion: 0.0.0 + description: The event input parameters. + required: true + constraints: [ + ] + metadata: { + } + name: onap.policies.controlloop.operational.common.Apex + version: 1.0.0 + derived_from: onap.policies.controlloop.operational.Common + metadata: { + } + description: Operational policies for Apex PDP +data_types: + onap.datatype.controlloop.Actor: + constraints: [ + ] + properties: + payload: + name: payload + type: map + typeVersion: 0.0.0 + description: Name/value pairs of payload information passed by Policy + to the actor + required: false + constraints: [ + ] + entry_schema: + type: string + typeVersion: 0.0.0 + constraints: [ + ] + metadata: + clamp_possible_values: ClampExecution:CDS/payload + target: + name: target + type: onap.datatype.controlloop.Target + typeVersion: 0.0.0 + description: The resource the operation should be performed on. + required: true + constraints: [ + ] + metadata: { + } + actor: + name: actor + type: string + typeVersion: 0.0.0 + description: The actor performing the operation. + required: true + constraints: [ + ] + metadata: + clamp_possible_values: Dictionary:DefaultActors,ClampExecution:CDS/actor + operation: + name: operation + type: string + typeVersion: 0.0.0 + description: The operation the actor is performing. + required: true + constraints: [ + ] + metadata: + clamp_possible_values: Dictionary:DefaultOperations, ClampExecution:CDS/operation + name: onap.datatype.controlloop.Actor + version: 0.0.0 + derived_from: tosca.datatypes.Root + metadata: { + } + description: An actor/operation/target definition + onap.datatype.controlloop.Operation: + constraints: [ + ] + properties: + failure_retries: + name: failure_retries + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke when the current operation + has exceeded its max retries. + default: final_failure_retries + required: false + constraints: [ + ] + metadata: { + } + id: + name: id + type: string + typeVersion: 0.0.0 + description: Unique identifier for the operation + required: true + constraints: [ + ] + metadata: { + } + failure_timeout: + name: failure_timeout + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke when the time out for + the operation occurs. + default: final_failure_timeout + required: false + constraints: [ + ] + metadata: { + } + failure: + name: failure + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke on Actor operation + failure. + default: final_failure + required: false + constraints: [ + ] + metadata: { + } + operation: + name: operation + type: onap.datatype.controlloop.Actor + typeVersion: 0.0.0 + description: The definition of the operation to be performed. + required: true + constraints: [ + ] + metadata: { + } + failure_guard: + name: failure_guard + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke when the current operation + is blocked due to guard policy enforcement. + default: final_failure_guard + required: false + constraints: [ + ] + metadata: { + } + retries: + name: retries + type: integer + typeVersion: 0.0.0 + description: The number of retries the actor should attempt to perform + the operation. + default: '0' + required: true + constraints: [ + ] + metadata: { + } + timeout: + name: timeout + type: integer + typeVersion: 0.0.0 + description: The amount of time for the actor to perform the operation. + required: true + constraints: [ + ] + metadata: { + } + failure_exception: + name: failure_exception + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke when the current operation + causes an exception. + default: final_failure_exception + required: false + constraints: [ + ] + metadata: { + } + description: + name: description + type: string + typeVersion: 0.0.0 + description: A user-friendly description of the intent for the operation + required: false + constraints: [ + ] + metadata: { + } + success: + name: success + type: string + typeVersion: 0.0.0 + description: Points to the operation to invoke on success. A value + of "final_success" indicates and end to the operation. + default: final_success + required: false + constraints: [ + ] + metadata: { + } + name: onap.datatype.controlloop.Operation + version: 0.0.0 + derived_from: tosca.datatypes.Root + metadata: { + } + description: An operation supported by an actor + onap.datatype.controlloop.Target: + constraints: [ + ] + properties: + entityIds: + name: entityIds + type: map + typeVersion: 0.0.0 + description: | + Map of values that identify the resource. If none are provided, it is assumed that the + entity that generated the ONSET event will be the target. + required: false + constraints: [ + ] + entry_schema: + type: string + typeVersion: 0.0.0 + constraints: [ + ] + metadata: + clamp_possible_values: ClampExecution:CSAR_RESOURCES + targetType: + name: targetType + type: string + typeVersion: 0.0.0 + description: Category for the target type + required: true + constraints: + - valid_values: + - VNF + - VM + - VFMODULE + - PNF + metadata: { + } + name: onap.datatype.controlloop.Target + version: 0.0.0 + derived_from: tosca.datatypes.Root + metadata: { + } + description: Definition for a entity in A&AI to perform a control loop operation + on +name: ToscaServiceTemplateSimple +version: 1.0.0 +metadata: { + } diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.file new file mode 100644 index 000000000..af7a61ef7 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.file @@ -0,0 +1,150 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.controlloop.operational.common.Drools: + derived_from: onap.policies.controlloop.operational.Common + type_version: 1.0.0 + version: 1.0.0 + description: Operational policies for Drools PDP + properties: + controllerName: + type: string + description: Drools controller properties + required: false + onap.policies.controlloop.operational.Common: + derived_from: tosca.policies.Root + version: 1.0.0 + description: | + Operational Policy for Control Loop execution. Originated in Frankfurt to support TOSCA Compliant + Policy Types. This does NOT support the legacy Policy YAML policy type. + properties: + id: + type: string + description: The unique control loop id. + required: true + timeout: + type: integer + description: | + Overall timeout for executing all the operations. This timeout should equal or exceed the total + timeout for each operation listed. + required: true + abatement: + type: boolean + description: Whether an abatement event message will be expected for the control loop from DCAE. + required: true + default: false + trigger: + type: string + description: Initial operation to execute upon receiving an Onset event message for the Control Loop. + required: true + operations: + type: list + description: List of operations to be performed when Control Loop is triggered. + required: true + entry_schema: + type: onap.datatype.controlloop.Operation +data_types: + onap.datatype.controlloop.Target: + derived_from: tosca.datatypes.Root + description: Definition for a entity in A&AI to perform a control loop operation on + properties: + targetType: + type: string + description: Category for the target type + required: true + constraints: + - valid_values: [VNF, VM, VFMODULE, PNF] + entityIds: + type: map + description: | + Map of values that identify the resource. If none are provided, it is assumed that the + entity that generated the ONSET event will be the target. + required: false + metadata: + clamp_possible_values: ClampExecution:CSAR_RESOURCES + entry_schema: + type: string + + onap.datatype.controlloop.Actor: + derived_from: tosca.datatypes.Root + description: An actor/operation/target definition + properties: + actor: + type: string + description: The actor performing the operation. + required: true + metadata: + clamp_possible_values: Dictionary:DefaultActors,ClampExecution:CDS/actor + operation: + type: string + description: The operation the actor is performing. + required: true + metadata: + clamp_possible_values: Dictionary:DefaultOperations, ClampExecution:CDS/operations + target: + type: onap.datatype.controlloop.Target + description: The resource the operation should be performed on. + required: true + payload: + type: map + description: Name/value pairs of payload information passed by Policy to the actor + required: false + metadata: + clamp_possible_values: ClampExecution:CDS/payload + entry_schema: + type: string + + onap.datatype.controlloop.Operation: + derived_from: tosca.datatypes.Root + description: An operation supported by an actor + properties: + id: + type: string + description: Unique identifier for the operation + required: true + description: + type: string + description: A user-friendly description of the intent for the operation + required: false + operation: + type: onap.datatype.controlloop.Actor + description: The definition of the operation to be performed. + required: true + timeout: + type: integer + description: The amount of time for the actor to perform the operation. + required: true + retries: + type: integer + description: The number of retries the actor should attempt to perform the operation. + required: true + default: 0 + success: + type: string + description: Points to the operation to invoke on success. A value of "final_success" indicates and end to the operation. + required: false + default: final_success + failure: + type: string + description: Points to the operation to invoke on Actor operation failure. + required: false + default: final_failure + failure_timeout: + type: string + description: Points to the operation to invoke when the time out for the operation occurs. + required: false + default: final_failure_timeout + failure_retries: + type: string + description: Points to the operation to invoke when the current operation has exceeded its max retries. + required: false + default: final_failure_retries + failure_exception: + type: string + description: Points to the operation to invoke when the current operation causes an exception. + required: false + default: final_failure_exception + failure_guard: + type: string + description: Points to the operation to invoke when the current operation is blocked due to guard policy enforcement. + required: false + default: final_failure_guard
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file new file mode 100644 index 000000000..3c17c9004 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file @@ -0,0 +1,158 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + version: 1.0.0 + description: a base policy type for all policies that govern monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: onap.datatypes.monitoring.tca_policy + description: TCA Policy JSON + required: true +data_types: + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + type: string + required: true + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + constraints: + - valid_values: + - VM + - VNF + eventName: + type: string + required: true + description: Event name to which thresholds need to be applied + policyName: + type: string + required: true + description: TCA Policy Scope Name + policyScope: + type: string + required: true + description: TCA Policy Scope + policyVersion: + type: string + required: true + description: TCA Policy Scope Version + thresholds: + type: list + required: true + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + type: string + required: true + description: Domain name to which TCA needs to be applied + default: measurementsForVfScaling + constraints: + - equal: measurementsForVfScaling + metricsPerEventName: + type: list + required: true + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + required: true + description: Closed Loop Control Name associated with the threshold + closedLoopEventStatus: + type: string + required: true + description: Closed Loop Event Status of the threshold + constraints: + - valid_values: + - ONSET + - ABATED + direction: + type: string + required: true + description: Direction of the threshold + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + fieldPath: + type: string + required: true + description: Json field Path as per CEF message which needs to be analyzed for TCA + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + severity: + type: string + required: true + description: Threshold Event Severity + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + thresholdValue: + type: integer + required: true + description: Threshold value for the field Path inside CEF message + version: + type: string + required: true + description: Version number associated with the threshold
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.header b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file new file mode 100644 index 000000000..f16f4e899 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file @@ -0,0 +1,80 @@ +{ + "groups": [ + { + "description": "This group should be used for managing all control loop related policies and pdps", + "name": "controlloop", + "pdpGroupState": "ACTIVE", + "pdpSubgroups": [ + { + "currentInstanceCount": 0, + "desiredInstanceCount": 1, + "pdpInstances": [], + "pdpType": "apex", + "policies": [], + "properties": {}, + "supportedPolicyTypes": [ + { + "name": "onap.policies.controlloop.Operational", + "version": "1.0.0" + } + ] + }, + { + "currentInstanceCount": 0, + "desiredInstanceCount": 1, + "pdpInstances": [], + "pdpType": "drools", + "policies": [], + "properties": {}, + "supportedPolicyTypes": [ + { + "name": "onap.policies.controlloop.operational.common.*", + "version": "1.0.0" + }, + { + "name": "onap.policies.controlloop.Operational", + "version": "1.0.0" + } + ] + }, + { + "currentInstanceCount": 0, + "desiredInstanceCount": 1, + "pdpInstances": [], + "pdpType": "xacml", + "policies": [], + "properties": {}, + "supportedPolicyTypes": [ + { + "name": "onap.policies.controlloop.guard.common.*", + "version": "1.0.0" + } + ] + } + ], + "properties": {} + }, + { + "description": "This group should be used for managing all monitoring related policies and pdps", + "name": "monitoring", + "pdpGroupState": "ACTIVE", + "pdpSubgroups": [ + { + "currentInstanceCount": 0, + "desiredInstanceCount": 1, + "pdpInstances": [], + "pdpType": "xacml", + "policies": [], + "properties": {}, + "supportedPolicyTypes": [ + { + "name": "onap.policies.monitoring.*", + "version": "1.0.0" + } + ] + } + ], + "properties": {} + } + ] +} diff --git a/src/test/resources/http-cache/example/policy/pap/v1/pdps/.header b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.header new file mode 100644 index 000000000..6a280d972 --- /dev/null +++ b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.header @@ -0,0 +1 @@ +{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file diff --git a/src/test/resources/http-cache/start_http_cache.sh b/src/test/resources/http-cache/start_http_cache.sh new file mode 100755 index 000000000..1f84b56f5 --- /dev/null +++ b/src/test/resources/http-cache/start_http_cache.sh @@ -0,0 +1,52 @@ +#!/bin/bash +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2018 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============================================ +# =================================================================== +# +### + +echo "Starting HTTP CACHE python script" +for i in "$@" +do +case $i in + --python_proxyaddress=*) + python_proxyaddress="--proxyaddress ${i#*=}" + echo "- Using python_proxyaddress and set it to: $python_proxyaddress" + shift # past argument=value + ;; + --http_proxyaddress=*) + export http_proxy="${i#*=}" + export https_proxy="${i#*=}" + echo "- Defining http_proxy/https_proxy env variables to: $http_proxy" + shift # past argument=value + ;; + -?|--help|-help) + echo "Usage: $(basename $0) [--http_proxyaddress=<http://proxy_address:port>] [--python_proxyaddress=<python_simulator_address:port>]" + echo "--http_proxyaddress Set the http_proxy/https_proxy in the script before running python" + echo "--python_proxyaddress <python_simulator_address:port>, like localhost:8080 and will be set as --proxyaddress, this is the adress returned by DCAE simulator response" + exit 2 + ;; +esac +done + +echo 'Installing requests packages for Python' +pip install --no-cache-dir requests +echo 'Executing the Http proxy in Cache mode only' +python -u third_party_proxy.py --port 8080 --root /usr/src/http-cache-app/data-cache $python_proxyaddress diff --git a/src/test/resources/http-cache/third_party_proxy.py b/src/test/resources/http-cache/third_party_proxy.py new file mode 100755 index 000000000..7fe316852 --- /dev/null +++ b/src/test/resources/http-cache/third_party_proxy.py @@ -0,0 +1,497 @@ +#!/usr/bin/env python2 +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2018 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============================================ +# =================================================================== +# +### + +import json +import requests +import os +import errno +import sys +import SimpleHTTPServer +import SocketServer +import argparse +import tempfile +import signal +import uuid +import shutil + +parser = argparse.ArgumentParser(description="3rd party Cache & Replay") +parser.add_argument("--username", "-u", type=str, help="Set the username for contacting 3rd party - only used for GET") +parser.add_argument("--password", "-p", type=str, help="Set the password for contacting 3rd party - only used for GET") +parser.add_argument("--root", "-r", default=tempfile.mkdtemp(), type=str, help="Root folder for the proxy cache") +parser.add_argument("--temp", "-t", default=tempfile.mkdtemp(), type=str, help="Temp folder for the generated content") +parser.add_argument("--proxy" , type=str, help="Url of the Act as a proxy. If not set, this script only uses the cache and will return a 404 if files aren't found") +parser.add_argument("--port", "-P", type=int, default="8081", help="Port on which the proxy should listen to") +parser.add_argument("--verbose", "-v", type=bool, help="Print more information in case of error") +parser.add_argument("--proxyaddress","-a", type=str, help="Address of this proxy, generally either third-party-proxy:8085 or localhost:8085 depending if started with docker-compose or not") +options = parser.parse_args() + + +PORT = options.port +HOST = options.proxy +AUTH = (options.username, options.password) +HEADERS = {'X-ECOMP-InstanceID':'CLAMP'} +CACHE_ROOT = str(options.root) +TMP_ROOT = str(options.temp) +PROXY_ADDRESS=str(options.proxyaddress) + +def signal_handler(signal_sent, frame): + global httpd + if signal_sent == signal.SIGINT: + print('Got Ctrl-C (SIGINT)') + httpd.socket.close() + httpd.shutdown() + httpd.server_close() + +class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): + def print_headers(self): + for header,value in self.headers.items(): + print("header: %s : %s" % (header, value)) + + def check_credentials(self): + pass + + def _send_content(self, header_file, content_file): + self.send_response(200) + with open(header_file, 'rb') as f: + headers = json.load(f) + for key,value in headers.items(): + if key in ('Transfer-Encoding',): + continue + self.send_header(key, value) + self.end_headers() + with open(content_file,'rb') as f: + fc = f.read() + self.wfile.write(fc) + + def _write_cache(self,cached_file_folder, header_file, content_file, response): + os.makedirs(cached_file_folder, 0777) + with open(content_file, 'w') as f: + f.write(response.raw.read()) + with open(header_file, 'w') as f: + json.dump(dict(response.raw.headers), f) + # Entry point of the code + def _get_cached_file_folder_name(self,folder): + cached_file_folder = '%s/%s' % (folder, self.path,) + print("Cached file name before escaping : %s" % cached_file_folder) + cached_file_folder = cached_file_folder.replace('<','<').replace('>','>').replace('?','?').replace('*','*').replace('\\','*').replace(':',':').replace('|','|') + print("Cached file name after escaping (used for cache storage) : %s" % cached_file_folder) + return cached_file_folder + + def _get_cached_content_file_name(self,cached_file_folder): + return "%s/.file" % (cached_file_folder,) + + def _get_cached_header_file_name(self,cached_file_folder): + return "%s/.header" % (cached_file_folder,) + + def _execute_content_generated_cases(self,http_type): + print("Testing special cases, cache files will be sent to :" +TMP_ROOT) + cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + _file_available = os.path.exists(cached_file_content) + + if self.path.startswith("/dcae-service-types?asdcResourceId=") and http_type == "GET": + if not _file_available: + print "self.path start with /dcae-service-types?asdcResourceId=, generating response json..." + uuidGenerated = str(uuid.uuid4()) + typeId = "typeId-" + uuidGenerated + typeName = "typeName-" + uuidGenerated + print "typeId generated: " + typeName + " and typeName: "+ typeId + jsonGenerated = "{\"totalCount\":1, \"items\":[{\"typeId\":\"" + typeId + "\", \"typeName\":\"" + typeName +"\"}]}" + print "jsonGenerated: " + jsonGenerated + + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/dcae-operationstatus/install") and http_type == "GET": + if not _file_available: + print "self.path start with /dcae-operationstatus/install, generating response json..." + jsonGenerated = "{\"operationType\": \"install\", \"status\": \"succeeded\"}" + print "jsonGenerated: " + jsonGenerated + + try: + os.makedirs(cached_file_folder, 0777) + except OSError as e: + if e.errno != errno.EEXIST: + raise + print(cached_file_folder+" already exists") + + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/dcae-operationstatus/uninstall") and http_type == "GET": + if not _file_available: + print "self.path start with /dcae-operationstatus/uninstall, generating response json..." + jsonGenerated = "{\"operationType\": \"uninstall\", \"status\": \"succeeded\"}" + print "jsonGenerated: " + jsonGenerated + + try: + os.makedirs(cached_file_folder, 0777) + except OSError as e: + if e.errno != errno.EEXIST: + raise + print(cached_file_folder+" already exists") + + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/sdc/v1/catalog/services/") and http_type == "POST": + if not _file_available: + print "self.path start with /sdc/v1/catalog/services/, generating response json..." + jsondata = json.loads(self.data_string) + jsonGenerated = "{\"artifactName\":\"" + jsondata['artifactName'] + "\",\"artifactType\":\"" + jsondata['artifactType'] + "\",\"artifactURL\":\"" + self.path + "\",\"artifactDescription\":\"" + jsondata['description'] + "\",\"artifactChecksum\":\"ZjJlMjVmMWE2M2M1OTM2MDZlODlmNTVmZmYzNjViYzM=\",\"artifactUUID\":\"" + str(uuid.uuid4()) + "\",\"artifactVersion\":\"1\"}" + print "jsonGenerated: " + jsonGenerated + + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/dcae-deployments/") and http_type == "PUT": + print "self.path start with /dcae-deployments/ DEPLOY, generating response json..." + #jsondata = json.loads(self.data_string) + jsonGenerated = "{\"operationType\":\"install\",\"status\":\"processing\",\"links\":{\"status\":\"http:\/\/" + PROXY_ADDRESS + "\/dcae-operationstatus/install?test=test\"}}" + print "jsonGenerated: " + jsonGenerated + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w+') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/dcae-deployments/") and http_type == "DELETE": + print "self.path start with /dcae-deployments/ UNDEPLOY, generating response json..." + #jsondata = json.loads(self.data_string) + jsonGenerated = "{\"operationType\":\"uninstall\",\"status\":\"processing\",\"links\":{\"status\":\"http:\/\/" + PROXY_ADDRESS + "\/dcae-operationstatus/uninstall?test=test\"}}" + print "jsonGenerated: " + jsonGenerated + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w+') as f: + f.write(jsonGenerated) + return True + elif (self.path.startswith("/pdp/api/") and (http_type == "PUT" or http_type == "DELETE")) or (self.path.startswith("/pdp/api/policyEngineImport") and http_type == "POST"): + print "self.path start with /pdp/api/, copying body to response ..." + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len(self.data_string)) + "\", \"Content-Type\": \""+str(self.headers['Content-Type'])+"\"}") + with open(cached_file_content, 'w+') as f: + f.write(self.data_string) + return True + elif self.path.startswith("/policy/api/v1/policytypes/") and http_type == "POST": + print "self.path start with POST new policy API /pdp/api/, copying body to response ..." + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len(self.data_string)) + "\", \"Content-Type\": \""+str(self.headers['Content-Type'])+"\"}") + with open(cached_file_content, 'w+') as f: + f.write(self.data_string) + return True + elif self.path.startswith("/policy/api/v1/policytypes/") and http_type == "DELETE": + print "self.path start with DELETE new policy API /policy/api/v1/policytypes/ ..." + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len("")) + "\", \"Content-Type\": \""+str("")+"\"}") + with open(cached_file_content, 'w+') as f: + f.write(self.data_string) + return True + elif self.path.startswith("/policy/pap/v1/pdps/policies") and http_type == "POST": + print "self.path start with POST new policy API /policy/pap/v1/pdps/ ..." + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w+') as f: + f.write("{\"Content-Length\": \"" + str(len("")) + "\", \"Content-Type\": \""+str("")+"\"}") + with open(cached_file_content, 'w+') as f: + f.write(self.data_string) + return True + elif (self.path.startswith("/policy/pap/v1/policies/deployed/")) and http_type == "GET": + print "self.path start with /policy/api/v1/policytypes/, generating response json..." + jsonGenerated = "{\"policyTypeId\": \"onap.policies.controlloop.operational\",\"policyTypeVersion\": \"1.0.0\",\"policyId\": \"OPERATIONAL_z711F_v1_0_ResourceInstanceName1_tca\"}" + print "jsonGenerated: " + jsonGenerated + if not os.path.exists(cached_file_folder): + os.makedirs(cached_file_folder, 0777) + + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(jsonGenerated)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(jsonGenerated) + return True + elif self.path.startswith("/dcae-service-types") and http_type == "GET": + if not _file_available: + self.path = "/dcae-service-types" + cached_file_folder = '%s/%s' % (TMP_ROOT, self.path) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + print "self.path start with /dcae-service-types, generating response json..." + response = "{\"links\": {\"previousLink\": {\"title\": \"string\",\"rel\": \"string\",\"uri\": \"string\",\"uriBuilder\": {},\"rels\": [\"string\"],\"params\": {\"additionalProp1\": \"string\",\"additionalProp2\": \"string\",\"additionalProp3\": \"string\"},\"type\": \"string\"},\"nextLink\": {\"title\": \"string\",\"rel\": \"string\",\"uri\": \"string\",\"uriBuilder\": {},\"rels\": [\"string\"],\"params\": {\"additionalProp1\": \"string\",\"additionalProp2\": \"string\",\"additionalProp3\": \"string\"},\"type\": \"string\"}},\"totalCount\": 1,\"items\": [{\"owner\": \"testOwner\",\"application\": \"testApplication\",\"component\": \"testComponent\",\"typeName\": \"testTypeName\",\"typeVersion\": 0,\"blueprintTemplate\": \"testBlueprintTemplate\",\"serviceIds\": [\"serviceId1\", \"serviceId2\"],\"vnfTypes\": [\"vnfType1\", \"vnfType2\"],\"serviceLocations\": [\"serviceLocation1\", \"serviceLocation2\"],\"asdcServiceId\": \"testAsdcServiceId\",\"asdcResourceId\": \"0\",\"asdcServiceURL\": \"testAsdcServiceURL\",\"typeId\": \"testtypeId\",\"selfLink\": {\"title\": \"selfLinkTitle\",\"rel\": \"selfLinkRel\",\"uri\": \"selfLinkUri\",\"uriBuilder\": {},\"rels\": [\"string\"],\"params\": {\"additionalProp1\": \"string\",\"additionalProp2\": \"string\",\"additionalProp3\": \"string\"},\"type\": \"string\"},\"created\": \"2020-01-22T09:38:15.436Z\",\"deactivated\": \"2020-01-22T09:38:15.437Z\"},{\"owner\": \"testOwner2\",\"application\": \"testApplication1\",\"component\": \"testComponent2\",\"typeName\": \"testTypeName2\",\"typeVersion\": 0,\"blueprintTemplate\": \"testBlueprintTemplate2\",\"serviceIds\": [\"serviceId3\", \"serviceId4\"],\"vnfTypes\": [\"vnfType13\", \"vnfType4\"],\"serviceLocations\": [\"serviceLocation3\", \"serviceLocation4\"],\"asdcServiceId\": \"testAsdcServiceId\",\"asdcResourceId\": \"1\",\"asdcServiceURL\": \"testAsdcServiceURL2\",\"typeId\": \"testtypeId2\",\"selfLink\": {\"title\": \"selfLinkTitle\",\"rel\": \"selfLinkRel\",\"uri\": \"selfLinkUri\",\"uriBuilder\": {},\"rels\": [\"string\"],\"params\": {\"additionalProp1\": \"string\",\"additionalProp2\": \"string\",\"additionalProp3\": \"string\"},\"type\": \"string\"},\"created\": \"2020-01-22T09:38:15.436Z\",\"deactivated\": \"2020-01-22T09:38:15.437Z\"}]}" + print "jsonGenerated: " + response + + os.makedirs(cached_file_folder, 0777) + with open(cached_file_header, 'w') as f: + f.write("{\"Content-Length\": \"" + str(len(response)) + "\", \"Content-Type\": \"application/json\"}") + with open(cached_file_content, 'w') as f: + f.write(response) + return True + else: + return False + + + def do_GET(self): + cached_file_folder = "" + cached_file_content ="" + cached_file_header="" + print("\n\n\nGot a GET request for %s " % self.path) + + self.print_headers() + self.check_credentials() + # Verify if it's a special case + is_special = self._execute_content_generated_cases("GET") + if is_special: + cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + else: + cached_file_folder = self._get_cached_file_folder_name(CACHE_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + + _file_available = os.path.exists(cached_file_content) + + if not _file_available: + print("Request for data currently not present in cache: %s" % (cached_file_folder,)) + + if not HOST: + self.send_response(404) + self.end_headers() + self.wfile.write('404 Not found, no remote HOST specified on the emulator !!!') + print("HOST value is: %s " % (options.proxy)) + return "404 Not found, no remote HOST specified on the emulator !!!" + + url = '%s%s' % (HOST, self.path) + response = requests.get(url, auth=AUTH, headers=HEADERS, stream=True) + + if response.status_code == 200: + self._write_cache(cached_file_folder, cached_file_header, cached_file_content, response) + else: + print('Error when requesting file :') + print('Requested url : %s' % (url,)) + print('Status code : %s' % (response.status_code,)) + print('Content : %s' % (response.content,)) + self.send_response(response.status_code) + self.end_headers() + self.wfile.write('404 Not found, nothing found on the remote server !!!') + return response.content + else: + print("Request for data currently present in cache: %s" % (cached_file_folder,)) + print("HOST value is: %s " % (HOST)) + + self._send_content(cached_file_header, cached_file_content) + + if self.path.startswith("/dcae-service-types?asdcResourceId="): + print "DCAE case deleting folder created " + cached_file_folder + shutil.rmtree(cached_file_folder, ignore_errors=False, onerror=None) + elif self.path.startswith("/dcae-service-types"): + print "DCAE case deleting folder created " + cached_file_folder + shutil.rmtree(cached_file_folder, ignore_errors=False, onerror=None) + else: + print "NOT in DCAE case deleting folder created " + cached_file_folder + + def do_POST(self): + cached_file_folder = "" + cached_file_content ="" + cached_file_header="" + print("\n\n\nGot a POST for %s" % self.path) + self.check_credentials() + self.data_string = self.rfile.read(int(self.headers['Content-Length'])) + print("data-string:\n %s" % self.data_string) + print("self.headers:\n %s" % self.headers) + + is_special = self._execute_content_generated_cases("POST") + if is_special: + cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + else: + cached_file_folder = self._get_cached_file_folder_name(CACHE_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + + _file_available = os.path.exists(cached_file_content) + + if not _file_available: + + if not HOST: + self.send_response(404) + self.end_headers() + self.wfile.write('404 Not found, no remote HOST specified on the emulator !!!') + return "404 Not found, no remote HOST specified on the emulator !!!" + + print("Request for data currently not present in cache: %s" % (cached_file_folder,)) + + url = '%s%s' % (HOST, self.path) + print("url: %s" % (url,)) + response = requests.post(url, data=self.data_string, headers=self.headers, stream=True) + + if response.status_code == 200: + self._write_cache(cached_file_folder, cached_file_header, cached_file_content, response) + else: + print('Error when requesting file :') + print('Requested url : %s' % (url,)) + print('Status code : %s' % (response.status_code,)) + print('Content : %s' % (response.content,)) + self.send_response(response.status_code) + self.end_headers() + self.wfile.write('404 Not found, nothing found on the remote server !!!') + return response.content + else: + print("Request for data present in cache: %s" % (cached_file_folder,)) + + self._send_content(cached_file_header, cached_file_content) + + def do_PUT(self): + cached_file_folder = "" + cached_file_content ="" + cached_file_header="" + print("\n\n\nGot a PUT for %s " % self.path) + self.check_credentials() + self.data_string = self.rfile.read(int(self.headers['Content-Length'])) + print("data-string:\n %s" % self.data_string) + print("self.headers:\n %s" % self.headers) + + is_special = self._execute_content_generated_cases("PUT") + if is_special: + cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + else: + cached_file_folder = self._get_cached_file_folder_name(CACHE_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + + _file_available = os.path.exists(cached_file_content) + + if not _file_available: + if not HOST: + self.send_response(404) + self.end_headers() + self.wfile.write('404 Not found, no remote HOST specified on the emulator !!!') + return "404 Not found, no remote HOST specified on the emulator !!!" + + print("Request for data currently not present in cache: %s" % (cached_file_folder,)) + + url = '%s%s' % (HOST, self.path) + print("url: %s" % (url,)) + response = requests.put(url, data=self.data_string, headers=self.headers, stream=True) + + if response.status_code == 200: + self._write_cache(cached_file_folder, cached_file_header, cached_file_content, response) + else: + print('Error when requesting file :') + print('Requested url : %s' % (url,)) + print('Status code : %s' % (response.status_code,)) + print('Content : %s' % (response.content,)) + self.send_response(response.status_code) + self.end_headers() + self.wfile.write('404 Not found, nothing found on the remote server !!!') + return response.content + else: + print("Request for data present in cache: %s" % (cached_file_folder,)) + + self._send_content(cached_file_header, cached_file_content) + + + def do_DELETE(self): + cached_file_folder = "" + cached_file_content ="" + cached_file_header="" + print("\n\n\nGot a DELETE for %s " % self.path) + self.check_credentials() + if self.headers.get('Content-Length') is not None: + self.data_string = self.rfile.read(int(self.headers['Content-Length'])) + else: + self.data_string = "empty generated" + print("self.headers:\n %s" % self.headers) + + is_special = self._execute_content_generated_cases("DELETE") + if is_special: + cached_file_folder = self._get_cached_file_folder_name(TMP_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + else: + cached_file_folder = self._get_cached_file_folder_name(CACHE_ROOT) + cached_file_content = self._get_cached_content_file_name(cached_file_folder) + cached_file_header = self._get_cached_header_file_name(cached_file_folder) + + _file_available = os.path.exists(cached_file_content) + + if not _file_available: + if not HOST: + self.send_response(404) + self.end_headers() + self.wfile.write('404 Not found, no remote HOST specified on the emulator !!!') + return "404 Not found, no remote HOST specified on the emulator !!!" + + print("Request for data currently not present in cache: %s" % (cached_file_folder,)) + + url = '%s%s' % (HOST, self.path) + print("url: %s" % (url,)) + response = requests.put(url, data=self.data_string, headers=self.headers, stream=True) + + if response.status_code == 200: + self._write_cache(cached_file_folder, cached_file_header, cached_file_content, response) + else: + print('Error when requesting file :') + print('Requested url : %s' % (url,)) + print('Status code : %s' % (response.status_code,)) + print('Content : %s' % (response.content,)) + self.send_response(response.status_code) + self.end_headers() + self.wfile.write('404 Not found, nothing found on the remote server !!!') + return response.content + else: + print("Request for data present in cache: %s" % (cached_file_folder,)) + + self._send_content(cached_file_header, cached_file_content) + + + +# Main code that start the HTTP server +httpd = SocketServer.ForkingTCPServer(('', PORT), Proxy) +httpd.allow_reuse_address = True +print "Listening on port "+ str(PORT) + "(Press Ctrl+C/Ctrl+Z to stop HTTPD Caching script)" +print "Caching folder " + CACHE_ROOT + ", Tmp folder for generated files " + TMP_ROOT +signal.signal(signal.SIGINT, signal_handler) +httpd.serve_forever()
\ No newline at end of file diff --git a/src/test/resources/https/https-test.properties b/src/test/resources/https/https-test.properties new file mode 100644 index 000000000..86e444efe --- /dev/null +++ b/src/test/resources/https/https-test.properties @@ -0,0 +1,130 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-2018 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============================================ +# =================================================================== +# +### + +### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time). +### (See below for the parameter 'server.http.port' if you want to have both enabled) +### To have only HTTP, keep the lines server.ssl.* commented +### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location +server.port=${clamp.it.tests.https} +### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port') +server.ssl.key-store=classpath:clds/aaf/org.onap.clamp.p12 +server.ssl.key-store-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc +server.ssl.key-store-type=PKCS12 +server.ssl.key-alias=clamp@clamp.onap.org + +# The key file used to decode the key store and trust store password +# If not defined, the key store and trust store password will not be decrypted +clamp.config.keyFile=classpath:clds/aaf/org.onap.clamp.keyfile +clamp.config.caCerts=classpath:clds/aaf/ssl/ca-certs.pem + +## Config part for Client certificates +server.ssl.client-auth=want +server.ssl.trust-store=classpath:clds/aaf/truststoreONAPall.jks +server.ssl.trust-store-password=enc:iDnPBBLq_EMidXlMa1FEuBR8TZzYxrCg66vq_XfLHdJ + +### In order to be user friendly when HTTPS is enabled, +### you can add another HTTP port that will be automatically redirected to HTTPS +### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...) +server.http-to-https-redirection.port=${clamp.it.tests.http-redirected} + +### HTTP Example: +###-------------- +### server.port=8080 + +### HTTPS Example: +### -------------- +### server.port=8443 +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass + +### HTTP (Redirected to HTTPS) and HTTPS Example: +### -------------------------------------------- +### server.port=8443 <-- The HTTPS port +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass +### server.http-to-https-redirection.port=8090 <-- The HTTP port + +server.servlet.context-path=/ +#Modified engine-rest applicationpath +spring.profiles.active=clamp-default, clamp-aaf-authentication,clamp-ssl-config + + +#clds datasource connection details +spring.datasource.driverClassName=org.mariadb.jdbc.Driver +spring.datasource.url=jdbc:mariadb:sequential://localhost:${docker.mariadb.port.host}/cldsdb4?autoReconnect=true&retriesAllDown=2147483647&failoverLoopRetries=2147483647 +spring.datasource.username=clds +spring.datasource.password=sidnnd83K +spring.datasource.validationQuery=SELECT 1 +spring.datasource.validationQueryTimeout=20000 +spring.datasource.validationInterval=30000 +spring.datasource.testWhileIdle = true +spring.datasource.minIdle = 0 +spring.datasource.initialSize=0 +# Automatically test whether a connection provided is good or not +spring.datasource.testOnBorrow=true +spring.datasource.ignoreExceptionOnPreLoad=true + +camel.springboot.consumer-template-cache-size=1000 +camel.springboot.producer-template-cache-size=1000 +# JMX enabled to have Camel Swagger runtime working +camel.springboot.jmx-enabled=true +camel.defaultthreadpool.poolsize=10 +camel.defaultthreadpool.maxpoolsize=20 +camel.defaultthreadpool.maxqueuesize=1000 +camel.defaultthreadpool.keepaliveTime=60 +camel.defaultthreadpool.rejectpolicy=CallerRuns +#camel.springboot.xmlRoutes = false +camel.springboot.xmlRoutes=classpath:/clds/camel/routes/*.xml +camel.springboot.xmlRests=classpath:/clds/camel/rest/*.xml +#camel.springboot.typeConversion = false + +#For EELF logback file +#com.att.eelf.logging.path= +com.att.eelf.logging.file=logback-default.xml +#The log folder that will be used in logback.xml file +clamp.config.log.path=log + +#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! +clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl +clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage +clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event +clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf +clamp.config.security.permission.type.template=org.onap.clamp.clds.template +clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca +#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties +clamp.config.security.permission.instance=dev +clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal + +#AAF related parameters +clamp.config.cadi.cadiLoglevel=DEBUG +clamp.config.cadi.cadiLatitude=10 +clamp.config.cadi.cadiLongitude=10 +clamp.config.cadi.aafLocateUrl=https://aaf-locate:8095 +clamp.config.cadi.oauthTokenUrl= https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.token:2.1/token +clamp.config.cadi.oauthIntrospectUrll=https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.introspect:2.1/introspect +clamp.config.cadi.aafEnv=DEV +clamp.config.cadi.aafUrl=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.service:2.1 +clamp.config.cadi.cadiX509Issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US
\ No newline at end of file diff --git a/src/test/resources/https/keystore-test.jks b/src/test/resources/https/keystore-test.jks Binary files differnew file mode 100644 index 000000000..04ad3b114 --- /dev/null +++ b/src/test/resources/https/keystore-test.jks diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 000000000..c47cab31c --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,95 @@ +<!-- Empty Configuration to prevent creating log files by Units Tests (e.g LoggingUtilsTest) ! --> +<configuration> + <jmxConfigurator /> + <!-- Example evaluator filter applied against console appender --> + <property + name="p_tim" + value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}" /> + <property + name="p_lvl" + value="%level" /> + <property + name="p_log" + value="%logger" /> + <property + name="p_mdc" + value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}" /> + <property + name="p_msg" + value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_exc" + value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_mak" + value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}" /> + <property + name="p_thr" + value="%thread" /> + <property + name="defaultPattern" + value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n" /> + <property + name="debugPattern" + value="%nopexception${p_tim}|${p_lvl}|${p_mdc}|${p_exc}|%msg%n" /> + + <!-- Example evaluator filter applied against console appender --> + <appender + name="STDOUT" + class="ch.qos.logback.core.ConsoleAppender"> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + <encoder> + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + </pattern> + </encoder> + </appender> + <logger + name="org.onap.aaf" + level="DEBUG"> + <appender-ref ref="STDOUT" /> + </logger> + <logger + name="org.apache" + level="DEBUG"> + <appender-ref ref="STDOUT" /> + </logger> + <!-- Spring related loggers --> + <logger + name="org.springframework" + level="DEBUG"> + <appender-ref ref="STDOUT" /> + </logger> + + <!-- CLDS related loggers --> + <logger + name="org.onap.clamp" + level="DEBUG"> + <appender-ref ref="STDOUT" /> + </logger> + + <!-- CLDS related loggers --> + <logger + name="com.att.eelf.error" + level="OFF"> + <appender-ref ref="STDOUT" /> + </logger> + + <logger + name="ch.qos.logback.classic" + level="INFO" > + <appender-ref ref="STDOUT" /> + </logger> + <logger + name="ch.qos.logback.core" + level="INFO" > + <appender-ref ref="STDOUT" /> + </logger> + + <!-- logback jms appenders & loggers definition ends here --> + + <root level="DEBUG"> + <appender-ref ref="STDOUT" /> + </root> +</configuration> diff --git a/src/test/resources/robotframework/Dockerfile b/src/test/resources/robotframework/Dockerfile new file mode 100644 index 000000000..4ae08208e --- /dev/null +++ b/src/test/resources/robotframework/Dockerfile @@ -0,0 +1,9 @@ +#FROM robotframework/rfdocker +# +#### Uncomment following two lines if having external test libraries: +##COPY --chown=robot:robot requirements.txt . +#RUN pip3 install --no-cache-dir -r requirements.txt +#COPY *.robot /home/robot/atest +FROM ppodgorsek/robot-framework:3.0.3 +COPY requirements.txt . +RUN pip install -r requirements.txt
\ No newline at end of file diff --git a/src/test/resources/robotframework/requirements.txt b/src/test/resources/robotframework/requirements.txt new file mode 100644 index 000000000..2ae8f4500 --- /dev/null +++ b/src/test/resources/robotframework/requirements.txt @@ -0,0 +1,6 @@ +certifi +chardet +idna +requests +urllib3 +robotframework-extendedrequestslibrary diff --git a/src/test/resources/robotframework/robotframework-test.properties b/src/test/resources/robotframework/robotframework-test.properties new file mode 100644 index 000000000..665842b84 --- /dev/null +++ b/src/test/resources/robotframework/robotframework-test.properties @@ -0,0 +1,173 @@ +### +# ============LICENSE_START======================================================= +# ONAP CLAMP +# ================================================================================ +# Copyright (C) 2017-2018 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============================================ +# =================================================================== +# +### + +### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time). +### (See below for the parameter 'server.http.port' if you want to have both enabled) +### To have only HTTP, keep the lines server.ssl.* commented +### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location +server.port=${clamp.it.tests.robotframework.http} +### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port') +#server.ssl.key-store=file:/tmp/mykey.jks +#server.ssl.key-store-password=pass +#server.ssl.key-password=pass + +### In order to be user friendly when HTTPS is enabled, +### you can add another HTTP port that will be automatically redirected to HTTPS +### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...) +#server.http-to-https-redirection.port=8090 + +### HTTP Example: +###-------------- +### server.port=8080 + +### HTTPS Example: +### -------------- +### server.port=8443 +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass + +### HTTP (Redirected to HTTPS) and HTTPS Example: +### -------------------------------------------- +### server.port=8443 <-- The HTTPS port +### server.ssl.key-store=file:/tmp/mykey.jks +### server.ssl.key-store-password=mypass +### server.ssl.key-password=mypass +### server.http-to-https-redirection.port=8090 <-- The HTTP port + +server.servlet.context-path=/ +#Modified engine-rest applicationpath +spring.profiles.active=clamp-default,clamp-default-user +spring.http.converters.preferred-json-mapper=gson + +#The max number of active threads in this pool +server.tomcat.max-threads=200 +#The minimum number of threads always kept alive +server.tomcat.min-Spare-Threads=25 +#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads +server.tomcat.max-idle-time=60000 + +#Servlet context parameters +server.context_parameters.p-name=value #context parameter with p-name as key and value as value. + +camel.springboot.consumer-template-cache-size=1000 +camel.springboot.producer-template-cache-size=1000 +# JMX enabled to have Camel Swagger runtime working +camel.springboot.jmx-enabled=true +camel.defaultthreadpool.poolsize=10 +camel.defaultthreadpool.maxpoolsize=20 +camel.defaultthreadpool.maxqueuesize=1000 +camel.defaultthreadpool.keepaliveTime=60 +camel.defaultthreadpool.rejectpolicy=CallerRuns +#camel.springboot.xmlRoutes = false +camel.springboot.xmlRoutes=classpath:/clds/camel/routes/*.xml +camel.springboot.xmlRests=classpath:/clds/camel/rest/*.xml +#camel.springboot.typeConversion = false + +#clds datasource connection details +spring.datasource.driverClassName=org.mariadb.jdbc.Driver +spring.datasource.url=jdbc:mariadb:sequential://localhost:3306,localhost:${docker.mariadb.port.host}/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3 +spring.datasource.username=clds +spring.datasource.password=sidnnd83K +spring.datasource.validationQuery=SELECT 1 +spring.datasource.validationQueryTimeout=20000 +spring.datasource.validationInterval=30000 +spring.datasource.testWhileIdle = true +spring.datasource.minIdle = 0 +spring.datasource.initialSize=0 +# Automatically test whether a connection provided is good or not +spring.datasource.testOnBorrow=true +spring.datasource.ignoreExceptionOnPreLoad=true + +spring.jpa.properties.javax.persistence.schema-generation.database.action=none +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +# disable Hibernate DDL generation because the schema will be generated from a sql script +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.ddl-auto=validate +spring.jpa.properties.hibernate.hbm2ddl.delimiter=; +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.use-new-id-generator-mappings=true + +# Whether to enable logging of SQL statements. +#spring.jpa.show-sql=true + +#Async Executor default Parameters +async.core.pool.size=10 +async.max.pool.size=20 +async.queue.capacity=500 + +#For EELF logback file +#com.att.eelf.logging.path= +clamp.config.logback.filename=logback-default.xml +#The log folder that will be used in logback.xml file +clamp.config.log.path=log +clamp.config.files.systemProperties=classpath:/system.properties +clamp.config.files.cldsUsers=classpath:/clds/clds-users.json +clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json +clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json + +# +# Configuration Settings for Policy Engine Components +clamp.config.policy.api.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.policy.api.userName=healthcheck +clamp.config.policy.api.password=zb!XztG34 +clamp.config.policy.pap.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.policy.pap.userName=healthcheck +clamp.config.policy.pap.password=zb!XztG34 + +# Sdc service properties +# +clamp.config.sdc.csarFolder = ${project.build.directory}/sdc-tests + +#DCAE Inventory Url Properties +clamp.config.dcae.inventory.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.dcae.intentory.retry.interval=100 +clamp.config.dcae.intentory.retry.limit=1 + +#DCAE Deployment Url Properties +clamp.config.dcae.deployment.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.dcae.deployment.userName=test +clamp.config.dcae.deployment.password=test + +#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case ! +clamp.config.security.permission.type.cl=permission-type-cl +clamp.config.security.permission.type.cl.manage=permission-type-cl-manage +clamp.config.security.permission.type.cl.event=permission-type-cl-event +clamp.config.security.permission.type.filter.vf=permission-type-filter-vf +clamp.config.security.permission.type.template=permission-type-template +clamp.config.security.permission.type.tosca=permission-type-tosca +#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties +clamp.config.security.permission.instance=dev +clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal + +# Configuration settings for CDS +clamp.config.cds.url=http4://localhost:${docker.http-cache.port.host} +clamp.config.cds.userName=ccsdkapps +clamp.config.cds.password=ccsdkapps + +## Tosca converter +clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json +clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml +clamp.config.tosca.converter.dictionary.support.enabled=true
\ No newline at end of file diff --git a/src/test/resources/robotframework/tests/01_healthcheck.robot b/src/test/resources/robotframework/tests/01_healthcheck.robot new file mode 100644 index 000000000..f19266781 --- /dev/null +++ b/src/test/resources/robotframework/tests/01_healthcheck.robot @@ -0,0 +1,19 @@ +*** Settings *** +Library Collections +Library RequestsLibrary +Library OperatingSystem +Library json +Library OperatingSystem +*** Variables *** +${login} admin +${passw} password +*** Keywords *** +Create the sessions +*** Test Cases *** +Get Requests health check ok + ${port} = Get Environment Variable CLAMP_PORT + ${auth}= Create List ${login} ${passw} + Create Session clamp http://localhost:${port} auth=${auth} disable_warnings=1 + Set Global Variable ${clamp_session} clamp + ${resp}= Get Request ${clamp_session} /restservices/clds/v1/healthcheck + Should Be Equal As Strings ${resp.status_code} 200
\ No newline at end of file diff --git a/src/test/resources/tosca/micro-service-policy-payload.json b/src/test/resources/tosca/micro-service-policy-payload.json new file mode 100644 index 000000000..2533a5410 --- /dev/null +++ b/src/test/resources/tosca/micro-service-policy-payload.json @@ -0,0 +1,42 @@ +{ + "tosca_definitions_version": "tosca_simple_yaml_1_0_0", + "topology_template": { + "policies": [ + { + "testPolicy": { + "type": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "type_version": "1.0.0", + "version": "1.0.0", + "metadata": { + "policy-id": "testPolicy" + }, + "properties": { + "tca_policy": { + "domain": "measurementsForVfScaling", + "metricsPerEventName": [ + { + "policyVersion": "1.0.0", + "thresholds": [ + { + "severity": "CRITICAL", + "fieldPath": "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "thresholdValue": 1, + "closedLoopEventStatus": "ONSET", + "closedLoopControlName": "test", + "version": "1.0.0", + "direction": "LESS" + } + ], + "policyName": "test", + "controlLoopSchemaType": "VM", + "policyScope": "test", + "eventName": "test" + } + ] + } + } + } + } + ] + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/micro-service-policy-properties.json b/src/test/resources/tosca/micro-service-policy-properties.json new file mode 100644 index 000000000..04fe0cc7f --- /dev/null +++ b/src/test/resources/tosca/micro-service-policy-properties.json @@ -0,0 +1,25 @@ +{ + "tca_policy": { + "domain": "measurementsForVfScaling", + "metricsPerEventName": [ + { + "policyVersion": "1.0.0", + "thresholds": [ + { + "severity": "CRITICAL", + "fieldPath": "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "thresholdValue": 1, + "closedLoopEventStatus": "ONSET", + "closedLoopControlName": "test", + "version": "1.0.0", + "direction": "LESS" + } + ], + "policyName": "test", + "controlLoopSchemaType": "VM", + "policyScope": "test", + "eventName": "test" + } + ] + } +} diff --git a/src/test/resources/tosca/model-properties-cds.json b/src/test/resources/tosca/model-properties-cds.json new file mode 100644 index 000000000..fea658431 --- /dev/null +++ b/src/test/resources/tosca/model-properties-cds.json @@ -0,0 +1,154 @@ +{ + "serviceDetails": { + "serviceType": "", + "namingPolicy": "", + "environmentContext": "General_Revenue-Bearing", + "serviceEcompNaming": "true", + "serviceRole": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "30ec5b59-4799-48d8-ac5f-1058a6b0e48f", + "ecompGeneratedNaming": "true", + "category": "Network L4+", + "type": "Service", + "UUID": "63cac700-ab9a-4115-a74f-7eac85e3fce0", + "instantiationType": "A-la-carte" + }, + "resourceDetails": { + "CP": {}, + "VL": {}, + "VF": { + "vLoadBalancerMS 0": { + "resourceVendor": "Test", + "resourceVendorModelNumber": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "subcategory": "Load Balancer", + "category": "Application L4+", + "type": "VF", + "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6", + "version": "1.0", + "resourceVendorRelease": "1.0", + "customizationUUID": "465246dc-7748-45f4-a013-308d92922552", + "controllerProperties": { + "sdnc_model_name": "baseconfiguration", + "sdnc_model_version": "1.0.0", + "workflows": { + "resource-assignment": { + "inputs": { + "template-prefix": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "template-prefix-with-complex-type": { + "type": "list", + "properties": { + "prefix-id": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + } + }, + "resource-assignment-properties": { + "type": "object", + "properties": { + "private1-prefix-id": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + } + } + } + } + } + } + } + } + }, + "CR": {}, + "VFC": {}, + "PNF": {}, + "Service": {}, + "CVFC": {}, + "Service Proxy": {}, + "Configuration": {}, + "AllottedResource": {}, + "VFModule": { + "Vloadbalancerms..vpkg..module-1": { + "vfModuleModelInvariantUUID": "ca052563-eb92-4b5b-ad41-9111768ce043", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vpkg..module-1", + "vfModuleModelUUID": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "vfModuleModelCustomizationUUID": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "min_vf_module_instances": 0, + "vf_module_label": "vpkg", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..vdns..module-3": { + "vfModuleModelInvariantUUID": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vdns..module-3", + "vfModuleModelUUID": "4fa73b49-8a6c-493e-816b-eb401567b720", + "vfModuleModelCustomizationUUID": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "min_vf_module_instances": 0, + "vf_module_label": "vdns", + "max_vf_module_instances": 50, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..base_template..module-0": { + "vfModuleModelInvariantUUID": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..base_template..module-0", + "vfModuleModelUUID": "63734409-f745-4e4d-a38b-131638a0edce", + "vfModuleModelCustomizationUUID": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "min_vf_module_instances": 1, + "vf_module_label": "base_template", + "max_vf_module_instances": 1, + "vf_module_type": "Base", + "isBase": true, + "initial_count": 1, + "volume_group": false + }, + "Vloadbalancerms..vlb..module-2": { + "vfModuleModelInvariantUUID": "a772a1f4-0064-412c-833d-4749b15828dd", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vlb..module-2", + "vfModuleModelUUID": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "vfModuleModelCustomizationUUID": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "min_vf_module_instances": 0, + "vf_module_label": "vlb", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/model-properties-operational-policy.json b/src/test/resources/tosca/model-properties-operational-policy.json new file mode 100644 index 000000000..2a6568528 --- /dev/null +++ b/src/test/resources/tosca/model-properties-operational-policy.json @@ -0,0 +1,353 @@ +{ + "serviceDetails": { + "serviceType": "", + "namingPolicy": "", + "environmentContext": "General_Revenue-Bearing", + "serviceEcompNaming": "true", + "serviceRole": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "30ec5b59-4799-48d8-ac5f-1058a6b0e48f", + "ecompGeneratedNaming": "true", + "category": "Network L4+", + "type": "Service", + "UUID": "63cac700-ab9a-4115-a74f-7eac85e3fce0", + "instantiationType": "A-la-carte" + }, + "resourceDetails": { + "CP": { + }, + "VL": { + }, + "VF": { + "vLoadBalancerMS 0": { + "resourceVendor": "Test", + "resourceVendorModelNumber": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "subcategory": "Load Balancer", + "category": "Application L4+", + "type": "VF", + "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6", + "version": "1.0", + "resourceVendorRelease": "1.0", + "customizationUUID": "465246dc-7748-45f4-a013-308d92922552", + "controllerProperties": { + "sdnc_model_name": "baseconfiguration", + "sdnc_model_version": "1.0.0", + "workflows": { + "resource-assignment": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate": { + "inputs": { + "activate-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-restconf": { + "inputs": { + "activate-restconf-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-cli": { + "inputs": { + "activate-cli-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "assign-activate": { + "inputs": { + "assign-activate-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "imperative-test-wf": { + "inputs": { + "imperative-test-wf-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + } + } + } + } + }, + "CR": { + }, + "VFC": { + }, + "PNF": { + }, + "Service": { + }, + "CVFC": { + }, + "Service Proxy": { + }, + "Configuration": { + }, + "AllottedResource": { + }, + "VFModule": { + "Vloadbalancerms..vpkg..module-1": { + "vfModuleModelInvariantUUID": "ca052563-eb92-4b5b-ad41-9111768ce043", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vpkg..module-1", + "vfModuleModelUUID": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "vfModuleModelCustomizationUUID": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "min_vf_module_instances": 0, + "vf_module_label": "vpkg", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..vdns..module-3": { + "vfModuleModelInvariantUUID": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vdns..module-3", + "vfModuleModelUUID": "4fa73b49-8a6c-493e-816b-eb401567b720", + "vfModuleModelCustomizationUUID": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "min_vf_module_instances": 0, + "vf_module_label": "vdns", + "max_vf_module_instances": 50, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..base_template..module-0": { + "vfModuleModelInvariantUUID": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..base_template..module-0", + "vfModuleModelUUID": "63734409-f745-4e4d-a38b-131638a0edce", + "vfModuleModelCustomizationUUID": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "min_vf_module_instances": 1, + "vf_module_label": "base_template", + "max_vf_module_instances": 1, + "vf_module_type": "Base", + "isBase": true, + "initial_count": 1, + "volume_group": false + }, + "Vloadbalancerms..vlb..module-2": { + "vfModuleModelInvariantUUID": "a772a1f4-0064-412c-833d-4749b15828dd", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vlb..module-2", + "vfModuleModelUUID": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "vfModuleModelCustomizationUUID": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "min_vf_module_instances": 0, + "vf_module_label": "vlb", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/model-properties.json b/src/test/resources/tosca/model-properties.json new file mode 100644 index 000000000..1c0fe24b4 --- /dev/null +++ b/src/test/resources/tosca/model-properties.json @@ -0,0 +1,353 @@ +{ + "serviceDetails": { + "serviceType": "", + "namingPolicy": "", + "environmentContext": "General_Revenue-Bearing", + "serviceEcompNaming": "true", + "serviceRole": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "30ec5b59-4799-48d8-ac5f-1058a6b0e48f", + "ecompGeneratedNaming": "true", + "category": "Network L4+", + "type": "Service", + "UUID": "63cac700-ab9a-4115-a74f-7eac85e3fce0", + "instantiationType": "A-la-carte" + }, + "resourceDetails": { + "CP": { + }, + "VL": { + }, + "VF": { + "vLoadBalancerMS 0": { + "resourceVendor": "Test", + "resourceVendorModelNumber": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "subcategory": "Load Balancer", + "category": "Application L4+", + "type": "VF", + "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6", + "version": "1.0", + "resourceVendorRelease": "1.0", + "customizationUUID": "465246dc-7748-45f4-a013-308d92922552", + "controllerProperties": { + "sdnc_model_name": "baseconfiguration", + "sdnc_model_version": "1.0.0", + "workflows": { + "resource-assignment": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-restconf": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-cli": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "assign-activate": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "imperative-test-wf": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + } + } + } + } + }, + "CR": { + }, + "VFC": { + }, + "PNF": { + }, + "Service": { + }, + "CVFC": { + }, + "Service Proxy": { + }, + "Configuration": { + }, + "AllottedResource": { + }, + "VFModule": { + "Vloadbalancerms..vpkg..module-1": { + "vfModuleModelInvariantUUID": "ca052563-eb92-4b5b-ad41-9111768ce043", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vpkg..module-1", + "vfModuleModelUUID": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "vfModuleModelCustomizationUUID": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "min_vf_module_instances": 0, + "vf_module_label": "vpkg", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..vdns..module-3": { + "vfModuleModelInvariantUUID": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vdns..module-3", + "vfModuleModelUUID": "4fa73b49-8a6c-493e-816b-eb401567b720", + "vfModuleModelCustomizationUUID": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "min_vf_module_instances": 0, + "vf_module_label": "vdns", + "max_vf_module_instances": 50, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..base_template..module-0": { + "vfModuleModelInvariantUUID": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..base_template..module-0", + "vfModuleModelUUID": "63734409-f745-4e4d-a38b-131638a0edce", + "vfModuleModelCustomizationUUID": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "min_vf_module_instances": 1, + "vf_module_label": "base_template", + "max_vf_module_instances": 1, + "vf_module_type": "Base", + "isBase": true, + "initial_count": 1, + "volume_group": false + }, + "Vloadbalancerms..vlb..module-2": { + "vfModuleModelInvariantUUID": "a772a1f4-0064-412c-833d-4749b15828dd", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vlb..module-2", + "vfModuleModelUUID": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "vfModuleModelCustomizationUUID": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "min_vf_module_instances": 0, + "vf_module_label": "vlb", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/new-converter/constraints.yaml b/src/test/resources/tosca/new-converter/constraints.yaml new file mode 100644 index 000000000..7a94ca965 --- /dev/null +++ b/src/test/resources/tosca/new-converter/constraints.yaml @@ -0,0 +1,60 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0
+policy_types:
+ onap.policies.controlloop.operational.common.Drools:
+ derived_from: onap.policies.controlloop.operational.Common
+ type_version: 1.0.0
+ version: 1.0.0
+ description: Operational policies for Drools PDP
+ properties:
+ controllerName:
+ type: String
+ description: Drools controller properties
+ required: true
+data_types:
+ onap.datatype.controlloop.Operation:
+ derived_from: tosca.datatypes.Root
+ description: An operation supported by an actor
+ properties:
+ id:
+ type: String
+ description: Unique identifier for the operation
+ required: true
+ constraints:
+ - length: 8
+ description:
+ type: Array
+ description: A user-friendly description of the intent for the operation
+ required: false
+ constraints:
+ - min_length: 5
+ - max_length: 7
+ test:
+ type: Integer
+ description: |
+ Overall timeout for executing all the operations. This timeout should equal or exceed the total
+ timeout for each operation listed.
+ required: true
+ constraints:
+ - greater_than: 7
+ - greater_or_equal: 1
+ - less_than: 7
+ - less_or_equal: 1
+ timeout:
+ type: Integer
+ description: The amount of time for the actor to perform the operation.
+ required: true
+ constraints:
+ - valid_values: [3,4,5.5,6,10]
+ retries:
+ type: Integer
+ description: The number of retries the actor should attempt to perform the operation.
+ required: true
+ default: 0
+ constraints:
+ - equal: 5
+ success:
+ type: String
+ description: Points to the operation to invoke on success. A value of "final_success" indicates and end to the operation.
+ required: false
+ constraints:
+ - valid_values: [VALID,TERMINATED]
diff --git a/src/test/resources/tosca/new-converter/sampleOperationalPolicies.yaml b/src/test/resources/tosca/new-converter/sampleOperationalPolicies.yaml new file mode 100644 index 000000000..c2afeccdc --- /dev/null +++ b/src/test/resources/tosca/new-converter/sampleOperationalPolicies.yaml @@ -0,0 +1,160 @@ +
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+policy_types:
+ onap.policies.controlloop.operational.Common:
+ derived_from: tosca.policies.Root
+ version: 1.0.0
+ description: Operational Policy for Control Loop execution
+ properties:
+ id:
+ type: String
+ description: The unique control loop id.
+ required: true
+ timeout:
+ type: Integer
+ description: |
+ Overall timeout for executing all the operations. This timeout should equal or exceed the total
+ timeout for each operation listed.
+ required: true
+ abatement:
+ type: Boolean
+ description: Whether an abatement event message will be expected for the control loop from DCAE.
+ required: true
+ default: false
+ trigger:
+ type: String
+ description: Initial operation to execute upon receiving an Onset event message for the Control Loop.
+ required: true
+ operations:
+ type: List
+ description: List of operations to be performed when Control Loop is triggered.
+ required: true
+ entry_schema:
+ type: onap.datatype.controlloop.Operation
+ onap.policies.controlloop.operational.common.Drools:
+ derived_from: onap.policies.controlloop.operational.Common
+ type_version: 1.0.0
+ version: 1.0.0
+ description: Operational policies for Drools PDP
+ properties:
+ controllerName:
+ type: String
+ description: Drools controller properties
+ required: false
+data_types:
+ # TBD if this is needed
+ onap.datatype.controlloop.operation.Failure:
+ derived_from: tosca.datatypes.Root
+ description: Captures information of an operational failure performed for control loop
+ properties:
+ messages:
+ type: String
+ description: error message
+ required: true
+ category:
+ type: String
+ description: |
+ The category the error occurred in. Whether this is a general error from the actor, or the operation
+ timed out, retries were exhausted in trying to execute the operation, a guard policy prevented the
+ operation from occuring, or an exception in the system caused the failure.
+ constraints:
+ - valid_values: [error, timeout, retries, guard, exception]
+ onap.datatype.controlloop.Target:
+ derived_from: tosca.datatypes.Root
+ description: Definition for a entity in A&AI to perform a control loop operation on
+ properties:
+ targetType:
+ type: String
+ description: Category for the target type
+ required: true
+ constraints:
+ - valid_values: [VNF, VM, VFMODULE, PNF]
+ entityIds:
+ type: Map
+ description: |
+ Map of values that identify the resource. If none are provided, it is assumed that the
+ entity that generated the ONSET event will be the target.
+ required: false
+ entry_schema:
+ type: String
+ onap.datatype.controlloop.Actor:
+ derived_from: tosca.datatypes.Root
+ description: An actor/operation/target definition
+ properties:
+ actor:
+ type: String
+ description: The actor performing the operation.
+ required: true
+ operation:
+ type: String
+ description: The operation the actor is performing.
+ required: true
+ target:
+ type: String
+ description: The resource the operation should be performed on.
+ required: true
+ metadata:
+ clamp_possible_values: <string:see clamp project for syntax>
+ payload:
+ type: Map
+ description: Name/value pairs of payload information passed by Policy to the actor
+ required: false
+ entry_schema:
+ type: String
+ onap.datatype.controlloop.Operation:
+ derived_from: tosca.datatypes.Root
+ description: An operation supported by an actor
+ properties:
+ id:
+ type: String
+ description: Unique identifier for the operation
+ required: true
+ description:
+ type: String
+ description: A user-friendly description of the intent for the operation
+ required: false
+ operation:
+ type: onap.datatype.controlloop.Actor
+ description: The definition of the operation to be performed.
+ required: true
+ metadata:
+ clamp_possible_values: <string:see clamp project for syntax>
+ timeout:
+ type: Integer
+ description: The amount of time for the actor to perform the operation.
+ required: true
+ retries:
+ type: Integer
+ description: The number of retries the actor should attempt to perform the operation.
+ required: true
+ default: 0
+ success:
+ type: String
+ description: Points to the operation to invoke on success. A value of "final_success" indicates and end to the operation.
+ required: false
+ default: final_success
+ failure:
+ type: String
+ description: Points to the operation to invoke on Actor operation failure.
+ required: false
+ default: final_failure
+ failure_timeout:
+ type: String
+ description: Points to the operation to invoke when the time out for the operation occurs.
+ required: false
+ default: final_failure_timeout
+ failure_retries:
+ type: String
+ description: Points to the operation to invoke when the current operation has exceeded its max retries.
+ required: false
+ default: final_failure_retries
+ failure_exception:
+ type: String
+ description: Points to the operation to invoke when the current operation causes an exception.
+ required: false
+ default: final_failure_exception
+ failure_guard:
+ type: String
+ description: Points to the operation to invoke when the current operation is blocked due to guard policy enforcement.
+ required: false
+ default: final_failure_guard
diff --git a/src/test/resources/tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml b/src/test/resources/tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml new file mode 100644 index 000000000..780acadc2 --- /dev/null +++ b/src/test/resources/tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml @@ -0,0 +1,174 @@ + +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.controlloop.operational.Common: + derived_from: onap.datatype.controlloop.operation.Failure + version: 1.0.0 + description: Operational Policy for Control Loop execution + properties: + id: + type: String + description: The unique control loop id. + required: true + timeout: + type: Integer + description: | + Overall timeout for executing all the operations. This timeout should equal or exceed the total + timeout for each operation listed. + required: true + constraints: + - valid_values: [1, 2, 5] + - equal: 5 + - greater_than: 7 + - greater_or_equal: 1 + - less_than: 7 + - less_or_equal: 1 + abatement: + type: Boolean + description: Whether an abatement event message will be expected for the control loop from DCAE. + required: true + default: false + trigger: + type: String + description: Initial operation to execute upon receiving an Onset event message for the Control Loop. + required: true + operations: + type: List + description: List of operations to be performed when Control Loop is triggered. + required: true + entry_schema: + type: onap.datatype.controlloop.Operation + onap.policies.controlloop.operational.common.Drools: + derived_from: onap.policies.controlloop.operational.Common + type_version: 1.0.0 + version: 1.0.0 + description: Operational policies for Drools PDP + properties: + controllerName: + type: String + description: Drools controller properties + required: true +data_types: + # TBD if this is needed + onap.datatype.controlloop.operation.Failure: + derived_from: onap.datatype.controlloop.Target + description: Captures information of an operational failure performed for control loop + properties: + messages: + type: String + description: error message + required: true + category: + type: String + description: | + The category the error occurred in. Whether this is a general error from the actor, or the operation + timed out, retries were exhausted in trying to execute the operation, a guard policy prevented the + operation from occuring, or an exception in the system caused the failure. + constraints: + - valid_values: [error, timeout, retries, guard, exception] + onap.datatype.controlloop.Target: + derived_from: tosca.datatypes.Root + description: Definition for a entity in A&AI to perform a control loop operation on + properties: + targetType: + type: String + description: Category for the target type + required: true + constraints: + - valid_values: [VNF, VM, VFMODULE, PNF] + entityIds: + type: Map + description: | + Map of values that identify the resource. If none are provided, it is assumed that the + entity that generated the ONSET event will be the target. + required: false + entry_schema: + type: String + onap.datatype.controlloop.Actor: + derived_from: tosca.datatypes.Root + description: An actor/operation/target definition + properties: + actor: + type: String + description: The actor performing the operation. + required: true + default: [1,"String",5.5,true] + operation: + type: String + description: The operation the actor is performing. + required: true + target: + type: String + description: The resource the operation should be performed on. + required: true + metadata: + clamp_possible_values: <string:see clamp project for syntax> + payload: + type: Map + description: Name/value pairs of payload information passed by Policy to the actor + required: false + entry_schema: + type: String + onap.datatype.controlloop.Operation: + derived_from: tosca.datatypes.Root + description: An operation supported by an actor + properties: + id: + type: String + description: Unique identifier for the operation + required: true + description: + type: Array + description: A user-friendly description of the intent for the operation + required: false + constraints: + - min_length: 5 + - max_length: 7 + - length: 1 + operation: + type: onap.datatype.controlloop.Actor + description: The definition of the operation to be performed. + required: true + metadata: + clamp_possible_values: <string:see clamp project for syntax> + timeout: + type: Integer + description: The amount of time for the actor to perform the operation. + required: true + constraints: + - valid_values: [3, 4, 5.5, 6, 10] + retries: + type: Integer + description: The number of retries the actor should attempt to perform the operation. + required: true + default: 0 + success: + type: String + description: Points to the operation to invoke on success. A value of "final_success" indicates and end to the operation. + required: false + default: final_success + failure: + type: String + description: Points to the operation to invoke on Actor operation failure. + required: false + default: final_failure + failure_timeout: + type: String + description: Points to the operation to invoke when the time out for the operation occurs. + required: false + default: final_failure_timeout + failure_retries: + type: String + description: Points to the operation to invoke when the current operation has exceeded its max retries. + required: false + default: final_failure_retries + failure_exception: + type: String + description: Points to the operation to invoke when the current operation causes an exception. + required: false + default: final_failure_exception + failure_guard: + type: String + description: Points to the operation to invoke when the current operation is blocked due to guard policy enforcement. + required: false + default: final_failure_guard diff --git a/src/test/resources/tosca/new-converter/tca-with-metadata.json b/src/test/resources/tosca/new-converter/tca-with-metadata.json new file mode 100644 index 000000000..3a700c8ee --- /dev/null +++ b/src/test/resources/tosca/new-converter/tca-with-metadata.json @@ -0,0 +1,224 @@ +{ + "title": "onap.policies.monitoring.cdap.tca.hi.lo.app", + "type": "object", + "required": [], + "properties": { + "tca_policy": { + "type": "object", + "description": "TCA Policy JSON", + "properties": { + "onap.datatypes.monitoring.tca_policy": { + "title": "onap.datatypes.monitoring.tca_policy", + "type": "object", + "required": [ + "domain", + "metricsPerEventName" + ], + "properties": { + "domain": { + "type": "string", + "description": "Domain name to which TCA needs to be applied", + "default": "measurementsForVfScaling", + "const": "measurementsForVfScaling" + }, + "metricsPerEventName": { + "type": "array", + "description": "Contains eventName and threshold details that need to be applied to given eventName", + "items": { + "title": "onap.datatypes.monitoring.metricsPerEventName", + "type": "object", + "required": [ + "controlLoopSchemaType", + "eventName", + "policyName", + "policyScope", + "policyVersion", + "thresholds", + "context", + "signature" + ], + "properties": { + "controlLoopSchemaType": { + "type": "string", + "description": "Specifies Control Loop Schema Type for the event Name e.g. VNF, VM", + "enum": [ + "VM", + "VNF" + ] + }, + "eventName": { + "type": "string", + "description": "Event name to which thresholds need to be applied" + }, + "policyName": { + "type": "string", + "description": "TCA Policy Scope Name" + }, + "policyScope": { + "type": "string", + "description": "TCA Policy Scope" + }, + "policyVersion": { + "type": "string", + "description": "TCA Policy Scope Version" + }, + "thresholds": { + "type": "array", + "description": "Thresholds associated with eventName", + "items": { + "title": "onap.datatypes.monitoring.thresholds", + "type": "object", + "required": [ + "closedLoopControlName", + "closedLoopEventStatus", + "direction", + "fieldPath", + "severity", + "thresholdValue", + "version" + ], + "properties": { + "closedLoopControlName": { + "type": "string", + "description": "Closed Loop Control Name associated with the threshold" + }, + "closedLoopEventStatus": { + "type": "string", + "description": "Closed Loop Event Status of the threshold", + "enum": [ + "ONSET", + "ABATED" + ] + }, + "direction": { + "type": "string", + "description": "Direction of the threshold", + "enum": [ + "LESS", + "LESS_OR_EQUAL", + "GREATER", + "GREATER_OR_EQUAL", + "EQUAL" + ] + }, + "fieldPath": { + "type": "string", + "description": "Json field Path as per CEF message which needs to be analyzed for TCA", + "enum": [ + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage", + "$.event.measurementsForVfScalingFields.meanRequestLatency", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed", + "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value" + ] + }, + "severity": { + "type": "string", + "description": "Threshold Event Severity", + "enum": [ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "thresholdValue": { + "type": "integer", + "description": "Threshold value for the field Path inside CEF message" + }, + "version": { + "type": "string", + "description": "Version number associated with the threshold" + } + } + }, + "format": "tabs-top" + }, + "context": { + "type": "string", + "description": "TCA Policy Dummy Context", + "enum": [ + "PROD" + ], + "options": { + "enum_titles": [ + "PROD" + ] + } + }, + "signature": { + "title": "onap.datatypes.monitoring.Dummy_Signature", + "type": "object", + "required": [ + "filter_clause" + ], + "properties": { + "filter_clause": { + "type": "qbldr", + "description": "Filter Clause", + "minLength": 1, + "qschema": { + "filters": [ + { + "type": "string", + "minLength": 1, + "id": "alarmCondition", + "label": "alarmCondition", + "operators": [ + "equals" + ] + } + ] + } + } + } + } + } + }, + "format": "tabs-top" + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/new-converter/tosca_apex_with_metadata.json b/src/test/resources/tosca/new-converter/tosca_apex_with_metadata.json new file mode 100644 index 000000000..4519d5c9f --- /dev/null +++ b/src/test/resources/tosca/new-converter/tosca_apex_with_metadata.json @@ -0,0 +1,577 @@ +{ + "title": "onap.policies.controlloop.operational.common.Apex", + "type": "object", + "description": "Operational policies for Apex PDP", + "required": [ + "abatement", + "operations", + "trigger", + "timeout", + "id", + "engineServiceParameters", + "eventOutputParameters", + "eventInputParameters" + ], + "properties": { + "abatement": { + "type": "boolean", + "description": "Whether an abatement event message will be expected for the control loop from DCAE.", + "default": "false" + }, + "operations": { + "type": "array", + "description": "List of operations to be performed when Control Loop is triggered.", + "items": { + "title": "onap.datatype.controlloop.Operation", + "type": "object", + "description": "An operation supported by an actor", + "required": [ + "id", + "operation", + "retries", + "timeout" + ], + "properties": { + "failure_retries": { + "type": "string", + "description": "Points to the operation to invoke when the current operation has exceeded its max retries.", + "default": "final_failure_retries" + }, + "id": { + "type": "string", + "description": "Unique identifier for the operation" + }, + "failure_timeout": { + "type": "string", + "description": "Points to the operation to invoke when the time out for the operation occurs.", + "default": "final_failure_timeout" + }, + "failure": { + "type": "string", + "description": "Points to the operation to invoke on Actor operation failure.", + "default": "final_failure" + }, + "operation": { + "title": "onap.datatype.controlloop.Actor", + "type": "object", + "description": "An actor/operation/target definition", + "required": [ + "target", + "actor", + "operation" + ], + "properties": { + "payload": { + "type": "object", + "description": "Name/value pairs of payload information passed by Policy to the actor", + "anyOf": [ + { + "title": "User defined", + "properties": {} + }, + { + "title": "resource-assignment", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + }, + { + "title": "activate", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + }, + { + "title": "activate-restconf", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + }, + { + "title": "activate-cli", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + }, + { + "title": "assign-activate", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + }, + { + "title": "imperative-test-wf", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": true + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": true + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async", + "readOnly": false + }, + "data": { + "title": "data", + "type": "string", + "format": "textarea", + "default": "{\"request-id\":\"\",\"service-instance-id\":\"\",\"hostname\":\"\",\"request-info\":{\"prop1\":\"\",\"prop2\":\"\"}}" + } + } + } + ] + }, + "target": { + "title": "onap.datatype.controlloop.Target", + "type": "object", + "description": "Definition for a entity in A&AI to perform a control loop operation on", + "required": [ + "targetType" + ], + "properties": { + "entityIds": { + "type": "object", + "description": "Map of values that identify the resource. If none are provided, it is assumed that the\nentity that generated the ONSET event will be the target.\n", + "anyOf": [ + { + "title": "User defined", + "properties": {} + }, + { + "title": "VNF-vLoadBalancerMS 0", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vpkg..module-1", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "ca052563-eb92-4b5b-ad41-9111768ce043", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vdns..module-3", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "4fa73b49-8a6c-493e-816b-eb401567b720", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..base_template..module-0", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "63734409-f745-4e4d-a38b-131638a0edce", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vlb..module-2", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "a772a1f4-0064-412c-833d-4749b15828dd", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "readOnly": "True" + } + } + } + ] + }, + "targetType": { + "type": "string", + "description": "Category for the target type", + "enum": [ + "VNF", + "VM", + "VFMODULE", + "PNF" + ] + } + } + }, + "actor": { + "type": "string", + "description": "The actor performing the operation.", + "enum": [ + "SDNR", + "SDNC", + "VFC", + "SO", + "APPC", + "CDS" + ], + "options": { + "enum_titles": [ + "SDNR", + "SDNC", + "VFC", + "SO", + "APPC" + ] + } + }, + "operation": { + "type": "string", + "description": "The operation the actor is performing.", + "enum": [ + "BandwidthOnDemand", + "VF Module Delete", + "Reroute", + "VF Module Create", + "ModifyConfig", + "Rebuild", + "Restart", + "Migrate", + "Health-Check", + "resource-assignment", + "activate", + "activate-restconf", + "activate-cli", + "assign-activate", + "imperative-test-wf" + ], + "options": { + "enum_titles": [ + "BandwidthOnDemand (SDNC operation)", + "VF Module Delete (SO operation)", + "Reroute (SDNC operation)", + "VF Module Create (SO operation)", + "ModifyConfig (APPC/VFC operation)", + "Rebuild (APPC operation)", + "Restart (APPC operation)", + "Migrate (APPC operation)", + "Health-Check (APPC operation)", + "resource-assignment (CDS operation)", + "activate (CDS operation)", + "activate-restconf (CDS operation)", + "activate-cli (CDS operation)", + "assign-activate (CDS operation)", + "imperative-test-wf (CDS operation)" + ] + } + } + } + }, + "failure_guard": { + "type": "string", + "description": "Points to the operation to invoke when the current operation is blocked due to guard policy enforcement.", + "default": "final_failure_guard" + }, + "retries": { + "type": "integer", + "description": "The number of retries the actor should attempt to perform the operation.", + "default": "0" + }, + "timeout": { + "type": "integer", + "description": "The amount of time for the actor to perform the operation." + }, + "failure_exception": { + "type": "string", + "description": "Points to the operation to invoke when the current operation causes an exception.", + "default": "final_failure_exception" + }, + "description": { + "type": "string", + "description": "A user-friendly description of the intent for the operation" + }, + "success": { + "type": "string", + "description": "Points to the operation to invoke on success. A value of \"final_success\" indicates and end to the operation.", + "default": "final_success" + } + } + }, + "format": "tabs-top" + }, + "trigger": { + "type": "string", + "description": "Initial operation to execute upon receiving an Onset event message for the Control Loop." + }, + "timeout": { + "type": "integer", + "description": "Overall timeout for executing all the operations. This timeout should equal or exceed the total\ntimeout for each operation listed.\n" + }, + "id": { + "type": "string", + "description": "The unique control loop id." + }, + "engineServiceParameters": { + "type": "string", + "description": "The engine parameters like name, instanceCount, policy implementation, parameters etc." + }, + "eventOutputParameters": { + "type": "string", + "description": "The event output parameters." + }, + "javaProperties": { + "type": "string", + "description": "Name/value pairs of properties to be set for APEX if needed." + }, + "eventInputParameters": { + "type": "string", + "description": "The event input parameters." + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/new-converter/tosca_metadata_clamp_possible_values.yaml b/src/test/resources/tosca/new-converter/tosca_metadata_clamp_possible_values.yaml new file mode 100644 index 000000000..7fe9d5398 --- /dev/null +++ b/src/test/resources/tosca/new-converter/tosca_metadata_clamp_possible_values.yaml @@ -0,0 +1,184 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: map + description: TCA Policy JSON + entry_schema: + type: onap.datatypes.monitoring.tca_policy + metadata: + policy_model_type: onap.policies.monitoring.cdap.tca.hi.lo.app + acronym: tca + +data_types: + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + type: string + required: true + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + constraints: + - valid_values: + - VM + - VNF + eventName: + type: string + required: true + description: Event name to which thresholds need to be applied + policyName: + type: string + required: true + description: TCA Policy Scope Name + policyScope: + type: string + required: true + description: TCA Policy Scope + policyVersion: + type: string + required: true + description: TCA Policy Scope Version + thresholds: + type: list + required: true + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + context: + type: string + required: true + description: TCA Policy Dummy Context + metadata: + clamp_possible_values: Dictionary:Context + + signature: + type: onap.datatypes.monitoring.Dummy_Signature + description: Signature + required: true + + onap.datatypes.monitoring.Dummy_Signature: + derived_from: tosca.datatypes.Root + properties: + filter_clause: + type: string + description: Filter Clause + required: true + metadata: + clamp_possible_values: Dictionary:EventDictionary#Operators + + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + type: string + required: true + description: Domain name to which TCA needs to be applied + default: measurementsForVfScaling + constraints: + - equal: measurementsForVfScaling + metricsPerEventName: + type: list + required: true + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + required: true + description: Closed Loop Control Name associated with the threshold + closedLoopEventStatus: + type: string + required: true + description: Closed Loop Event Status of the threshold + constraints: + - valid_values: + - ONSET + - ABATED + direction: + type: string + required: true + description: Direction of the threshold + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + fieldPath: + type: string + required: true + description: Json field Path as per CEF message which needs to be analyzed for TCA + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + severity: + type: string + required: true + description: Threshold Event Severity + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + thresholdValue: + type: integer + required: true + description: Threshold value for the field Path inside CEF message + version: + type: string + required: true + description: Version number associated with the threshold diff --git a/src/test/resources/tosca/operational-policy-cds-payload-with-list.json b/src/test/resources/tosca/operational-policy-cds-payload-with-list.json new file mode 100644 index 000000000..9a9308e3b --- /dev/null +++ b/src/test/resources/tosca/operational-policy-cds-payload-with-list.json @@ -0,0 +1,590 @@ +{ + "type": "object", + "title": "Configuration", + "required": [ + "operational_policy" + ], + "properties": { + "operational_policy": { + "type": "object", + "title": "Related Parameters", + "required": [ + "controlLoop", + "policies" + ], + "properties": { + "controlLoop": { + "type": "object", + "title": "Control Loop details", + "required": [ + "timeout", + "abatement", + "trigger_policy", + "controlLoopName" + ], + "properties": { + "timeout": { + "type": "string", + "title": "Overall Time Limit", + "default": "0", + "format": "number" + }, + "abatement": { + "type": "string", + "title": "Abatement", + "enum": [ + "True", + "False" + ] + }, + "trigger_policy": { + "type": "string", + "title": "Policy Decision Entry" + }, + "controlLoopName": { + "type": "string", + "title": "Control loop name", + "readOnly": "True" + } + } + }, + "policies": { + "uniqueItems": "true", + "id": "policies_array", + "type": "array", + "title": "Policy Decision Tree", + "format": "tabs-top", + "items": { + "title": "Policy Decision", + "type": "object", + "id": "policy_item", + "headerTemplate": "{{self.id}} - {{self.recipe}}", + "format": "categories", + "basicCategoryTitle": "recipe", + "required": [ + "id", + "retry", + "timeout", + "actor", + "success", + "failure", + "failure_timeout", + "failure_retries", + "failure_exception", + "failure_guard", + "target" + ], + "properties": { + "id": { + "default": "Policy 1", + "title": "Policy ID", + "type": "string" + }, + "retry": { + "default": "0", + "title": "Number of Retry", + "type": "string", + "format": "number" + }, + "timeout": { + "default": "0", + "title": "Timeout", + "type": "string", + "format": "number" + }, + "actor": { + "type": "object", + "title": "Actor", + "anyOf": [ + { + "title": "APPC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "APPC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Restart", + "Rebuild", + "Migrate", + "Health-Check", + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SO", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SO", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "VF Module Create", + "VF Module Delete" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SDNC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SDNC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Reroute", + "BandwidthOnDemand" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "VFC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "VFC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "CDS", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "CDS", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "object", + "anyOf": [ + { + "title": "user-defined", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "user-defined", + "format": "textarea" + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "default": "", + "format": "textarea" + } + } + }, + { + "title": "resource-assignment", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "resource-assignment", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "template-prefix": { + "title": "template-prefix", + "type": "array" + }, + "template-prefix-with-complex-type": { + "title": "template-prefix-with-complex-type", + "type": "array", + "items": { + "properties": { + "prefix-id": { + "title": "prefix-id", + "type": "string" + } + } + } + }, + "private1-prefix-id": { + "title": "private1-prefix-id", + "type": "string" + } + } + } + } + } + } + } + ] + } + } + } + ] + }, + "success": { + "default": "final_success", + "title": "When Success", + "type": "string" + }, + "failure": { + "default": "final_failure", + "title": "When Failure", + "type": "string" + }, + "failure_timeout": { + "default": "final_failure_timeout", + "title": "When Failure Timeout", + "type": "string" + }, + "failure_retries": { + "default": "final_failure_retries", + "title": "When Failure Retries", + "type": "string" + }, + "failure_exception": { + "default": "final_failure_exception", + "title": "When Failure Exception", + "type": "string" + }, + "failure_guard": { + "default": "final_failure_guard", + "title": "When Failure Guard", + "type": "string" + }, + "target": { + "type": "object", + "required": [ + "type", + "resourceID" + ], + "anyOf": [ + { + "title": "User Defined", + "additionalProperties": "True", + "properties": { + "type": { + "title": "Target type", + "type": "string", + "default": "", + "enum": [ + "VNF", + "VFMODULE", + "VM" + ] + }, + "resourceID": { + "title": "Target type", + "type": "string", + "default": "" + } + } + }, + { + "title": "User defined", + "properties": {} + }, + { + "title": "VNF-vLoadBalancerMS 0", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VNF", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vpkg..module-1", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "ca052563-eb92-4b5b-ad41-9111768ce043", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vdns..module-3", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "4fa73b49-8a6c-493e-816b-eb401567b720", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..base_template..module-0", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "63734409-f745-4e4d-a38b-131638a0edce", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vlb..module-2", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "a772a1f4-0064-412c-833d-4749b15828dd", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "readOnly": "True" + } + } + } + ] + } + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/operational-policy-json-schema.json b/src/test/resources/tosca/operational-policy-json-schema.json new file mode 100644 index 000000000..dc6c32fa7 --- /dev/null +++ b/src/test/resources/tosca/operational-policy-json-schema.json @@ -0,0 +1,936 @@ +{ + "type": "object", + "title": "Configuration", + "required": [ + "operational_policy" + ], + "properties": { + "operational_policy": { + "type": "object", + "title": "Related Parameters", + "required": [ + "controlLoop", + "policies" + ], + "properties": { + "controlLoop": { + "type": "object", + "title": "Control Loop details", + "required": [ + "timeout", + "abatement", + "trigger_policy", + "controlLoopName" + ], + "properties": { + "timeout": { + "type": "string", + "title": "Overall Time Limit", + "default": "0", + "format": "number" + }, + "abatement": { + "type": "string", + "title": "Abatement", + "enum": [ + "True", + "False" + ] + }, + "trigger_policy": { + "type": "string", + "title": "Policy Decision Entry" + }, + "controlLoopName": { + "type": "string", + "title": "Control loop name", + "readOnly": "True" + } + } + }, + "policies": { + "uniqueItems": "true", + "id": "policies_array", + "type": "array", + "title": "Policy Decision Tree", + "format": "tabs-top", + "items": { + "title": "Policy Decision", + "type": "object", + "id": "policy_item", + "headerTemplate": "{{self.id}} - {{self.recipe}}", + "format": "categories", + "basicCategoryTitle": "recipe", + "required": [ + "id", + "retry", + "timeout", + "actor", + "success", + "failure", + "failure_timeout", + "failure_retries", + "failure_exception", + "failure_guard", + "target" + ], + "properties": { + "id": { + "default": "Policy 1", + "title": "Policy ID", + "type": "string" + }, + "retry": { + "default": "0", + "title": "Number of Retry", + "type": "string", + "format": "number" + }, + "timeout": { + "default": "0", + "title": "Timeout", + "type": "string", + "format": "number" + }, + "actor": { + "type": "object", + "title": "Actor", + "anyOf": [ + { + "title": "APPC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "APPC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Restart", + "Rebuild", + "Migrate", + "Health-Check", + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SO", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SO", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "VF Module Create", + "VF Module Delete" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "SDNC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "SDNC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "Reroute", + "BandwidthOnDemand" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "VFC", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "VFC", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "string", + "default": "", + "enum": [ + "ModifyConfig" + ] + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "format": "textarea" + } + } + }, + { + "title": "CDS", + "type": "object", + "properties": { + "actor": { + "title": "actor", + "type": "string", + "default": "CDS", + "options": { + "hidden": true + } + }, + "recipe": { + "title": "recipe", + "type": "object", + "anyOf": [ + { + "title": "user-defined", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "user-defined", + "format": "textarea" + }, + "payload": { + "title": "Payload (YAML)", + "type": "string", + "default": "", + "format": "textarea" + } + } + }, + { + "title": "resource-assignment", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "resource-assignment", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + }, + { + "title": "activate", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "activate", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + }, + { + "title": "activate-restconf", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "activate-restconf", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + }, + { + "title": "activate-cli", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "activate-cli", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + }, + { + "title": "assign-activate", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "assign-activate", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + }, + { + "title": "imperative-test-wf", + "type": "object", + "properties": { + "recipe": { + "title": "recipe", + "type": "string", + "default": "imperative-test-wf", + "options": { + "hidden": true + } + }, + "payload": { + "title": "Payload", + "type": "object", + "properties": { + "artifact_name": { + "title": "artifact name", + "type": "string", + "default": "baseconfiguration", + "readOnly": "True" + }, + "artifact_version": { + "title": "artifact version", + "type": "string", + "default": "1.0.0", + "readOnly": "True" + }, + "mode": { + "title": "mode", + "type": "string", + "default": "async" + }, + "data": { + "title": "data", + "properties": { + "request-id": { + "title": "request-id", + "type": "string" + }, + "service-instance-id": { + "title": "service-instance-id", + "type": "string" + }, + "hostname": { + "title": "hostname", + "type": "string" + }, + "request-info": { + "title": "request-info", + "type": "object", + "properties": { + "prop1": { + "title": "prop1", + "type": "string" + }, + "prop2": { + "title": "prop2", + "type": "string" + } + } + } + } + } + } + } + } + } + ] + } + } + } + ] + }, + "success": { + "default": "final_success", + "title": "When Success", + "type": "string" + }, + "failure": { + "default": "final_failure", + "title": "When Failure", + "type": "string" + }, + "failure_timeout": { + "default": "final_failure_timeout", + "title": "When Failure Timeout", + "type": "string" + }, + "failure_retries": { + "default": "final_failure_retries", + "title": "When Failure Retries", + "type": "string" + }, + "failure_exception": { + "default": "final_failure_exception", + "title": "When Failure Exception", + "type": "string" + }, + "failure_guard": { + "default": "final_failure_guard", + "title": "When Failure Guard", + "type": "string" + }, + "target": { + "type": "object", + "required": [ + "type", + "resourceID" + ], + "anyOf": [ + { + "title": "User Defined", + "additionalProperties": "True", + "properties": { + "type": { + "title": "Target type", + "type": "string", + "default": "", + "enum": [ + "VNF", + "VFMODULE", + "VM" + ] + }, + "resourceID": { + "title": "Target type", + "type": "string", + "default": "" + } + } + }, + { + "title": "User defined", + "properties": {} + }, + { + "title": "VNF-vLoadBalancerMS 0", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VNF", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vpkg..module-1", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "ca052563-eb92-4b5b-ad41-9111768ce043", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vpkg..module-1", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vdns..module-3", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "4fa73b49-8a6c-493e-816b-eb401567b720", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vdns..module-3", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..base_template..module-0", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "63734409-f745-4e4d-a38b-131638a0edce", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..base_template..module-0", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Vloadbalancerms..vlb..module-2", + "properties": { + "type": { + "title": "Type", + "type": "string", + "default": "VFMODULE", + "readOnly": "True" + }, + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "a772a1f4-0064-412c-833d-4749b15828dd", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Vloadbalancerms..vlb..module-2", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "readOnly": "True" + } + } + } + ] + } + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/operational-policy-no-guard-properties.json b/src/test/resources/tosca/operational-policy-no-guard-properties.json new file mode 100644 index 000000000..fdb1906a4 --- /dev/null +++ b/src/test/resources/tosca/operational-policy-no-guard-properties.json @@ -0,0 +1,35 @@ +{ + "operational_policy": { + "controlLoop": { + "trigger_policy": "new", + "timeout": "0", + "abatement": "on", + "controlLoopName": "LOOP_iYTIP_v1_0_ResourceInstanceName1_tca" + }, + "policies": [ + { + "id": "new", + "recipe": "Restart", + "retry": "10", + "timeout": "10", + "actor": "SO", + "payload": "", + "success": "", + "failure": "", + "failure_timeout": "", + "failure_retries": "", + "failure_exception": "", + "failure_guard": "", + "target": { + "type": "VM", + "resourceID": "", + "modelInvariantId": "", + "modelVersionId": "", + "modelName": "", + "modelVersion": "", + "modelCustomizationId": "" + } + } + ] + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/operational-policy-properties.json b/src/test/resources/tosca/operational-policy-properties.json new file mode 100644 index 000000000..a38334b55 --- /dev/null +++ b/src/test/resources/tosca/operational-policy-properties.json @@ -0,0 +1,132 @@ +{ + "operational_policy": { + "controlLoop": { + "timeout": "0", + "abatement": "True", + "trigger_policy": "policy1", + "controlLoopName": "LOOP_ASJOy_v1_0_ResourceInstanceName1_tca" + }, + "policies": [ + { + "actor": { + "actor": "APPC", + "recipe": "Restart", + "payload": "requestParameters: '{\"usePreload\":true,\"userParams\":[]}'\r\nconfigurationParameters: '[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[10].value\",\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[15].value\",\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[22].value\"}]'" + }, + "id": "policy1", + "retry": "0", + "timeout": "0", + "success": "final_success", + "failure": "policy2", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard", + "target": { + "type": "VNF", + "resourceID": "vLoadBalancerMS" + } + }, + { + "actor": { + "actor": "SO", + "recipe": "VF Module Create", + "payload": "" + }, + "id": "policy2", + "retry": "0", + "timeout": "0", + "success": "final_success", + "failure": "final_failure", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard", + "target": { + "type": "VFMODULE", + "resourceID": "Vloadbalancerms..vpkg..module-1", + "modelInvariantId": "ca052563-eb92-4b5b-ad41-9111768ce043", + "modelVersionId": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "modelName": "Vloadbalancerms..vpkg..module-1", + "modelVersion": "1", + "modelCustomizationId": "1bffdc31-a37d-4dee-b65c-dde623a76e52" + } + }, + { + "actor": { + "actor": "CDS", + "recipe": { + "recipe": "resource-assignment", + "payload": { + "artifact_name": "baseconfiguration", + "artifact_version": "1.0.0", + "mode": "async", + "data": { + "resource-assignment-properties": { + "request-id": "request-id", + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id", + "action-name": "action-name", + "scope-type": "scope-type", + "hostname": "hostname", + "vnf_name": "vnf_name" + } + } + } + } + }, + "id": "policy3", + "retry": "0", + "timeout": "0", + "success": "final_success", + "failure": "final_failure", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard", + "target": { + "type": "VFMODULE", + "resourceID": "Vloadbalancerms..vpkg..module-1", + "modelInvariantId": "ca052563-eb92-4b5b-ad41-9111768ce043", + "modelVersionId": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "modelName": "Vloadbalancerms..vpkg..module-1", + "modelVersion": "1", + "modelCustomizationId": "1bffdc31-a37d-4dee-b65c-dde623a76e52" + } + }, + { + "actor": { + "actor": "CDS", + "recipe": { + "recipe": "modify-config", + "payload": { + "artifact_name": "baseconfiguration", + "artifact_version": "1.0.0", + "mode": "async", + "data": { + } + } + } + }, + "id": "policy4", + "retry": "0", + "timeout": "0", + "success": "final_success", + "failure": "final_failure", + "failure_timeout": "final_failure_timeout", + "failure_retries": "final_failure_retries", + "failure_exception": "final_failure_exception", + "failure_guard": "final_failure_guard", + "target": { + "type": "VFMODULE", + "resourceID": "Vloadbalancerms..vpkg..module-1", + "modelInvariantId": "ca052563-eb92-4b5b-ad41-9111768ce043", + "modelVersionId": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "modelName": "Vloadbalancerms..vpkg..module-1", + "modelVersion": "1", + "modelCustomizationId": "1bffdc31-a37d-4dee-b65c-dde623a76e52" + } + } + ] + } +} diff --git a/src/test/resources/tosca/pdp-group-policy-payload.json b/src/test/resources/tosca/pdp-group-policy-payload.json new file mode 100644 index 000000000..17535ecbb --- /dev/null +++ b/src/test/resources/tosca/pdp-group-policy-payload.json @@ -0,0 +1,48 @@ +{ + "groups": [ + { + "name": "pdpGroup1", + "deploymentSubgroups": [ + { + "pdpType": "pdpSubgroup1", + "action": "POST", + "policies": [ + { + "name": "configPolicyTest", + "version": "1.0.0" + } + ] + } + ] + }, + { + "name": "pdpGroup2", + "deploymentSubgroups": [ + { + "pdpType": "pdpSubgroup2", + "action": "POST", + "policies": [ + { + "name": "opLegacyPolicy", + "version": "1.0.0" + }, + { + "name": "opPolicy", + "version": "1.0.0" + } + ] + }, + { + "pdpType": "pdpSubgroup1", + "action": "POST", + "policies": [ + { + "name": "configPolicyTest2", + "version": "1.0.0" + } + ] + } + ] + } + ] +}
\ No newline at end of file diff --git a/src/test/resources/tosca/policy-yaml-to-json-with-constraints.json b/src/test/resources/tosca/policy-yaml-to-json-with-constraints.json new file mode 100644 index 000000000..fe9b84d13 --- /dev/null +++ b/src/test/resources/tosca/policy-yaml-to-json-with-constraints.json @@ -0,0 +1,63 @@ +{ + "schema": { + "uniqueItems": "true", + "format": "tabs", + "type": "array", + "title": "Properties with constraints", + "items": { + "type": "object", + "title": "Properties with constraints", + "required": [ + "cpus", + "memSize" + ], + "properties": { + "appPassword": { + "propertyOrder": 1004, + "minLength": 6, + "title": "application password", + "type": "string", + "maxLength": 10 + }, + "cost": { + "exclusiveMaximum": 100.5, + "propertyOrder": 1005, + "type": "integer", + "exclusiveMinimum": 50.5 + }, + "keylength": { + "propertyOrder": 1007, + "type": "integer", + "enum": [ + 128, + 256 + ] + }, + "cpus": { + "propertyOrder": 1001, + "default": 1, + "minLength": 1, + "type": "string", + "maxLength": 4 + }, + "ports": { + "propertyOrder": 1002, + "maximum": 9010, + "type": "integer", + "minimum": 9000 + }, + "memSize": { + "propertyOrder": 1003, + "maximum": 10, + "title": "memory size", + "type": "integer", + "minimum": 2 + }, + "algorithm": { + "propertyOrder": 1006, + "type": "string" + } + } + } + } +} diff --git a/src/test/resources/tosca/policy-yaml-to-json-with-datatypes.json b/src/test/resources/tosca/policy-yaml-to-json-with-datatypes.json new file mode 100644 index 000000000..ef9c2c03a --- /dev/null +++ b/src/test/resources/tosca/policy-yaml-to-json-with-datatypes.json @@ -0,0 +1,108 @@ +{ + "schema": { + "uniqueItems": "true", + "format": "tabs", + "type": "array", + "title": "Properties with different types", + "items": { + "type": "object", + "title": "Properties with different types", + "required": [ + "memSize" + ], + "properties": { + "cpus": { + "propertyOrder": 1001, + "uniqueItems": "true", + "format": "tabs-top", + "type": "array", + "items": { + "type": "object", + "required": [], + "properties": { + "closedLoopControlName": { + "propertyOrder": 1002, + "type": "string" + } + } + } + }, + "domain": { + "propertyOrder": 1009, + "type": "object", + "required": [], + "properties": { + "closedLoopControlName": { + "propertyOrder": 1002, + "type": "string" + } + } + }, + "thresholdValue": { + "propertyOrder": 1007, + "uniqueItems": "true", + "format": "select", + "type": "array", + "items": { + "type": "string" + } + }, + "ports": { + "propertyOrder": 1003, + "type": "object", + "items": { + "type": "string" + } + }, + "closedLoopEventStatus": { + "propertyOrder": 1004, + "type": "object", + "items": { + "type": "integer" + } + }, + "version": { + "propertyOrder": 1008, + "uniqueItems": "true", + "format": "tabs-top", + "type": "array", + "items": { + "type": "object", + "required": [], + "properties": { + "closedLoopControlName": { + "propertyOrder": 1002, + "type": "string" + } + } + } + }, + "memSize": { + "propertyOrder": 1006, + "required": [], + "properties": { + "name": { + "propertyOrder": 20002, + "required": [ + "severity" + ], + "properties": { + "severity": { + "propertyOrder": 20003, + "type": "string" + } + } + } + } + }, + "direction": { + "propertyOrder": 1005, + "type": "object", + "items": { + "type": "integer" + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/policy-yaml-to-json.json b/src/test/resources/tosca/policy-yaml-to-json.json new file mode 100644 index 000000000..b83d3f24f --- /dev/null +++ b/src/test/resources/tosca/policy-yaml-to-json.json @@ -0,0 +1,192 @@ +{ + "schema": { + "uniqueItems": "true", + "format": "tabs", + "type": "array", + "title": "TCA Policy JSON", + "items": { + "type": "object", + "title": "TCA Policy JSON", + "required": [ + "domain", + "metricsPerEventName" + ], + "properties": { + "domain": { + "propertyOrder": 1001, + "default": "measurementsForVfScaling", + "title": "Domain name to which TCA needs to be applied", + "type": "string" + }, + "metricsPerEventName": { + "propertyOrder": 1002, + "uniqueItems": "true", + "format": "tabs-top", + "title": "Contains eventName and threshold details that need to be applied to given eventName", + "type": "array", + "items": { + "type": "object", + "required": [ + "controlLoopSchemaType", + "eventName", + "policyName", + "policyScope", + "policyVersion", + "thresholds" + ], + "properties": { + "policyVersion": { + "propertyOrder": 1007, + "title": "TCA Policy Scope Version", + "type": "string" + }, + "thresholds": { + "propertyOrder": 1008, + "uniqueItems": "true", + "format": "tabs-top", + "title": "Thresholds associated with eventName", + "type": "array", + "items": { + "type": "object", + "required": [ + "closedLoopControlName", + "closedLoopEventStatus", + "direction", + "fieldPath", + "severity", + "thresholdValue", + "version" + ], + "properties": { + "severity": { + "propertyOrder": 1013, + "title": "Threshold Event Severity", + "type": "string", + "enum": [ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "fieldPath": { + "propertyOrder": 1012, + "title": "Json field Path as per CEF message which needs to be analyzed for TCA", + "type": "string", + "enum": [ + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage", + "$.event.measurementsForVfScalingFields.meanRequestLatency", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed", + "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value" + ] + }, + "thresholdValue": { + "propertyOrder": 1014, + "title": "Threshold value for the field Path inside CEF message", + "type": "integer" + }, + "closedLoopEventStatus": { + "propertyOrder": 1010, + "title": "Closed Loop Event Status of the threshold", + "type": "string", + "enum": [ + "ONSET", + "ABATED" + ] + }, + "closedLoopControlName": { + "propertyOrder": 1009, + "title": "Closed Loop Control Name associated with the threshold", + "type": "string" + }, + "version": { + "propertyOrder": 1015, + "title": "Version number associated with the threshold", + "type": "string" + }, + "direction": { + "propertyOrder": 1011, + "title": "Direction of the threshold", + "type": "string", + "enum": [ + "LESS", + "LESS_OR_EQUAL", + "GREATER", + "GREATER_OR_EQUAL", + "EQUAL" + ] + } + } + } + }, + "policyName": { + "propertyOrder": 1005, + "title": "TCA Policy Scope Name", + "type": "string" + }, + "controlLoopSchemaType": { + "propertyOrder": 1003, + "title": "Specifies Control Loop Schema Type for the event Name e.g. VNF, VM", + "type": "string", + "enum": [ + "VM", + "VNF" + ] + }, + "policyScope": { + "propertyOrder": 1006, + "title": "TCA Policy Scope", + "type": "string" + }, + "eventName": { + "propertyOrder": 1004, + "title": "Event name to which thresholds need to be applied", + "type": "string" + } + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/resource-details-cds.json b/src/test/resources/tosca/resource-details-cds.json new file mode 100644 index 000000000..d972d0cb9 --- /dev/null +++ b/src/test/resources/tosca/resource-details-cds.json @@ -0,0 +1,336 @@ +{ + "CP": { + }, + "VL": { + }, + "VF": { + "vLoadBalancerMS 0": { + "resourceVendor": "Test", + "resourceVendorModelNumber": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "subcategory": "Load Balancer", + "category": "Application L4+", + "type": "VF", + "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6", + "version": "1.0", + "resourceVendorRelease": "1.0", + "customizationUUID": "465246dc-7748-45f4-a013-308d92922552", + "controllerProperties": { + "sdnc_model_name": "baseconfiguration", + "sdnc_model_version": "1.0.0", + "workflows": { + "resource-assignment": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate": { + "inputs": { + "activate-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-restconf": { + "inputs": { + "activate-restconf-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-cli": { + "inputs": { + "activate-cli-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "assign-activate": { + "inputs": { + "assign-activate-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "imperative-test-wf": { + "inputs": { + "imperative-test-wf-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + } + } + } + } + }, + "CR": { + }, + "VFC": { + }, + "PNF": { + }, + "Service": { + }, + "CVFC": { + }, + "Service Proxy": { + }, + "Configuration": { + }, + "AllottedResource": { + }, + "VFModule": { + "Vloadbalancerms..vpkg..module-1": { + "vfModuleModelInvariantUUID": "ca052563-eb92-4b5b-ad41-9111768ce043", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vpkg..module-1", + "vfModuleModelUUID": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "vfModuleModelCustomizationUUID": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "min_vf_module_instances": 0, + "vf_module_label": "vpkg", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..vdns..module-3": { + "vfModuleModelInvariantUUID": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vdns..module-3", + "vfModuleModelUUID": "4fa73b49-8a6c-493e-816b-eb401567b720", + "vfModuleModelCustomizationUUID": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "min_vf_module_instances": 0, + "vf_module_label": "vdns", + "max_vf_module_instances": 50, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..base_template..module-0": { + "vfModuleModelInvariantUUID": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..base_template..module-0", + "vfModuleModelUUID": "63734409-f745-4e4d-a38b-131638a0edce", + "vfModuleModelCustomizationUUID": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "min_vf_module_instances": 1, + "vf_module_label": "base_template", + "max_vf_module_instances": 1, + "vf_module_type": "Base", + "isBase": true, + "initial_count": 1, + "volume_group": false + }, + "Vloadbalancerms..vlb..module-2": { + "vfModuleModelInvariantUUID": "a772a1f4-0064-412c-833d-4749b15828dd", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vlb..module-2", + "vfModuleModelUUID": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "vfModuleModelCustomizationUUID": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "min_vf_module_instances": 0, + "vf_module_label": "vlb", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/resource-details.json b/src/test/resources/tosca/resource-details.json new file mode 100644 index 000000000..b55adbf52 --- /dev/null +++ b/src/test/resources/tosca/resource-details.json @@ -0,0 +1,336 @@ +{ + "CP": { + }, + "VL": { + }, + "VF": { + "vLoadBalancerMS 0": { + "resourceVendor": "Test", + "resourceVendorModelNumber": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "1a31b9f2-e50d-43b7-89b3-a040250cf506", + "subcategory": "Load Balancer", + "category": "Application L4+", + "type": "VF", + "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6", + "version": "1.0", + "resourceVendorRelease": "1.0", + "customizationUUID": "465246dc-7748-45f4-a013-308d92922552", + "controllerProperties": { + "sdnc_model_name": "baseconfiguration", + "sdnc_model_version": "1.0.0", + "workflows": { + "resource-assignment": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-restconf": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "activate-cli": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "assign-activate": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + }, + "imperative-test-wf": { + "inputs": { + "resource-assignment-properties": { + "type": "object", + "properties": { + "request-id": { + "type": "string", + "required": true, + "input-param": true + }, + "service-instance-id": { + "type": "string", + "required": true, + "input-param": true + }, + "hostname": { + "type": "string", + "required": true, + "input-param": true + }, + "request-info": { + "type": "object", + "properties": { + "prop1": { + "required": true, + "type": "string", + "input-param": true + }, + "prop2": { + "required": true, + "type": "string", + "input-param": true + } + } + } + } + } + } + } + } + } + } + }, + "CR": { + }, + "VFC": { + }, + "PNF": { + }, + "Service": { + }, + "CVFC": { + }, + "Service Proxy": { + }, + "Configuration": { + }, + "AllottedResource": { + }, + "VFModule": { + "Vloadbalancerms..vpkg..module-1": { + "vfModuleModelInvariantUUID": "ca052563-eb92-4b5b-ad41-9111768ce043", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vpkg..module-1", + "vfModuleModelUUID": "1e725ccc-b823-4f67-82b9-4f4367070dbc", + "vfModuleModelCustomizationUUID": "1bffdc31-a37d-4dee-b65c-dde623a76e52", + "min_vf_module_instances": 0, + "vf_module_label": "vpkg", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..vdns..module-3": { + "vfModuleModelInvariantUUID": "4c10ba9b-f88f-415e-9de3-5d33336047fa", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vdns..module-3", + "vfModuleModelUUID": "4fa73b49-8a6c-493e-816b-eb401567b720", + "vfModuleModelCustomizationUUID": "bafcdab0-801d-4d81-9ead-f464640a38b1", + "min_vf_module_instances": 0, + "vf_module_label": "vdns", + "max_vf_module_instances": 50, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + }, + "Vloadbalancerms..base_template..module-0": { + "vfModuleModelInvariantUUID": "921f7c96-ebdd-42e6-81b9-1cfc0c9796f3", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..base_template..module-0", + "vfModuleModelUUID": "63734409-f745-4e4d-a38b-131638a0edce", + "vfModuleModelCustomizationUUID": "86baddea-c730-4fb8-9410-cd2e17fd7f27", + "min_vf_module_instances": 1, + "vf_module_label": "base_template", + "max_vf_module_instances": 1, + "vf_module_type": "Base", + "isBase": true, + "initial_count": 1, + "volume_group": false + }, + "Vloadbalancerms..vlb..module-2": { + "vfModuleModelInvariantUUID": "a772a1f4-0064-412c-833d-4749b15828dd", + "vfModuleModelVersion": "1", + "vfModuleModelName": "Vloadbalancerms..vlb..module-2", + "vfModuleModelUUID": "0f5c3f6a-650a-4303-abb6-fff3e573a07a", + "vfModuleModelCustomizationUUID": "96a78aad-4ffb-4ef0-9c4f-deb03bf1d806", + "min_vf_module_instances": 0, + "vf_module_label": "vlb", + "max_vf_module_instances": 1, + "vf_module_type": "Expansion", + "isBase": false, + "initial_count": 0, + "volume_group": false + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/service-details.json b/src/test/resources/tosca/service-details.json new file mode 100644 index 000000000..f41eec107 --- /dev/null +++ b/src/test/resources/tosca/service-details.json @@ -0,0 +1,15 @@ +{ + "serviceType": "", + "namingPolicy": "", + "environmentContext": "General_Revenue-Bearing", + "serviceEcompNaming": "true", + "serviceRole": "", + "name": "vLoadBalancerMS", + "description": "vLBMS", + "invariantUUID": "30ec5b59-4799-48d8-ac5f-1058a6b0e48f", + "ecompGeneratedNaming": "true", + "category": "Network L4+", + "type": "Service", + "UUID": "63cac700-ab9a-4115-a74f-7eac85e3fce0", + "instantiationType": "A-la-carte" +}
\ No newline at end of file diff --git a/src/test/resources/tosca/tosca-with-constraints.yaml b/src/test/resources/tosca/tosca-with-constraints.yaml new file mode 100644 index 000000000..959bc483b --- /dev/null +++ b/src/test/resources/tosca/tosca-with-constraints.yaml @@ -0,0 +1,54 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.example.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + example_policy: + type: map + description: Properties with constraints + entry_schema: + type: onap.datatypes.monitoring.example_policy +data_types: + onap.datatypes.monitoring.example_policy: + derived_from: tosca.datatypes.Root + properties: + cpus: + type: string + required: true + default: 1 + constraints: + - in_range: [ 1, 4 ] + ports: + type: integer + constraints: + - in_range: [ 9000, 9010 ] + memSize: + type: integer + required: true + description: memory size + constraints: + - greater_or_equal: 2 + - less_or_equal: 10 + appPassword: + type: string + description: application password + constraints: + - min_length: 6 + - max_length: 10 + cost: + type: float + constraints: + - less_than: 100.50 + - greater_than: 50.50 + algorithm: + type: string + constraints: + - equal: aes + keylength: + type: integer + constraints: + - valid_values: [ 128, 256 ] diff --git a/src/test/resources/tosca/tosca-with-datatypes.yaml b/src/test/resources/tosca/tosca-with-datatypes.yaml new file mode 100644 index 000000000..61d5dbcc8 --- /dev/null +++ b/src/test/resources/tosca/tosca-with-datatypes.yaml @@ -0,0 +1,63 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.example.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + example_policy: + type: map + description: Properties with different types + entry_schema: + type: onap.datatypes.monitoring.example_policy +data_types: + onap.datatypes.monitoring.example2: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + onap.datatypes.monitoring.example3: + derived_from: tosca.datatypes.Root + properties: + name: + type: onap.datatypes.monitoring.example4 + onap.datatypes.monitoring.example4: + derived_from: tosca.datatypes.Root + properties: + severity: + type: string + required: true + onap.datatypes.monitoring.example_policy: + derived_from: tosca.datatypes.Root + properties: + cpus: + type: list + entry_schema: + type: onap.datatypes.monitoring.example2 + ports: + type: map + entry_schema: + type: string + closedLoopEventStatus: + type: map + entry_schema: + type: integer + direction: + type: map + entry_schema: + type: float + memSize: + type: onap.datatypes.monitoring.example3 + required: true + thresholdValue: + type: list + entry_schema: + type: string + version: + type: list + entry_schema: + type: onap.datatypes.monitoring.example2 + domain: + type: onap.datatypes.monitoring.example2
\ No newline at end of file diff --git a/src/test/resources/tosca/tosca_example.yaml b/src/test/resources/tosca/tosca_example.yaml new file mode 100644 index 000000000..b0119f887 --- /dev/null +++ b/src/test/resources/tosca/tosca_example.yaml @@ -0,0 +1,158 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: map + description: TCA Policy JSON + entry_schema: + type: onap.datatypes.monitoring.tca_policy +data_types: + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + type: string + required: true + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + constraints: + - valid_values: + - VM + - VNF + eventName: + type: string + required: true + description: Event name to which thresholds need to be applied + policyName: + type: string + required: true + description: TCA Policy Scope Name + policyScope: + type: string + required: true + description: TCA Policy Scope + policyVersion: + type: string + required: true + description: TCA Policy Scope Version + thresholds: + type: list + required: true + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + type: string + required: true + description: Domain name to which TCA needs to be applied + default: measurementsForVfScaling + constraints: + - equal: measurementsForVfScaling + metricsPerEventName: + type: list + required: true + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + required: true + description: Closed Loop Control Name associated with the threshold + closedLoopEventStatus: + type: string + required: true + description: Closed Loop Event Status of the threshold + constraints: + - valid_values: + - ONSET + - ABATED + direction: + type: string + required: true + description: Direction of the threshold + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + fieldPath: + type: string + required: true + description: Json field Path as per CEF message which needs to be analyzed for TCA + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + severity: + type: string + required: true + description: Threshold Event Severity + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + thresholdValue: + type: integer + required: true + description: Threshold value for the field Path inside CEF message + version: + type: string + required: true + description: Version number associated with the threshold diff --git a/src/test/resources/tosca/tosca_metadata_clamp_possible_values.yaml b/src/test/resources/tosca/tosca_metadata_clamp_possible_values.yaml new file mode 100644 index 000000000..4d3c3dff2 --- /dev/null +++ b/src/test/resources/tosca/tosca_metadata_clamp_possible_values.yaml @@ -0,0 +1,184 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: map + description: TCA Policy JSON + entry_schema: + type: onap.datatypes.monitoring.tca_policy + metadata: + policy_model_type: onap.policies.monitoring.cdap.tca.hi.lo.app + acronym: tca + +data_types: + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + type: string + required: true + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + constraints: + - valid_values: + - VM + - VNF + eventName: + type: string + required: true + description: Event name to which thresholds need to be applied + policyName: + type: string + required: true + description: TCA Policy Scope Name + policyScope: + type: string + required: true + description: TCA Policy Scope + policyVersion: + type: string + required: true + description: TCA Policy Scope Version + thresholds: + type: list + required: true + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + context: + type: string + required: true + description: TCA Policy Dummy Context + metadata: + clamp_possible_values: ["Dictionary:Context"] + + signature: + type: onap.datatypes.monitoring.Dummy_Signature + description: Signature + required: true + + onap.datatypes.monitoring.Dummy_Signature: + derived_from: tosca.datatypes.Root + properties: + filter_clause: + type: string + description: Filter Clause + required: true + metadata: + clamp_possible_values: ["Dictionary:EventDictionary#Operators"] + + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + type: string + required: true + description: Domain name to which TCA needs to be applied + default: measurementsForVfScaling + constraints: + - equal: measurementsForVfScaling + metricsPerEventName: + type: list + required: true + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + required: true + description: Closed Loop Control Name associated with the threshold + closedLoopEventStatus: + type: string + required: true + description: Closed Loop Event Status of the threshold + constraints: + - valid_values: + - ONSET + - ABATED + direction: + type: string + required: true + description: Direction of the threshold + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + fieldPath: + type: string + required: true + description: Json field Path as per CEF message which needs to be analyzed for TCA + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + severity: + type: string + required: true + description: Threshold Event Severity + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + thresholdValue: + type: integer + required: true + description: Threshold value for the field Path inside CEF message + version: + type: string + required: true + description: Version number associated with the threshold diff --git a/src/test/resources/tosca/tosca_metadata_clamp_possible_values_json_schema.json b/src/test/resources/tosca/tosca_metadata_clamp_possible_values_json_schema.json new file mode 100644 index 000000000..418ee71be --- /dev/null +++ b/src/test/resources/tosca/tosca_metadata_clamp_possible_values_json_schema.json @@ -0,0 +1,249 @@ +{ + "schema":{ + "uniqueItems":"true", + "format":"tabs", + "type":"array", + "title":"TCA Policy JSON", + "items":{ + "type":"object", + "title":"TCA Policy JSON", + "required":[ + "domain", + "metricsPerEventName" + ], + "properties":{ + "domain":{ + "propertyOrder":1001, + "default":"measurementsForVfScaling", + "title":"Domain name to which TCA needs to be applied", + "type":"string" + }, + "metricsPerEventName":{ + "propertyOrder":1002, + "uniqueItems":"true", + "format":"tabs-top", + "title":"Contains eventName and threshold details that need to be applied to given eventName", + "type":"array", + "items":{ + "type":"object", + "required":[ + "controlLoopSchemaType", + "eventName", + "policyName", + "policyScope", + "policyVersion", + "thresholds", + "context", + "signature" + ], + "properties":{ + "policyVersion":{ + "propertyOrder":1007, + "title":"TCA Policy Scope Version", + "type":"string" + }, + "thresholds":{ + "propertyOrder":1008, + "uniqueItems":"true", + "format":"tabs-top", + "title":"Thresholds associated with eventName", + "type":"array", + "items":{ + "type":"object", + "required":[ + "closedLoopControlName", + "closedLoopEventStatus", + "direction", + "fieldPath", + "severity", + "thresholdValue", + "version" + ], + "properties":{ + "severity":{ + "propertyOrder":1013, + "title":"Threshold Event Severity", + "type":"string", + "enum":[ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "fieldPath":{ + "propertyOrder":1012, + "title":"Json field Path as per CEF message which needs to be analyzed for TCA", + "type":"string", + "enum":[ + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage", + "$.event.measurementsForVfScalingFields.meanRequestLatency", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed", + "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value" + ] + }, + "thresholdValue":{ + "propertyOrder":1014, + "title":"Threshold value for the field Path inside CEF message", + "type":"integer" + }, + "closedLoopEventStatus":{ + "propertyOrder":1010, + "title":"Closed Loop Event Status of the threshold", + "type":"string", + "enum":[ + "ONSET", + "ABATED" + ] + }, + "closedLoopControlName":{ + "propertyOrder":1009, + "title":"Closed Loop Control Name associated with the threshold", + "type":"string" + }, + "version":{ + "propertyOrder":1015, + "title":"Version number associated with the threshold", + "type":"string" + }, + "direction":{ + "propertyOrder":1011, + "title":"Direction of the threshold", + "type":"string", + "enum":[ + "LESS", + "LESS_OR_EQUAL", + "GREATER", + "GREATER_OR_EQUAL", + "EQUAL" + ] + } + } + } + }, + "policyName":{ + "propertyOrder":1005, + "title":"TCA Policy Scope Name", + "type":"string" + }, + "signature":{ + "propertyOrder":1017, + "title":"Signature", + "required":[ + "filter_clause" + ], + "properties":{ + "filter_clause":{ + "propertyOrder":30002, + "qschema":{ + "filters":[ + { + "operators":[ + "equals" + ], + "minLength":1, + "id":"alarmCondition", + "label":"alarmCondition", + "type":"string" + }, + { + "plugin":"datetimepicker", + "operators":[ + "equals" + ], + "minLength":1, + "id":"timeEpoch", + "label":"timeEpoch", + "type":"datetime", + "input_event":"dp.change", + "validation":{ + "format":"YYYY/MM/DD HH:mm:ss" + } + } + ] + }, + "minLength":1, + "title":"Filter Clause", + "type":"qbldr" + } + } + }, + "controlLoopSchemaType":{ + "propertyOrder":1003, + "title":"Specifies Control Loop Schema Type for the event Name e.g. VNF, VM", + "type":"string", + "enum":[ + "VM", + "VNF" + ] + }, + "policyScope":{ + "propertyOrder":1006, + "title":"TCA Policy Scope", + "type":"string" + }, + "context":{ + "propertyOrder":1016, + "options":{ + "enum_titles":[ + "PROD" + ] + }, + "title":"TCA Policy Dummy Context", + "type":"string", + "enum":[ + "PROD" + ] + }, + "eventName":{ + "propertyOrder":1004, + "title":"Event name to which thresholds need to be applied", + "type":"string" + } + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/tosca_with_date_time_json_schema.json b/src/test/resources/tosca/tosca_with_date_time_json_schema.json new file mode 100644 index 000000000..e15942cc5 --- /dev/null +++ b/src/test/resources/tosca/tosca_with_date_time_json_schema.json @@ -0,0 +1,240 @@ +{ + "schema":{ + "uniqueItems":"true", + "format":"tabs", + "type":"array", + "title":"TCA Policy JSON", + "items":{ + "type":"object", + "title":"TCA Policy JSON", + "required":[ + "domain", + "metricsPerEventName" + ], + "properties":{ + "domain":{ + "propertyOrder":1001, + "default":"measurementsForVfScaling", + "title":"Domain name to which TCA needs to be applied", + "type":"string" + }, + "metricsPerEventName":{ + "propertyOrder":1002, + "uniqueItems":"true", + "format":"tabs-top", + "title":"Contains eventName and threshold details that need to be applied to given eventName", + "type":"array", + "items":{ + "type":"object", + "required":[ + "controlLoopSchemaType", + "eventName", + "policyName", + "policyScope", + "policyVersion", + "thresholds", + "context", + "signature" + ], + "properties":{ + "policyVersion":{ + "propertyOrder":1007, + "title":"TCA Policy Scope Version", + "type":"string" + }, + "thresholds":{ + "propertyOrder":1008, + "uniqueItems":"true", + "format":"tabs-top", + "title":"Thresholds associated with eventName", + "type":"array", + "items":{ + "type":"object", + "required":[ + "closedLoopControlName", + "closedLoopEventStatus", + "direction", + "fieldPath", + "severity", + "thresholdValue", + "version" + ], + "properties":{ + "severity":{ + "propertyOrder":1013, + "title":"Threshold Event Severity", + "type":"string", + "enum":[ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "fieldPath":{ + "propertyOrder":1012, + "title":"Json field Path as per CEF message which needs to be analyzed for TCA", + "type":"string", + "enum":[ + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated", + "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait", + "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage", + "$.event.measurementsForVfScalingFields.meanRequestLatency", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree", + "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed", + "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value" + ] + }, + "thresholdValue":{ + "propertyOrder":1014, + "title":"Threshold value for the field Path inside CEF message", + "type":"integer" + }, + "closedLoopEventStatus":{ + "propertyOrder":1010, + "title":"Closed Loop Event Status of the threshold", + "type":"string", + "enum":[ + "ONSET", + "ABATED" + ] + }, + "closedLoopControlName":{ + "propertyOrder":1009, + "title":"Closed Loop Control Name associated with the threshold", + "type":"string" + }, + "version":{ + "propertyOrder":1015, + "title":"Version number associated with the threshold", + "type":"string" + }, + "direction":{ + "propertyOrder":1011, + "title":"Direction of the threshold", + "type":"string", + "enum":[ + "LESS", + "LESS_OR_EQUAL", + "GREATER", + "GREATER_OR_EQUAL", + "EQUAL" + ] + } + } + } + }, + "policyName":{ + "propertyOrder":1005, + "title":"TCA Policy Scope Name", + "type":"string" + }, + "signature":{ + "propertyOrder":1017, + "title":"Signature", + "required":[ + "filter_clause" + ], + "properties":{ + "filter_clause":{ + "propertyOrder":30002, + "qschema":{ + "filters":[ + { + "plugin":"datetimepicker", + "operators":[ + "equals" + ], + "minLength":1, + "id":"timeEpoch", + "label":"timeEpoch", + "type":"datetime", + "input_event":"dp.change", + "validation":{ + "format":"YYYY/MM/DD HH:mm:ss" + } + } + ] + }, + "minLength":1, + "title":"Filter Clause", + "type":"qbldr" + } + } + }, + "controlLoopSchemaType":{ + "propertyOrder":1003, + "title":"Specifies Control Loop Schema Type for the event Name e.g. VNF, VM", + "type":"string", + "enum":[ + "VM", + "VNF" + ] + }, + "policyScope":{ + "propertyOrder":1006, + "title":"TCA Policy Scope", + "type":"string" + }, + "context":{ + "propertyOrder":1016, + "options":{ + "enum_titles":[ + "PROD" + ] + }, + "title":"TCA Policy Dummy Context", + "type":"string", + "enum":[ + "PROD" + ] + }, + "eventName":{ + "propertyOrder":1004, + "title":"Event name to which thresholds need to be applied", + "type":"string" + } + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/test/resources/tosca/tosca_with_metadata.yaml b/src/test/resources/tosca/tosca_with_metadata.yaml new file mode 100644 index 000000000..5967d1569 --- /dev/null +++ b/src/test/resources/tosca/tosca_with_metadata.yaml @@ -0,0 +1,162 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +policy_types: + onap.policies.Monitoring: + derived_from: tosca.policies.Root + description: a base policy type for all policies that governs monitoring provisioning + onap.policies.monitoring.cdap.tca.hi.lo.app: + derived_from: onap.policies.Monitoring + version: 1.0.0 + properties: + tca_policy: + type: map + description: TCA Policy JSON + entry_schema: + type: onap.datatypes.monitoring.tca_policy + metadata: + policy_model_type: onap.policies.monitoring.cdap.tca.hi.lo.app + acronym: tca + +data_types: + onap.datatypes.monitoring.metricsPerEventName: + derived_from: tosca.datatypes.Root + properties: + controlLoopSchemaType: + type: string + required: true + description: Specifies Control Loop Schema Type for the event Name e.g. VNF, VM + constraints: + - valid_values: + - VM + - VNF + eventName: + type: string + required: true + description: Event name to which thresholds need to be applied + policyName: + type: string + required: true + description: TCA Policy Scope Name + policyScope: + type: string + required: true + description: TCA Policy Scope + policyVersion: + type: string + required: true + description: TCA Policy Scope Version + thresholds: + type: list + required: true + description: Thresholds associated with eventName + entry_schema: + type: onap.datatypes.monitoring.thresholds + onap.datatypes.monitoring.tca_policy: + derived_from: tosca.datatypes.Root + properties: + domain: + type: string + required: true + description: Domain name to which TCA needs to be applied + default: measurementsForVfScaling + constraints: + - equal: measurementsForVfScaling + metricsPerEventName: + type: list + required: true + description: Contains eventName and threshold details that need to be applied to given eventName + entry_schema: + type: onap.datatypes.monitoring.metricsPerEventName + onap.datatypes.monitoring.thresholds: + derived_from: tosca.datatypes.Root + properties: + closedLoopControlName: + type: string + required: true + description: Closed Loop Control Name associated with the threshold + closedLoopEventStatus: + type: string + required: true + description: Closed Loop Event Status of the threshold + constraints: + - valid_values: + - ONSET + - ABATED + direction: + type: string + required: true + description: Direction of the threshold + constraints: + - valid_values: + - LESS + - LESS_OR_EQUAL + - GREATER + - GREATER_OR_EQUAL + - EQUAL + fieldPath: + type: string + required: true + description: Json field Path as per CEF message which needs to be analyzed for TCA + constraints: + - valid_values: + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated + - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait + - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage + - $.event.measurementsForVfScalingFields.meanRequestLatency + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree + - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed + - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value + severity: + type: string + required: true + description: Threshold Event Severity + constraints: + - valid_values: + - CRITICAL + - MAJOR + - MINOR + - WARNING + - NORMAL + thresholdValue: + type: integer + required: true + description: Threshold value for the field Path inside CEF message + version: + type: string + required: true + description: Version number associated with the threshold |