diff options
author | Jessica Wagantall <jwagantall@linuxfoundation.org> | 2020-12-08 09:33:13 -0800 |
---|---|---|
committer | Jessica Wagantall <jwagantall@linuxfoundation.org> | 2020-12-08 09:33:25 -0800 |
commit | bfc36d8cb714661eb00ba805d7858872cbce5308 (patch) | |
tree | 99052cc69000d791187d45381b4253353c77bef1 /src/main | |
parent | dcd4bab11134095747a90d05f97a578b7d909520 (diff) | |
parent | 1083012bb7376c63d26b7caf9e6251d736342e30 (diff) |
Merge branch 'master' of /home/jwagantall/linuxfoundation/onap/IT-21108/clamp
Signed-off-by: Jessica Wagantall <jwagantall@linuxfoundation.org>
Diffstat (limited to 'src/main')
178 files changed, 26951 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 |