diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5601d3bbb232b817dddb815531d4697e507721ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target/ +.project +.classpath +/.settings diff --git a/Dockerfile.bugzilla b/Dockerfile.bugzilla new file mode 100644 index 0000000000000000000000000000000000000000..117ba2d4f13b7b329745f71f6c3d397691ff53f8 --- /dev/null +++ b/Dockerfile.bugzilla @@ -0,0 +1,6 @@ +FROM ibm-semeru-runtimes:open-17.0.7_7-jdk +MAINTAINER openslice.io +RUN mkdir /opt/shareclasses +RUN mkdir -p /opt/openslice/lib/ +COPY target/org.etsi.osl.bugzilla-1.2.0-SNAPSHOT.jar /opt/openslice/lib/ +CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses","-jar", "/opt/openslice/lib/org.etsi.osl.bugzilla-1.2.0-SNAPSHOT.jar"] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f5455d4b2a29e8f438efa1a5d73a3f9c454ebdb --- /dev/null +++ b/pom.xml @@ -0,0 +1,215 @@ + + 4.0.0 + + + org.etsi.osl + org.etsi.osl.main + 1.2.0-SNAPSHOT + ../org.etsi.osl.main + + + org.etsi.osl.bugzilla + + org.etsi.osl.bugzilla + http://maven.apache.org + + + UTF-8 + UTF-8 + ${spring-boot-version} + ${spring-cloud-consul-version} + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot-version} + pom + import + + + + org.apache.camel.springboot + camel-spring-boot-dependencies + ${camel.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-cache + + + + + org.apache.camel.springboot + camel-http-starter + + + + + org.apache.camel.springboot + camel-undertow-starter + + + org.springframework.boot + spring-boot-starter-undertow + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + + org.springframework.boot + spring-boot-starter-activemq + + + org.apache.activemq + activemq-amqp + test + + + org.apache.qpid + proton-j + + + + + org.messaginghub + pooled-jms + + + + + + org.apache.camel.springboot + camel-spring-boot-starter + + + org.apache.activemq + activemq-pool + + + org.apache.camel + camel-activemq + + + org.apache.activemq + activemq-broker + + + + + org.apache.camel.springboot + camel-service-starter + + + org.apache.camel + camel-jackson + + + org.apache.camel + camel-http + + + org.apache.camel + camel-base + + + org.apache.camel + camel-http-common + + + org.apache.camel + camel-stream + + + com.h2database + h2 + + + + + org.etsi.osl + org.etsi.osl.model + ${project.version} + + + org.etsi.osl + org.etsi.osl.tmf.api + ${project.version} + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-version} + + + + repackage + + + + + + + + + + diff --git a/python.example b/python.example new file mode 100644 index 0000000000000000000000000000000000000000..881746e146d076aaf03bca5d737cb827bd74ee6d --- /dev/null +++ b/python.example @@ -0,0 +1,29 @@ +Python clients can use stomp to exhange things + +pip install stomp.py + + +simple.py: + +****************************************************** +import time +import sys + +import stomp + +hosts = [('localhost', 61613)] +conn = stomp.Connection(host_and_ports=hosts) +#conn.set_listener('', MyListener()) +conn.start() +conn.connect('admin', 'admin', wait=True,headers = {'client-id': 'clientname'} ) + +#conn.subscribe(destination='/topic/users.create', id=1, ack='auto') + +conn.send(body=' '.join(sys.argv[1:]), destination='/topic/users.create') + +time.sleep(2) +conn.disconnect() +****************************************************** + +run: python simple.py '{"name":"CT", "email":"tranoris@example.com"}' + diff --git a/src/main/java/org/etsi/osl/bugzilla/ActiveMQComponentConfig.java b/src/main/java/org/etsi/osl/bugzilla/ActiveMQComponentConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..c7a4e69db435278d02c86c5ae8af18121a67613e --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/ActiveMQComponentConfig.java @@ -0,0 +1,42 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package org.etsi.osl.bugzilla; + + +import org.apache.camel.component.activemq.ActiveMQComponent; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import jakarta.jms.ConnectionFactory; + +/** + * @author ctranoris + * + */ +@Configuration +public class ActiveMQComponentConfig { + + @Bean(name = "activemq") + public ActiveMQComponent createComponent(ConnectionFactory factory) { + ActiveMQComponent activeMQComponent = new ActiveMQComponent(); + activeMQComponent.setConnectionFactory(factory); + return activeMQComponent; + } +} diff --git a/src/main/java/org/etsi/osl/bugzilla/BugzillaClient.java b/src/main/java/org/etsi/osl/bugzilla/BugzillaClient.java new file mode 100644 index 0000000000000000000000000000000000000000..1d5ce6631a943c024d18b4c649f2da0613e76060 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/BugzillaClient.java @@ -0,0 +1,967 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + + +import org.apache.camel.CamelContext; +import org.apache.camel.FluentProducerTemplate; +import org.apache.camel.ProducerTemplate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.etsi.osl.bugzilla.model.Bug; +import org.etsi.osl.bugzilla.model.Comment; +import org.etsi.osl.bugzilla.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.etsi.osl.model.CompositeExperimentOnBoardDescriptor; +import org.etsi.osl.model.CompositeVxFOnBoardDescriptor; +import org.etsi.osl.model.DeploymentDescriptor; +import org.etsi.osl.model.DeploymentDescriptorStatus; +import org.etsi.osl.model.DeploymentDescriptorVxFPlacement; +import org.etsi.osl.model.ExperimentMetadata; +import org.etsi.osl.model.ExperimentOnBoardDescriptor; +import org.etsi.osl.model.IMANOCommunicationStatus; +import org.etsi.osl.model.OnBoardingStatus; +import org.etsi.osl.model.PortalUser; +import org.etsi.osl.model.VFImage; +import org.etsi.osl.model.ValidationJob; +import org.etsi.osl.model.ValidationStatus; +import org.etsi.osl.model.VxFMetadata; +import org.etsi.osl.model.VxFOnBoardedDescriptor; +import org.etsi.osl.tmf.common.model.Notification; +import org.etsi.osl.tmf.common.model.service.Characteristic; +import org.etsi.osl.tmf.common.model.service.Note; +import org.etsi.osl.tmf.common.model.service.ServiceRef; +import org.etsi.osl.tmf.pm632.model.ContactMedium; +import org.etsi.osl.tmf.pm632.model.Individual; +import org.etsi.osl.tmf.pm632.model.IndividualCreateEvent; +import org.etsi.osl.tmf.prm669.model.RelatedParty; +import org.etsi.osl.tmf.so641.model.ServiceOrder; +import org.etsi.osl.tmf.so641.model.ServiceOrderAttributeValueChangeNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderCreateNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderDeleteNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderItem; +import org.etsi.osl.tmf.so641.model.ServiceOrderStateChangeNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderStateType; +import jakarta.validation.Valid; + + + +/** + * @author ctranoris + * + */ +@Configuration +public class BugzillaClient { + + private static final transient Log logger = LogFactory.getLog(BugzillaClient.class.getName()); + + + static CamelContext contxt; + + @Value("${portaltitle}") + private String PORTAL_TITLE = ""; + + @Value("${maindomain}") + private String MAIN_CFS_URL; + + + @Value("${main_operations_product}") + private String MAIN_OPERATIONS_PRODUCT; + + + /** */ + private static final String BUGHEADER = "THIS IS AN AUTOMATED ISSUE CREATED BY OPENSLICE SERVICES.\n" + + "*********************************************************\n"; + + + @Autowired + public void setActx(CamelContext actx) { + BugzillaClient.contxt = actx; + logger.info( "BugzillaClient configure() contxt = " + contxt); + } + + + /** + * Request to the activeMQ channel to get VxF metadata + * @param vxfid + * @return + */ + private VxFMetadata getVxFFromID(long vxfid) { + ProducerTemplate template = contxt.createProducerTemplate(); + String ret = template + .requestBody( "activemq:queue:getVxFByID", vxfid , String.class); + + VxFMetadata vxf; + try { + ObjectMapper mapper = new ObjectMapper(); + vxf = mapper.readValue( ret, VxFMetadata.class); + return vxf; + } catch (JsonParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (JsonMappingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + return null; + } + + + /** + * Request to the activeMQ channel to get VxF metadata + * @param vxfid + * @return + */ + private ExperimentMetadata getNSDFromID(long nsdid) { + ProducerTemplate template = contxt.createProducerTemplate(); + String ret = template + .requestBody( "activemq:queue:getNSDByID", nsdid , String.class); + + ExperimentMetadata nsd; + try { + ObjectMapper mapper = new ObjectMapper(); + nsd = mapper.readValue( ret, ExperimentMetadata.class); + return nsd; + } catch (JsonParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (JsonMappingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + return null; + } + + public static Comment createComment( String description ) { + + Comment c = new Comment(); + c.setComment(description); + c.setIs_markdown( false ); + c.setIs_private( false ); + return c; + } + + + public static User transformUser2BugzillaUser( final PortalUser portalUser ){ + + //PortalUser portalUser = portalRepositoryRef.getUserByID(portaluserid); + User u = new User(); + u.setEmail( portalUser.getEmail() ); + u.setFullName( portalUser.getFirstname() + "" + portalUser.getLastname() ); + u.setPassword( UUID.randomUUID().toString() ); //no password. The user needs to reset it in the other system (e.g. Bugzilla) + + + logger.info( "In : portaluser getLastname = " + portalUser.getLastname() ); + + + return u; + + } + + + public static User transformIndividual2BugzillaUser( final IndividualCreateEvent individualCreateEvent ){ + + @Valid + Individual indv = individualCreateEvent.getEvent().getIndividual(); + //PortalUser portalUser = portalRepositoryRef.getUserByID(portaluserid); + User u = new User(); + + for (ContactMedium cm : indv.getContactMedium() ) { + if ( cm.getCharacteristic().getEmailAddress()!=null ) { + u.setEmail( cm.getCharacteristic().getEmailAddress()); + } + } + + u.setFullName( indv.getFullName() + "" + indv.getFamilyName() ); + u.setPassword( UUID.randomUUID().toString() ); //no password. The user needs to reset it in the other system (e.g. Bugzilla) + + + logger.info( "In : Individual getFamilyName = " + indv.getFamilyName() + " email: " + u.getEmail()); + + + return u; + + } + + + public Bug transformNSInstantiation2BugBody( DeploymentDescriptor descriptor ) { + + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] Deployment Request of NSD:" + descriptor.getExperiment().getName() + ",User: " + descriptor.getOwner().getUsername(); + String alias = descriptor.getUuid() ; + + String description = getDeploymentDescription( descriptor ); + + String status= "CONFIRMED"; + String resolution = null; + + if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.TERMINATED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.COMPLETED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.RUNNING )) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.REJECTED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.FAILED )) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description, descriptor.getOwner().getEmail(), status, resolution); + // Create the email and assign it to the mentor. + b.setAssignedTo(descriptor.getMentor().getEmail()); + return b; + } + + public Bug transformNSTermination2BugBody( DeploymentDescriptor descriptor ) { + + logger.debug("transformNSTermination2BugBody"+descriptor.toString()); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] Deployment Request of NSD:" + descriptor.getExperiment().getName() + ",User: " + descriptor.getOwner().getUsername(); + String alias = descriptor.getUuid() ; + + String description = getDeploymentDescription( descriptor ); + + String status= "CONFIRMED"; + String resolution = null; + + if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.COMPLETED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.TERMINATION_FAILED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.FAILED )) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description, descriptor.getOwner().getEmail(), status, resolution); + return b; + + } + + public Bug transformNSDeletion2BugBody( DeploymentDescriptor descriptor ) { + + + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] Deployment Request of NSD:" + descriptor.getExperiment().getName() + ",User: " + descriptor.getOwner().getUsername(); + String alias = descriptor.getUuid() ; + + String description = getDeploymentDescription( descriptor ); + + String status= "CONFIRMED"; + String resolution = null; + + if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.COMPLETED || descriptor.getStatus() == DeploymentDescriptorStatus.FAILED_OSM_REMOVED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( descriptor.getStatus() == DeploymentDescriptorStatus.DELETION_FAILED ) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + Bug b = createBug(product, component, summary, alias, description, descriptor.getOwner().getEmail(), status, resolution); + return b; + + } + + public Bug transformDeployment2BugBody( final DeploymentDescriptor descriptor) { + logger.debug("transformDeployment2BugBody"+descriptor.toString()); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] Deployment Request of NSD:" + descriptor.getExperiment().getName() + ",User: " + descriptor.getOwner().getUsername(); + String alias = descriptor.getUuid() ; + + String description = getDeploymentDescription( descriptor ); + + String status= "CONFIRMED"; + String resolution = null; + if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.SCHEDULED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.INSTANTIATING ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.RUNNING )) { + status = "IN_PROGRESS"; + component = "NSD Deployment Request" ; + } else if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.COMPLETED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( ( descriptor.getStatus() == DeploymentDescriptorStatus.REJECTED ) || ( descriptor.getStatus() == DeploymentDescriptorStatus.FAILED )) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description, descriptor.getOwner().getEmail(), status, resolution); + // Create the email and assign it to the mentor. + if ( descriptor.getMentor() != null) { + b.setAssignedTo(descriptor.getMentor().getEmail()); + } + return b; + } + + + public Comment transformDeployment2BugComment( DeploymentDescriptor descriptor ) { + + String description = getDeploymentDescription( descriptor ); + + Comment b = createComment( description); + + return b; + } + + + /** + * @param descriptor + * @return + */ + private String getDeploymentDescription( DeploymentDescriptor descriptor ) { + + StringBuilder description = new StringBuilder( BUGHEADER ); + + description.append( "\nSTATUS: " + descriptor.getStatus() + "\n"); + if ( descriptor.getStartDate() != null ) { + description.append( "\nFeedback: " + descriptor.getFeedback() ); + description.append("\nScheduled Start Date: " + descriptor.getStartDate().toString() ); + description.append( "\nScheduled End Date: " + descriptor.getEndDate().toString() ); + } else { + description.append( "\nNOT YET SCHEDULED \n"); + } + + + description.append( + "\nDeployment Request by user :" + descriptor.getOwner().getUsername() + +"\nHere are the details:\n" + + "\nExperiment name: " + descriptor.getName() + + "\nDescription: " + descriptor.getDescription() + + "\nDate Created: " + descriptor.getDateCreated().toString() + + "\nRequested Tentative Start date: " + descriptor.getStartReqDate().toString() + + "\nRequested Tentative End date: " + descriptor.getEndReqDate().toString() + + "\nExperiment (NSD) requested: " + descriptor.getExperiment().getName() ); + + + if ( descriptor.getMentor() != null ) { + description.append( "\nMentor: " + descriptor.getMentor().getFirstname() + " " + descriptor.getMentor().getLastname() + ", " + descriptor.getMentor().getOrganization() ) ; + } + + + description.append( "\nConstituent VxF Placement " ) ; + for (DeploymentDescriptorVxFPlacement pl : descriptor.getVxfPlacements()) { + if ( ( pl.getConstituentVxF().getVxfref() != null ) && ( pl.getInfrastructure() != null )) { + description.append( "\n Constituent VxF: " + pl.getConstituentVxF().getVxfref().getName() + " - Infrastructure: " + pl.getInfrastructure().getName() ); + } + } + + + + + description.append( "\n*************************************************\n"); + description.append( "\nTo manage this Request, go to: " + MAIN_CFS_URL + "/#!/edit_deployment/" + descriptor.getId() ); + return description.toString(); + } + + + + + + /** + * @param product + * @param component + * @param summary + * @param alias + * @param description + * @param ccemail + * @return + */ + public Bug createBug(String product, String component, String summary, String alias, String description, String ccemail, String status, String resolution ) { + + Bug b = new Bug(); + b.setProduct(product); + b.setComponent(component); + b.setSummary(summary); + b.setVersion( "unspecified" ); + List aliaslist = new ArrayList<>(); + aliaslist.add(alias); + b.setAlias( aliaslist ); + List cclist = new ArrayList<>(); + cclist.add( ccemail ); + b.setCc(cclist); + b.setDescription(description.toString()); + b.setStatus(status); + b.setResolution(resolution); + + return b; + } + + + + + + public Bug transformVxFValidation2BugBody( VxFMetadata vxf ) { + + logger.info( "In transformVxFValidation2BugBody: alias = " + vxf.getUuid()); + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Validation" ; + String summary = "[PORTAL] Validation Request for VxF:" + vxf.getName() + ", Owner: " + vxf.getOwner().getUsername(); + String alias = vxf.getUuid() ; + + StringBuilder description = new StringBuilder( BUGHEADER ); + + description.append( "\n\n VxF: " + vxf.getName()); + description.append( "\n Owner: " + vxf.getOwner().getUsername() ); + description.append( "\n Vendor: " + vxf.getVendor() ); + description.append( "\n Version: " + vxf.getVersion() ); + description.append( "\n Archive: " + vxf.getPackageLocation() ); + description.append( "\n UUID: " + vxf.getUuid() ); + description.append( "\n ID: " + vxf.getId() ); + description.append( "\n Date Created: " + vxf.getDateCreated().toString() ); + description.append( "\n Date Updated: " + vxf.getDateUpdated().toString() ); + + description.append( "\n VDU Images: " ); + for (VFImage img : vxf.getVfimagesVDU() ) { + description.append( "\n\t Image: " + img.getName() + ", " + MAIN_CFS_URL + "/#!/vfimage_view/" + img.getId() ); + + } + + description.append( "\n" ); + description.append( "\n Validation Status: " + vxf.getValidationStatus() ); + //description.append( "\n Certified: " + String.valueOf( vxf.isCertified() ).toUpperCase() ); + + description.append( "\n Validation jobs: " ); + for (ValidationJob j : vxf.getValidationJobs()) { + description.append( "\n\t" + j.getDateCreated().toString() + ", id:" + j.getJobid() + ", Status:" + j.getValidationStatus() + ", Output:" + j.getOutputLog() ); + } + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/vxf_edit/" + vxf.getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( vxf.getValidationStatus().equals( ValidationStatus.UNDER_REVIEW ) ) { + status = "CONFIRMED"; + } else if ( vxf.getValidationStatus().equals( ValidationStatus.COMPLETED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } + + + Bug b = createBug(product, component, summary, alias, description.toString(), vxf.getOwner().getEmail(), status, resolution); + + return b; + } + + public Bug transformVxFAutomaticOnBoarding2BugBodyCompObj( final CompositeVxFOnBoardDescriptor compvxfobd ) { + return transformVxFAutomaticOnBoarding2BugBody( compvxfobd.getObd() ); + } + + public Bug transformVxFAutomaticOnBoarding2BugBody( final VxFOnBoardedDescriptor obd ) { + + VxFOnBoardedDescriptor vxfobd = obd; + + logger.info( "In transformVxFAutomaticOnBoarding2BugBody: alias = " + vxfobd.getUuid()); + + + + VxFMetadata avxf = getVxFFromID( vxfobd.getVxfid() ); + + if ( avxf==null ) { + logger.error( "Cannot retrieve VxF for vxf ID = " + vxfobd.getVxfid() ); + return null; + } + vxfobd.setVxf(avxf); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Onboarding" ; + String summary = "[PORTAL] OSM OnBoarding Action for VxF:" + vxfobd.getVxf().getName() + ", Owner: " + vxfobd.getVxf().getOwner().getUsername(); + String alias = vxfobd.getUuid() ; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " VxF OSM ONBOARDING ACTION \n" + + "**************************************************************\n"); + + description.append( "\n\n VxF: " + vxfobd.getVxf().getName()); + description.append( "\n Owner: " + vxfobd.getVxf().getOwner().getUsername() ); + description.append( "\n Vendor: " + vxfobd.getVxf().getVendor() ); + description.append( "\n Version: " + vxfobd.getVxf().getVersion() ); + description.append( "\n Archive: " + vxfobd.getVxf().getPackageLocation() ); + description.append( "\n UUID: " + vxfobd.getVxf().getUuid() ); + description.append( "\n ID: " + vxfobd.getVxf().getId() ); + description.append( "\n Date Created: " + vxfobd.getVxf().getDateCreated().toString() ); + description.append( "\n Date Updated: " + vxfobd.getVxf().getDateUpdated().toString() ); + + + description.append( "\n" ); + description.append( "\n VxF OnBoarding Status: " + vxfobd.getOnBoardingStatus() ); + description.append( "\n VxF OnBoarding Feedback: " + vxfobd.getFeedbackMessage() ); + description.append( "\n Last Onboarding: " + vxfobd.getLastOnboarding()); + description.append( "\n Last Onboarding Deploy ID: " + vxfobd.getDeployId()); + description.append( "\n Onboarding MANO provider: " + vxfobd.getObMANOprovider().getName() ); + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/vxf_edit/" + vxfobd.getVxf().getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( vxfobd.getOnBoardingStatus().equals( OnBoardingStatus.ONBOARDED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( vxfobd.getOnBoardingStatus().equals( OnBoardingStatus.FAILED ) ) { +// status = "CONFIRMED"; + status = "RESOLVED"; + resolution = "INVALID"; + } + + Bug b = createBug(product, component, summary, alias, description.toString(), vxfobd.getVxf().getOwner().getEmail(), status, resolution); + return b; + } + + + + + + + public Bug transformNSDValidation2BugBody(ExperimentMetadata nsd) { + logger.info( "In transformNSDValidation2BugBody: alias = " + nsd.getUuid()); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Validation" ; + String summary = "[PORTAL] Validation Request for NSD:" + nsd.getName() + ", Owner: " + nsd.getOwner().getUsername(); + String alias = nsd.getUuid() ; + + StringBuilder description = new StringBuilder( BUGHEADER ); + description.append( "\n Validation Status: " + nsd.getValidationStatus() ); + description.append( "\n Valid: " + String.valueOf( nsd.isValid() ).toUpperCase() ); + + description.append( "\n\n NSD: " + nsd.getName()); + description.append( "\n Owner: " + nsd.getOwner().getUsername() ); + description.append( "\n Vendor: " + nsd.getVendor() ); + description.append( "\n Version: " + nsd.getVersion() ); + description.append( "\n Archive: " + nsd.getPackageLocation() ); + description.append( "\n UUID: " + nsd.getUuid() ); + description.append( "\n ID: " + nsd.getId() ); + description.append( "\n Date Created: " + nsd.getDateCreated().toString() ); + description.append( "\n Date Updated: " + nsd.getDateUpdated().toString() ); + + + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/experiment_edit/" + nsd.getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( nsd.getValidationStatus().equals( ValidationStatus.UNDER_REVIEW ) ) { + status = "IN_PROGRESS"; + } else if ( nsd.isValid() && ( nsd.getValidationStatus().equals( ValidationStatus.COMPLETED ) ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( !nsd.isValid() && ( nsd.getValidationStatus().equals( ValidationStatus.COMPLETED ) ) ) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description.toString(), nsd.getOwner().getEmail(), status, resolution); + + return b; + } + + public Bug transformNSDAutomaticOnBoarding2BugBodyCompObj(CompositeExperimentOnBoardDescriptor compoexpobd ) { + return transformNSDAutomaticOnBoarding2BugBody(compoexpobd.getObd() ); + } + + public Bug transformNSDAutomaticOnBoarding2BugBody(ExperimentOnBoardDescriptor obd ) { + + ExperimentOnBoardDescriptor uexpobd = obd; + + logger.info( "In transformNSDAutomaticOnBoarding2BugBody: alias = " + uexpobd.getUuid()); + ExperimentMetadata ansd = getNSDFromID( uexpobd.getExperimentid() ); + + if ( ansd==null ) { + logger.error( "Cannot retrieve NSD for vxf ID = " + uexpobd.getExperimentid() ); + return null; + } + uexpobd.setExperiment(ansd); + + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Onboarding" ; + String summary = "[PORTAL] OSM OnBoarding Action for NSD:" + uexpobd.getExperiment().getName() + ", Owner: " + uexpobd.getExperiment().getOwner().getUsername(); + String alias = uexpobd.getUuid() ; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " NSD OSM ONBOARDING ACTION \n" + + "**************************************************************\n"); + + description.append( "\n\n NSD: " + uexpobd.getExperiment().getName()); + description.append( "\n Owner: " + uexpobd.getExperiment().getOwner().getUsername() ); + description.append( "\n Vendor: " + uexpobd.getExperiment().getVendor() ); + description.append( "\n Version: " + uexpobd.getExperiment().getVersion() ); + description.append( "\n Archive: " + uexpobd.getExperiment().getPackageLocation() ); + description.append( "\n UUID: " + uexpobd.getExperiment().getUuid() ); + description.append( "\n ID: " + uexpobd.getExperiment().getId() ); + description.append( "\n Date Created: " + uexpobd.getExperiment().getDateCreated().toString() ); + description.append( "\n Date Updated: " + uexpobd.getExperiment().getDateUpdated().toString() ); + + + description.append( "\n" ); + description.append( "\n NSD OnBoarding Status: " + uexpobd.getOnBoardingStatus() ); + description.append( "\n NSD OnBoarding Feedback: " + uexpobd.getFeedbackMessage() ); + description.append( "\n Last Onboarding: " + uexpobd.getLastOnboarding()); + description.append( "\n Last Onboarding Deploy ID: " + uexpobd.getDeployId()); + description.append( "\n Onboarding MANO provider: " + uexpobd.getObMANOprovider().getName() ); + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/experiment_edit/" + uexpobd.getExperiment().getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( uexpobd.getOnBoardingStatus().equals( OnBoardingStatus.ONBOARDED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( uexpobd.getOnBoardingStatus().equals( OnBoardingStatus.FAILED ) ) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description.toString(), uexpobd.getExperiment().getOwner().getEmail(), status, resolution); + return b; + } + + + public Bug transformVxFAutomaticOffBoarding2BugBody( VxFOnBoardedDescriptor obd ) { + + + VxFOnBoardedDescriptor vxfobd = obd; + logger.info( "In transformVxFAutomaticOnBoarding2BugBody: alias = " + vxfobd.getUuid()); + + VxFMetadata avxf = getVxFFromID( vxfobd.getVxfid() ); + if ( avxf==null ) { + logger.error( "Cannot retrieve VxF for vxf ID = " + vxfobd.getVxfid() ); + return null; + } + vxfobd.setVxf(avxf); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Offboarding" ; + String summary = "[PORTAL] OSM OffBoarding Action for VxF:" + vxfobd.getVxf().getName() + ", Owner: " + vxfobd.getVxf().getOwner().getUsername(); + String alias = vxfobd.getUuid() ; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " VxF OSM OFFBOARDING ACTION \n" + + "**************************************************************\n"); + + description.append( "\n\n VxF: " + vxfobd.getVxf().getName()); + description.append( "\n Owner: " + vxfobd.getVxf().getOwner().getUsername() ); + description.append( "\n Vendor: " + vxfobd.getVxf().getVendor() ); + description.append( "\n Version: " + vxfobd.getVxf().getVersion() ); + description.append( "\n Archive: " + vxfobd.getVxf().getPackageLocation() ); + description.append( "\n UUID: " + vxfobd.getVxf().getUuid() ); + description.append( "\n ID: " + vxfobd.getVxf().getId() ); + description.append( "\n Date Created: " + vxfobd.getVxf().getDateCreated().toString() ); + description.append( "\n Date Updated: " + vxfobd.getVxf().getDateUpdated().toString() ); + + + description.append( "\n" ); + description.append( "\n VxF OffBoarding Status: " + vxfobd.getOnBoardingStatus() ); + description.append( "\n VxF OffBoarding Feedback: " + vxfobd.getFeedbackMessage() ); + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/vxf_edit/" + vxfobd.getVxf().getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( vxfobd.getOnBoardingStatus().equals( OnBoardingStatus.OFFBOARDED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( vxfobd.getOnBoardingStatus().equals( OnBoardingStatus.FAILED ) ) { + status = "CONFIRMED"; +// status = "RESOLVED"; +// resolution = "INVALID"; + } + + Bug b = createBug(product, component, summary, alias, description.toString(), vxfobd.getVxf().getOwner().getEmail(), status, resolution); + return b; + } + + public Bug transformNSDAutomaticOffBoarding2BugBody( ExperimentOnBoardDescriptor obd ) { + + + ExperimentOnBoardDescriptor uexpobd = obd; + ExperimentMetadata ansd = getNSDFromID( uexpobd.getExperimentid() ); + + if ( ansd==null ) { + logger.error( "Cannot retrieve NSD for vxf ID = " + uexpobd.getExperimentid() ); + return null; + } + uexpobd.setExperiment(ansd); + + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Offboarding" ; + String summary = "[PORTAL] OSM OffBoarding Action for NSD:" + uexpobd.getExperiment().getName() + ", Owner: " + uexpobd.getExperiment().getOwner().getUsername(); + String alias = uexpobd.getUuid() ; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " NSD OSM OFFBOARDING ACTION \n" + + "**************************************************************\n"); + + description.append( "\n\n NSD: " + uexpobd.getExperiment().getName()); + description.append( "\n Owner: " + uexpobd.getExperiment().getOwner().getUsername() ); + description.append( "\n Vendor: " + uexpobd.getExperiment().getVendor() ); + description.append( "\n Version: " + uexpobd.getExperiment().getVersion() ); + description.append( "\n Archive: " + uexpobd.getExperiment().getPackageLocation() ); + description.append( "\n UUID: " + uexpobd.getExperiment().getUuid() ); + description.append( "\n ID: " + uexpobd.getExperiment().getId() ); + description.append( "\n Date Created: " + uexpobd.getExperiment().getDateCreated().toString() ); + description.append( "\n Date Updated: " + uexpobd.getExperiment().getDateUpdated().toString() ); + + + description.append( "\n" ); + description.append( "\n NSD OffBoarding Status: " + uexpobd.getOnBoardingStatus() ); + description.append( "\n NSD OffBoarding Feedback: " + uexpobd.getFeedbackMessage() ); + + description.append( "\n\n*************************************************\n"); + description.append( "\nTo manage this , go to: " + MAIN_CFS_URL + "/#!/experiment_edit/" + uexpobd.getExperiment().getId() ); + + String status= "CONFIRMED"; + String resolution = null; + if ( uexpobd.getOnBoardingStatus().equals( OnBoardingStatus.OFFBOARDED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( uexpobd.getOnBoardingStatus().equals( OnBoardingStatus.FAILED ) ) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + + Bug b = createBug(product, component, summary, alias, description.toString(), uexpobd.getExperiment().getOwner().getEmail(), status, resolution); + return b; + } + + + + public Bug transformOSMCommunicationFail2BugBody() { + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] OSM Communication Action"; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " OSM COMMUNICATION ACTION FAILURE\n" + + "**************************************************************\n"); + + description.append( "\n\n "+ IMANOCommunicationStatus.getMessage()); + + String status= "CONFIRMED"; + String resolution = null; + + Bug b = createBug(product, component, summary, IMANOCommunicationStatus.getOsmCommunicationStatusUUID(), description.toString(), null, status, resolution); + return b; + } + + public Bug transformOSMCommunicationSuccess2BugBody() { + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] OSM Communication Action"; + + StringBuilder description = new StringBuilder( "**************************************************************\n" + + "THIS IS AN AUTOMATED ISSUE UPDATE CREATED BY PORTAL API.\n" + + "**************************************************************\n" + + " OSM COMMUNICATION ACTION RESTORED\n" + + "**************************************************************\n"); + + description.append( "\n\n "+ IMANOCommunicationStatus.getMessage()); + + String status = "RESOLVED"; + String resolution = "FIXED"; + + Bug b = createBug(product, component, summary, IMANOCommunicationStatus.getOsmCommunicationStatusUUID(), description.toString(), null, status, resolution); + return b; + } + + + public Bug transformNotification2BugBody( final Notification n) { + logger.debug("transformNotification2BugBody"+n.toString()); + + ServiceOrder so = null; + String status= "CONFIRMED"; + if ( n instanceof ServiceOrderCreateNotification) { + so = ((ServiceOrderCreateNotification)n).getEvent().getServiceOrder(); + logger.debug("ServiceOrder=" + so.toString()); + }else if ( n instanceof ServiceOrderStateChangeNotification ) { + so = ((ServiceOrderStateChangeNotification)n).getEvent().getServiceOrder(); + logger.debug("ServiceOrder=" + so.toString()); + } else if ( n instanceof ServiceOrderAttributeValueChangeNotification ) { + so = ((ServiceOrderAttributeValueChangeNotification)n).getEvent().getServiceOrder(); + logger.debug("ServiceOrder=" + so.toString()); + } else if ( n instanceof ServiceOrderDeleteNotification ) { + so = ((ServiceOrderAttributeValueChangeNotification)n).getEvent().getServiceOrder(); + logger.debug("ServiceOrder=" + so.toString()); + } +// else if ( n instanceof ServiceOrderStateChangeNotification) { +// msgtopic = EVENT_SERVICE_ORDER_STATE_CHANGED; +// } else if ( n instanceof ServiceOrderDeleteNotification) { +// msgtopic = EVENT_SERVICE_ORDER_DELETE; +// } else if ( n instanceof ServiceOrderAttributeValueChangeNotification) { +// msgtopic = EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED; +// } + if (so == null) { + return null; + } + String alias = so.getUuid() ; + String product = MAIN_OPERATIONS_PRODUCT; + String component = "Operations Support" ; + String summary = "[PORTAL] Service Order:" + alias ; + + + String description = getServiceOrderDescription( so ); + + String resolution = null; + if ( ( so.getState().equals( ServiceOrderStateType.INPROGRESS )) || + so.getState().equals( ServiceOrderStateType.HELD ) || + so.getState().equals( ServiceOrderStateType.PARTIAL ) || + so.getState().equals( ServiceOrderStateType.PENDING )) { + status = "IN_PROGRESS"; + } else if ( so.getState().equals( ServiceOrderStateType.COMPLETED ) ) { + status = "RESOLVED"; + resolution = "FIXED"; + } else if ( ( so.getState().equals( ServiceOrderStateType.REJECTED )) || + ( so.getState().equals( ServiceOrderStateType.FAILED ) )) { + status = "RESOLVED"; + resolution = "INVALID"; + } + + RelatedParty rp = so.getOrderRequester(); + String email = "tranoris@ece.upatras.gr"; + if ( rp.getExtendedInfo() !=null ) { + email =rp.getExtendedInfo(); + } + Bug b = createBug(product, component, summary, alias, description, email, status, resolution); + + return b; + } + + /** + * @param descriptor + * @return + */ + private String getServiceOrderDescription( ServiceOrder so ) { + + StringBuilder description = new StringBuilder( BUGHEADER ); + + //description.append( "\n" + so.toString() + "\n"); + + + description.append( "\n Order id: " + so.getId() ); + description.append( "\n State: " + so.getState().name() ); + description.append( "\n Order Date: " + so.getOrderDate() ); + description.append( "\n Requested Start Date: " + so.getRequestedStartDateString() ); + description.append( "\n Requested Completion Date: " + so.getRequestedCompletionDateString() ); + description.append( "\n Start Date: " + so.getStartDateString() ); + description.append( "\n Expected Completion Date: " + so.getExpectedCompletionDateString() ); + + + description.append( "\n Parties:"); + for (RelatedParty rp : so.getRelatedParty()) { + description.append( "\n - " + rp.getRole() + ", " + rp.getName() + ", " + rp.getExtendedInfo() ); + } + + description.append( "\n Notes:"); + + + //Convert a Stream to List + List notes = so.getNote() + .stream() + .sorted( Comparator.comparing(Note::getDate , Comparator.nullsLast(Comparator.reverseOrder())) ) + .collect(Collectors.toList()); + + for (Note note : notes) { + description.append( "\n - " + note.getDateString() +" [" + note.getAuthor() + "]:" ); + description.append( "\n " + note.getText() ); + } + description.append( "\n "); + + description.append( "\n Order Items:"); + for (ServiceOrderItem soi : so.getOrderItem()) { + description.append( "\n\t ************************************" ); + description.append( "\n\t Order Item: " + soi.getId() ); + description.append( "\n\t Action: " + soi.getAction() ); + description.append( "\n\t State: " + soi.getState() ); + description.append( "\n\t ** Service Details **" ); + description.append( "\n\t - Service Specification Name: " ); + description.append( "\n\t " + soi.getService().getServiceSpecification().getName() ); + description.append( "\n\t - Service Specification Version: " + soi.getService().getServiceSpecification().getVersion() ); + description.append( "\n\t - Service State: " + soi.getService().getState() ); + description.append( "\n\t - Service Name: " + soi.getService().getName() ); + description.append( "\n\t - Characteristics" ); + for (Characteristic c : soi.getService().getServiceCharacteristic()) { + description.append( "\n\t\t - " + c.getName() ); + description.append( "\n\t\t " + c.getValue().getValue() + " (" + c.getValue().getAlias() + ")" ); + } + + description.append( "\n\t - SupportingServices" ); + for (ServiceRef c : soi.getService().getSupportingService() ) { + description.append( "\n\t\t - " + c.getName() ); + } + } + + + + + description.append( "\n*************************************************\n"); + description.append( "\nTo manage this Request, go to: " + MAIN_CFS_URL + "/services/service_order/" + so.getId() ); + return description.toString(); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/BugzillaRouteBuilder.java b/src/main/java/org/etsi/osl/bugzilla/BugzillaRouteBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..520c8bed5dd628aec2b9cc74aff6838214816b31 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/BugzillaRouteBuilder.java @@ -0,0 +1,674 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla; + + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Map; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.camel.CamelExecutionException; +import org.apache.camel.Exchange; +import org.apache.camel.FluentProducerTemplate; +import org.apache.camel.LoggingLevel; +import org.apache.camel.Predicate; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.http.HttpClientConfigurer; +import org.apache.camel.component.http.HttpComponent; +import org.apache.camel.model.dataformat.JsonLibrary; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.etsi.osl.bugzilla.model.Bug; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.etsi.osl.tmf.pm632.model.IndividualCreateEvent; +import org.etsi.osl.tmf.so641.model.ServiceOrderAttributeValueChangeNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderCreateNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderDeleteNotification; +import org.etsi.osl.tmf.so641.model.ServiceOrderStateChangeNotification; +import jakarta.annotation.PostConstruct; + +/** + * @author ctranoris + * + */ +/** + * @author ctranoris + * + */ +@Configuration +@Component +public class BugzillaRouteBuilder extends RouteBuilder { + + /** + * In consul + * Under config/openslice/osdata there will be a YAML properties + * bugzilla: + * host: locahost:8080 + * key: xxxxxxx + */ + + @Value("${bugzillaurl}") + private String BUGZILLAURL = "localhost:443/bugzilla"; + @Value("${bugzillakey}") + private String BUGZILLAKEY = ""; + + @Value("${EVENT_SERVICE_ORDER_CREATE}") + private String EVENT_SERVICE_ORDER_CREATE = ""; + + @Value("${EVENT_SERVICE_ORDER_STATE_CHANGED}") + private String EVENT_SERVICE_ORDER_STATE_CHANGED = ""; + + @Value("${EVENT_SERVICE_ORDER_DELETE}") + private String EVENT_SERVICE_ORDER_DELETE = ""; + + @Value("${EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED}") + private String EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED = ""; + + + @Value("${EVENT_SERVICE_CREATE}") + private String EVENT_SERVICE_CREATE = ""; + + @Value("${EVENT_SERVICE_STATE_CHANGED}") + private String EVENT_SERVICE_STATE_CHANGED = ""; + + @Value("${EVENT_SERVICE_DELETE}") + private String EVENT_SERVICE_DELETE = ""; + + @Value("${EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED}") + private String EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED = ""; + + + @Value("${EVENT_INDIVIDUAL_CREATE}") + private String EVENT_INDIVIDUAL_CREATE = ""; + + @PostConstruct + public void postConstruct() { + // to validate if properties are loaded + System.out.println("** bugzilla.host: " + BUGZILLAURL); + System.out.println("** bugzilla.key: " + BUGZILLAKEY); + } + + private static final transient Log logger = LogFactory.getLog( BugzillaRouteBuilder.class.getName() ); + + private static final TrustManager[] DUMMY_TRUST_MANAGERS = new TrustManager[] { new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[] {}; + } + + } }; + + public void configure() { + + +// if ( ( BUGZILLAURL == null ) || BUGZILLAURL.equals( "" ) ){ +// return; //no routing towards Bugzilla +// } +// if ( ( BUGZILLAKEY == null ) || BUGZILLAKEY.equals( "" ) ){ +// return;//no routing towards Bugzilla +// } +// + + HttpComponent httpComponent = getContext().getComponent("https", HttpComponent.class); + httpComponent.setHttpClientConfigurer(new MyHttpClientConfigurer()); + + String usedBUGZILLAURL = "https://" + BUGZILLAURL; + if ( BUGZILLAURL.contains("http:")) { + usedBUGZILLAURL = BUGZILLAURL; + } else if ( BUGZILLAURL.contains("https:")) { + usedBUGZILLAURL = BUGZILLAURL.replace("https", "https"); + } + + /** + * Create New Issue in Bugzilla. The body is a {@link Bug} + */ + from("direct:bugzilla.newIssue") + .marshal().json( JsonLibrary.Jackson, true) + .convertBodyTo( String.class ).to("stream:out") +// .errorHandler(deadLetterChannel("direct:dlq_bugzilla") +// .maximumRedeliveries( 4 ) //let's try for the next 120 mins to send it.... +// .redeliveryDelay( 60000 ).useOriginalMessage() +// .deadLetterHandleNewException( false ) +// //.logExhaustedMessageHistory(false) +// .logExhausted(true) +// .logHandled(true) +// //.retriesExhaustedLogLevel(LoggingLevel.WARN) +// .retryAttemptedLogLevel( LoggingLevel.WARN) ) + .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.POST)) + .toD( usedBUGZILLAURL + "/rest.cgi/bug?api_key="+ BUGZILLAKEY +"&throwExceptionOnFailure=true") + .to("log:DEBUG?showBody=true&showHeaders=true") + .to("stream:out"); + + /** + * Update issue in bugzilla. The body is a {@link Bug}. header.uuid is used to select the bug + */ + from("direct:bugzilla.updateIssue") + .marshal().json( JsonLibrary.Jackson, true) + .convertBodyTo( String.class ).to("stream:out") + .errorHandler(deadLetterChannel("direct:dlq_bugzilla") + .maximumRedeliveries( 4 ) //let's try for the next 120 minutess to send it.... + .redeliveryDelay( 60000 ).useOriginalMessage() +// .deadLetterHandleNewException( false ) + //.logExhaustedMessageHistory(false) + .logExhausted(true) + .logHandled(true) + //.retriesExhaustedLogLevel(LoggingLevel.WARN) + .retryAttemptedLogLevel( LoggingLevel.WARN) ) + .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.PUT)) + .toD( usedBUGZILLAURL + "/rest.cgi/bug/${header.uuid}?api_key="+ BUGZILLAKEY +"&throwExceptionOnFailure=true") + .to("log:DEBUG?showBody=true&showHeaders=true") + .to("stream:out"); + + + + + /** + * Create user route, from activemq:topic:users.create + */ + + from("activemq:topic:users.create").routeId( "users-create-route" ) + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.PortalUser.class, true) + .bean( BugzillaClient.class, "transformUser2BugzillaUser") + .marshal().json( JsonLibrary.Jackson, true) + .convertBodyTo( String.class ).to("stream:out") +// .errorHandler(deadLetterChannel("direct:dlq_users") +// .maximumRedeliveries( 4 ) //let's try 10 times to send it.... +// .redeliveryDelay( 60000 ).useOriginalMessage() +// .deadLetterHandleNewException( false ) +// //.logExhaustedMessageHistory(false) +// .logExhausted(true) +// .logHandled(true) +// //.retriesExhaustedLogLevel(LoggingLevel.WARN) +// .retryAttemptedLogLevel( LoggingLevel.WARN) ) + .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.POST)) + .toD( usedBUGZILLAURL + "/rest.cgi/user?api_key="+ BUGZILLAKEY +"&throwExceptionOnFailure=true") + .to("stream:out"); + + +// from("timer://test?delay=10s&period=30000") +// .bean( BugzillaClient.class, "getPortalUser") +// .marshal().json( JsonLibrary.Jackson, true) +// .convertBodyTo( String.class ) +// .to( "activemq:topic:users.create" ); + + + /** + * Create user route, from Individual event + */ + + + + from( EVENT_INDIVIDUAL_CREATE ) + .unmarshal().json( JsonLibrary.Jackson, IndividualCreateEvent.class, true) + .bean( BugzillaClient.class, "transformIndividual2BugzillaUser") + .marshal().json( JsonLibrary.Jackson, true) + .convertBodyTo( String.class ).to("stream:out") + .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.POST)) + .toD( usedBUGZILLAURL + "/rest.cgi/user?api_key="+ BUGZILLAKEY +"&throwExceptionOnFailure=true") + .to("stream:out"); + + + /** + * dead Letter Queue Users if everything fails to connect + */ + from("direct:dlq_users") + .setBody() +// .body(DeploymentDescriptor.class) +// .bean( BugzillaClient.class, "transformDeployment2BugBody") + .body(String.class) + .to("stream:out"); + + + from("direct:bugzilla.bugmanage") + .choice() + .when( issueExists ) + .log( "Update ISSUE for ${body.alias} !" ) + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue") + .endChoice() + .otherwise() + .log( "New ISSUE for ${body.alias} !" ) + .to("direct:bugzilla.newIssue") + .endChoice(); + + +// /** +// * Create VxF Validate New Route +// */ +// String jenkinsURL = null; +//// if (PortalRepository.getPropertyByName("jenkinsciurl").getValue() != null) { +//// jenkinsURL = PortalRepository.getPropertyByName("jenkinsciurl").getValue(); +//// } +// if ( ( jenkinsURL != null ) && ( !jenkinsURL.equals( "" ) ) ){ +// from("activemq:topic:vxf.new.validation") +// .delay(30000) +// .bean( BugzillaClient.class, "transformVxFValidation2BugBody") +// .to("direct:bugzilla.newIssue"); +// } + + /** + * Service Order Topics + */ + + + from( EVENT_SERVICE_ORDER_CREATE ) + .unmarshal().json( JsonLibrary.Jackson, ServiceOrderCreateNotification.class, true) + .bean( BugzillaClient.class, "transformNotification2BugBody") + .to("direct:bugzilla.newIssue"); + + from( EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED ) + .unmarshal().json( JsonLibrary.Jackson, ServiceOrderAttributeValueChangeNotification.class, true) + .bean( BugzillaClient.class, "transformNotification2BugBody") + .to("direct:bugzilla.bugmanage"); + + from( EVENT_SERVICE_ORDER_DELETE ) + .unmarshal().json( JsonLibrary.Jackson, ServiceOrderDeleteNotification.class, true) + .bean( BugzillaClient.class, "transformNotification2BugBody") + .to("direct:bugzilla.bugmanage"); + + from( EVENT_SERVICE_ORDER_STATE_CHANGED ) + .unmarshal().json( JsonLibrary.Jackson, ServiceOrderStateChangeNotification.class, true) + .bean( BugzillaClient.class, "transformNotification2BugBody") + .to("direct:bugzilla.bugmanage"); + + + + + /** + * Update Validation Route + */ + from("activemq:topic:vxf.validationresult.update") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.ValidationStatus.class, true) + .bean( BugzillaClient.class, "transformVxFValidation2BugBody") + .to("direct:bugzilla.bugmanage"); + + + /** + * Create VxF Validate New Route + */ + from("activemq:topic:vxf.onboard") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.VxFOnBoardedDescriptor.class, true) + .bean( BugzillaClient.class, "transformVxFAutomaticOnBoarding2BugBody") + .to("direct:bugzilla.newIssue"); + + from("activemq:topic:vxf.onBoardByCompositeObj") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.CompositeVxFOnBoardDescriptor.class, true) + .bean( BugzillaClient.class, "transformVxFAutomaticOnBoarding2BugBodyCompObj") + .to("direct:bugzilla.newIssue"); + + /** + * Create VxF OffBoard New Route + */ + from("activemq:topic:vxf.offboard") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.VxFOnBoardedDescriptor.class, true) + .bean( BugzillaClient.class, "transformVxFAutomaticOffBoarding2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic OnBoarding Route Success + */ + from("activemq:topic:vxf.onboard.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.VxFOnBoardedDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformVxFAutomaticOnBoarding2BugBody") + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue"); + //.to("direct:bugzilla.bugmanage"); + + + /** + * Automatic OnBoarding Route Fail + */ + from("activemq:topic:vxf.onboard.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.VxFOnBoardedDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformVxFAutomaticOnBoarding2BugBody") + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue"); + //.to("direct:bugzilla.bugmanage"); + + + + + /** + * IMPORTANT NOTE: NSD ISSUE VALIDATION IS DISABLED FOR NOW + * SINCE THERE IS NO nsd VALIDATION! + //Create NSD Validate New Route + from("activemq:topic:nsd.validate.new") + .bean( BugzillaClient.class, "transformNSDValidation2BugBody") + .to("direct:bugzilla.newIssue"); + + //Create NSD Validation Update Route + from("activemq:topic:nsd.validate.update") + .bean( BugzillaClient.class, "transformNSDValidation2BugBody") + .choice() + .when( issueExists ) + .log( "Update ISSUE for validating ${body.alias} !" ) + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue") + .endChoice() + .otherwise() + .log( "New ISSUE for validating ${body.alias} !" ) + .to("direct:bugzilla.newIssue") + .endChoice(); + + */ + + /** + * Create NSD onboard New Route + */ + from("activemq:topic:nsd.onboard") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.ExperimentOnBoardDescriptor.class, true) + .bean( BugzillaClient.class, "transformNSDAutomaticOnBoarding2BugBody") + .to("direct:bugzilla.newIssue"); + + /** + * Create NSD onboard New Route + */ + from("activemq:topic:nsd.onBoardByCompositeObj") + .log( "activemq:topic:nsd.onBoardByCompositeObj for ${body} !" ) + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.CompositeExperimentOnBoardDescriptor.class, true) + .bean( BugzillaClient.class, "transformNSDAutomaticOnBoarding2BugBodyCompObj") + .to("direct:bugzilla.newIssue"); + + /** + * Create NSD offboard New Route + */ + from("activemq:topic:nsd.offboard") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.ExperimentOnBoardDescriptor.class, true) + .bean( BugzillaClient.class, "transformNSDAutomaticOffBoarding2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic OnBoarding Route Success + */ + from("activemq:topic:nsd.onboard.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.ExperimentOnBoardDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSDAutomaticOnBoarding2BugBody") + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue"); + + + /** + * Automatic OnBoarding Route Fail + */ + from("activemq:topic:nsd.onboard.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.ExperimentOnBoardDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSDAutomaticOnBoarding2BugBody") + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue"); + + + /** + * Automatic NS Instantiation Route Success + */ + from("activemq:topic:nsd.deployment.instantiation.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSInstantiation2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Termination Route Success + */ + from("activemq:topic:nsd.deployment.termination.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSInstantiation2BugBody") + .to("direct:bugzilla.bugmanage"); + + from("activemq:topic:nsd.deployment.termination.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSInstantiation2BugBody") + .to("direct:bugzilla.bugmanage"); + + + /** + * Create Deployment Route Issue + */ + from("activemq:topic:deployments.create") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .bean( BugzillaClient.class, "transformDeployment2BugBody") + .to("direct:bugzilla.newIssue"); + + /** + * Update Deployment Route + */ + from("activemq:topic:deployments.update") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .bean( BugzillaClient.class, "transformDeployment2BugBody") + .process( BugHeaderExtractProcessor ) + .to("direct:bugzilla.updateIssue"); + + /** + * OSM5 Communication + */ + from("activemq:topic:communication.osm.fail") + .delay(30000) + .bean( BugzillaClient.class, "transformOSMCommunicationFail2BugBody") + .to("direct:bugzilla.bugmanage"); + + from("activemq:topic:communication.osm5.success") + .delay(30000) + .bean( BugzillaClient.class, "transformOSMCommunicationSuccess2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * NS Scheduling Route + */ + from("activemq:topic:nsd.schedule") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSInstantiation2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Instantiation Route Fail + */ + from("activemq:topic:nsd.deployment.instantiation.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSInstantiation2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Termination Route Success + */ + from("activemq:topic:nsd.instance.termination.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSTermination2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Termination Route Fail + */ + from("activemq:topic:nsd.instance.termination.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSTermination2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Deletion Route Success + */ + from("activemq:topic:nsd.instance.deletion.success") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSDeletion2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Automatic NS Deletion Route Fail + */ + from("activemq:topic:nsd.instance.deletion.fail") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformNSDeletion2BugBody") + .to("direct:bugzilla.bugmanage"); + + /** + * Reject Deployment Route Issue + */ + from("activemq:topic:nsd.deployment.reject") + .unmarshal().json( JsonLibrary.Jackson, org.etsi.osl.model.DeploymentDescriptor.class, true) + .delay(30000) + .bean( BugzillaClient.class, "transformDeployment2BugBody") + .to("direct:bugzilla.bugmanage"); + + from("direct:issue.get") + .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.GET)) + .toD( usedBUGZILLAURL + "/rest.cgi/bug/${header.uuid}?api_key="+ BUGZILLAKEY +"&throwExceptionOnFailure=true"); + + + /** + * dead Letter Queue if everything fails to connect + */ + from("direct:dlq_bugzilla") + .setBody() + .body(String.class) + .to("stream:out"); +// + } + + Predicate issueExists = new Predicate() { + + @Override + public boolean matches(Exchange exchange) { + + Bug aBug = exchange.getIn().getBody( Bug.class ); + Object m = null; + try{ + FluentProducerTemplate template = exchange.getContext().createFluentProducerTemplate() + .withHeader("uuid", aBug.getAliasFirst() ) + .to( "direct:issue.get"); + m = template.request(); + }catch( CamelExecutionException e){ + logger.error( "issueExists: " + e.getMessage() ); + //e.printStackTrace(); + } + + if ( m != null ) + { + return true; + } + else { + return false; + } + + } + }; + + Processor BugHeaderExtractProcessor = new Processor() { + + @Override + public void process(Exchange exchange) throws Exception { + + Map headers = exchange.getIn().getHeaders(); + Bug aBug = exchange.getIn().getBody( Bug.class ); + headers.put("uuid", aBug.getAliasFirst() ); + exchange.getMessage().setHeaders(headers); + + //copy Description to Comment + aBug.setComment( BugzillaClient.createComment( aBug.getDescription() ) ); + //delete Description + aBug.setDescription( null ); + aBug.setAlias( null ); //dont put any Alias + aBug.setCc( null ); + + exchange.getMessage().setBody( aBug ); + // copy attachements from IN to OUT to propagate them + //exchange.getOut().setAttachments(exchange.getIn().getAttachments()); + + } + }; + + + + + + public class MyHttpClientConfigurer implements HttpClientConfigurer { + + @Override + public void configureHttpClient(HttpClientBuilder hc) { + + HttpClientConnectionManager ccm = new PoolingHttpClientConnectionManager( createRegistry() ); + hc.setConnectionManager(ccm); + + + } + + + private Registry createRegistry() { + + RegistryBuilder registryBuilder = RegistryBuilder.create(); + try { +// HostnameVerifier hostnameVerifier = getVerifyHostName() ? new DefaultHostnameVerifier() +// : NoopHostnameVerifier.INSTANCE; + HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; + var ssl = SSLContext.getInstance("TLS"); + ssl.init(null, DUMMY_TRUST_MANAGERS, null); + SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(ssl.getSocketFactory(), + hostnameVerifier); + registryBuilder.register("https", sslConnectionFactory); + registryBuilder.register("http", PlainConnectionSocketFactory.INSTANCE); + + return registryBuilder.build(); + } catch (Exception e) { + throw new IllegalStateException("Failure trying to create scheme registry", e); + } + } + + } + + +} + + diff --git a/src/main/java/org/etsi/osl/bugzilla/BugzillaService.java b/src/main/java/org/etsi/osl/bugzilla/BugzillaService.java new file mode 100644 index 0000000000000000000000000000000000000000..739854b7396d5681becae098248544561b013c9d --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/BugzillaService.java @@ -0,0 +1,45 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package org.etsi.osl.bugzilla; + +//import org.apache.camel.zipkin.starter.CamelZipkin; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + + +/** + * @author ctranoris + * + * based on + * https://github.com/apache/camel/tree/master/examples/camel-example-spring-boot-activemq + * https://github.com/indrabasak/spring-consul-example + */ + +@SpringBootApplication +//@EnableRetry +@EnableAutoConfiguration +@EnableConfigurationProperties +public class BugzillaService { + public static void main(String[] args) { + SpringApplication.run( BugzillaService.class, args); + } +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/AssignedToDetail.java b/src/main/java/org/etsi/osl/bugzilla/model/AssignedToDetail.java new file mode 100644 index 0000000000000000000000000000000000000000..1130f647ecc9add1f16def3b19ee0b005355c7ee --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/AssignedToDetail.java @@ -0,0 +1,102 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class AssignedToDetail { + + @JsonProperty("email") + private String email; + @JsonProperty("id") + private Integer id; + @JsonProperty("name") + private String name; + @JsonProperty("real_name") + private String realName; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("email") + public String getEmail() { + return email; + } + + @JsonProperty("email") + public void setEmail(String email) { + this.email = email; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("real_name") + public String getRealName() { + return realName; + } + + @JsonProperty("real_name") + public void setRealName(String realName) { + this.realName = realName; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/Bug.java b/src/main/java/org/etsi/osl/bugzilla/model/Bug.java new file mode 100644 index 0000000000000000000000000000000000000000..07d7020feef2173b744f8a731bdf215fb132feb4 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/Bug.java @@ -0,0 +1,539 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class Bug { + + @JsonProperty("alias") + private List alias = null; + @JsonProperty("assigned_to") + private String assignedTo; + @JsonProperty("assigned_to_detail") + private AssignedToDetail assignedToDetail; + @JsonProperty("blocks") + private List blocks = null; + @JsonProperty("cc") + private List cc = null; + @JsonProperty("cc_detail") + private List ccDetail = null; + @JsonProperty("classification") + private String classification; + @JsonProperty("component") + private String component; + @JsonProperty("comment") + private Comment comment; + @JsonProperty("creation_time") + private String creationTime; + @JsonProperty("creator") + private String creator; + @JsonProperty("creator_detail") + private CreatorDetail creatorDetail; + @JsonProperty("deadline") + private Object deadline; + @JsonProperty("depends_on") + private List dependsOn = null; + @JsonProperty("dupe_of") + private Object dupeOf; + @JsonProperty("flags") + private List flags = null; + @JsonProperty("groups") + private List groups = null; + @JsonProperty("id") + private Integer id; + @JsonProperty("is_cc_accessible") + private Boolean isCcAccessible; + @JsonProperty("is_confirmed") + private Boolean isConfirmed; + @JsonProperty("is_creator_accessible") + private Boolean isCreatorAccessible; + @JsonProperty("is_open") + private Boolean isOpen; + @JsonProperty("keywords") + private List keywords = null; + @JsonProperty("last_change_time") + private String lastChangeTime; + @JsonProperty("op_sys") + private String opSys; + @JsonProperty("platform") + private String platform; + @JsonProperty("priority") + private String priority; + @JsonProperty("product") + private String product; + @JsonProperty("qa_contact") + private String qaContact; + @JsonProperty("resolution") + private String resolution; + @JsonProperty("see_also") + private List seeAlso = null; + @JsonProperty("severity") + private String severity; + @JsonProperty("status") + private String status; + @JsonProperty("summary") + private String summary; + @JsonProperty("description") + private String description; + @JsonProperty("target_milestone") + private String targetMilestone; + @JsonProperty("url") + private String url; + @JsonProperty("version") + private String version; + @JsonProperty("whiteboard") + private String whiteboard; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("alias") + public List getAlias() { + return alias; + } + + @JsonIgnore + public String getAliasFirst() { + + if ( alias!= null ) { + if ( alias.size() >0 ) { + return (String) alias.get(0).toString(); + } + } + + return ""; + } + + + + @JsonProperty("alias") + public void setAlias(List alias) { + this.alias = alias; + } + + @JsonProperty("assigned_to") + public String getAssignedTo() { + return assignedTo; + } + + @JsonProperty("assigned_to") + public void setAssignedTo(String assignedTo) { + this.assignedTo = assignedTo; + } + + @JsonProperty("assigned_to_detail") + public AssignedToDetail getAssignedToDetail() { + return assignedToDetail; + } + + @JsonProperty("assigned_to_detail") + public void setAssignedToDetail(AssignedToDetail assignedToDetail) { + this.assignedToDetail = assignedToDetail; + } + + @JsonProperty("blocks") + public List getBlocks() { + return blocks; + } + + @JsonProperty("blocks") + public void setBlocks(List blocks) { + this.blocks = blocks; + } + + @JsonProperty("cc") + public List getCc() { + return cc; + } + + @JsonProperty("cc") + public void setCc(List cc) { + this.cc = cc; + } + + @JsonProperty("cc_detail") + public List getCcDetail() { + return ccDetail; + } + + @JsonProperty("cc_detail") + public void setCcDetail(List ccDetail) { + this.ccDetail = ccDetail; + } + + @JsonProperty("classification") + public String getClassification() { + return classification; + } + + @JsonProperty("classification") + public void setClassification(String classification) { + this.classification = classification; + } + + @JsonProperty("component") + public String getComponent() { + return component; + } + + @JsonProperty("component") + public void setComponent(String component) { + this.component = component; + } + + @JsonProperty("comment") + public Comment getComment() { + return comment; + } + + @JsonProperty("comment") + public void setComment(Comment comment) { + this.comment = comment; + } + + @JsonProperty("creation_time") + public String getCreationTime() { + return creationTime; + } + + @JsonProperty("creation_time") + public void setCreationTime(String creationTime) { + this.creationTime = creationTime; + } + + @JsonProperty("creator") + public String getCreator() { + return creator; + } + + @JsonProperty("creator") + public void setCreator(String creator) { + this.creator = creator; + } + + @JsonProperty("creator_detail") + public CreatorDetail getCreatorDetail() { + return creatorDetail; + } + + @JsonProperty("creator_detail") + public void setCreatorDetail(CreatorDetail creatorDetail) { + this.creatorDetail = creatorDetail; + } + + @JsonProperty("deadline") + public Object getDeadline() { + return deadline; + } + + @JsonProperty("deadline") + public void setDeadline(Object deadline) { + this.deadline = deadline; + } + + @JsonProperty("depends_on") + public List getDependsOn() { + return dependsOn; + } + + @JsonProperty("depends_on") + public void setDependsOn(List dependsOn) { + this.dependsOn = dependsOn; + } + + @JsonProperty("dupe_of") + public Object getDupeOf() { + return dupeOf; + } + + @JsonProperty("dupe_of") + public void setDupeOf(Object dupeOf) { + this.dupeOf = dupeOf; + } + + @JsonProperty("flags") + public List getFlags() { + return flags; + } + + @JsonProperty("flags") + public void setFlags(List flags) { + this.flags = flags; + } + + @JsonProperty("groups") + public List getGroups() { + return groups; + } + + @JsonProperty("groups") + public void setGroups(List groups) { + this.groups = groups; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("is_cc_accessible") + public Boolean getIsCcAccessible() { + return isCcAccessible; + } + + @JsonProperty("is_cc_accessible") + public void setIsCcAccessible(Boolean isCcAccessible) { + this.isCcAccessible = isCcAccessible; + } + + @JsonProperty("is_confirmed") + public Boolean getIsConfirmed() { + return isConfirmed; + } + + @JsonProperty("is_confirmed") + public void setIsConfirmed(Boolean isConfirmed) { + this.isConfirmed = isConfirmed; + } + + @JsonProperty("is_creator_accessible") + public Boolean getIsCreatorAccessible() { + return isCreatorAccessible; + } + + @JsonProperty("is_creator_accessible") + public void setIsCreatorAccessible(Boolean isCreatorAccessible) { + this.isCreatorAccessible = isCreatorAccessible; + } + + @JsonProperty("is_open") + public Boolean getIsOpen() { + return isOpen; + } + + @JsonProperty("is_open") + public void setIsOpen(Boolean isOpen) { + this.isOpen = isOpen; + } + + @JsonProperty("keywords") + public List getKeywords() { + return keywords; + } + + @JsonProperty("keywords") + public void setKeywords(List keywords) { + this.keywords = keywords; + } + + @JsonProperty("last_change_time") + public String getLastChangeTime() { + return lastChangeTime; + } + + @JsonProperty("last_change_time") + public void setLastChangeTime(String lastChangeTime) { + this.lastChangeTime = lastChangeTime; + } + + @JsonProperty("op_sys") + public String getOpSys() { + return opSys; + } + + @JsonProperty("op_sys") + public void setOpSys(String opSys) { + this.opSys = opSys; + } + + @JsonProperty("platform") + public String getPlatform() { + return platform; + } + + @JsonProperty("platform") + public void setPlatform(String platform) { + this.platform = platform; + } + + @JsonProperty("priority") + public String getPriority() { + return priority; + } + + @JsonProperty("priority") + public void setPriority(String priority) { + this.priority = priority; + } + + @JsonProperty("product") + public String getProduct() { + return product; + } + + @JsonProperty("product") + public void setProduct(String product) { + this.product = product; + } + + @JsonProperty("qa_contact") + public String getQaContact() { + return qaContact; + } + + @JsonProperty("qa_contact") + public void setQaContact(String qaContact) { + this.qaContact = qaContact; + } + + @JsonProperty("resolution") + public String getResolution() { + return resolution; + } + + @JsonProperty("resolution") + public void setResolution(String resolution) { + this.resolution = resolution; + } + + @JsonProperty("see_also") + public List getSeeAlso() { + return seeAlso; + } + + @JsonProperty("see_also") + public void setSeeAlso(List seeAlso) { + this.seeAlso = seeAlso; + } + + @JsonProperty("severity") + public String getSeverity() { + return severity; + } + + @JsonProperty("severity") + public void setSeverity(String severity) { + this.severity = severity; + } + + @JsonProperty("status") + public String getStatus() { + return status; + } + + @JsonProperty("status") + public void setStatus(String status) { + this.status = status; + } + + @JsonProperty("summary") + public String getSummary() { + return summary; + } + + @JsonProperty("summary") + public void setSummary(String summary) { + this.summary = summary; + } + + @JsonProperty("description") + public String getDescription() { + return description; + } + + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + + + @JsonProperty("target_milestone") + public String getTargetMilestone() { + return targetMilestone; + } + + @JsonProperty("target_milestone") + public void setTargetMilestone(String targetMilestone) { + this.targetMilestone = targetMilestone; + } + + @JsonProperty("url") + public String getUrl() { + return url; + } + + @JsonProperty("url") + public void setUrl(String url) { + this.url = url; + } + + @JsonProperty("version") + public String getVersion() { + return version; + } + + @JsonProperty("version") + public void setVersion(String version) { + this.version = version; + } + + @JsonProperty("whiteboard") + public String getWhiteboard() { + return whiteboard; + } + + @JsonProperty("whiteboard") + public void setWhiteboard(String whiteboard) { + this.whiteboard = whiteboard; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/Bugs.java b/src/main/java/org/etsi/osl/bugzilla/model/Bugs.java new file mode 100644 index 0000000000000000000000000000000000000000..8be5217bcc2bfcf76969ad5f01c8a7aa296bc7ec --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/Bugs.java @@ -0,0 +1,79 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class Bugs { + + @JsonProperty("bugs") + private List bugs = null; + @JsonProperty("faults") + private List faults = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("bugs") + public List getBugs() { + return bugs; + } + + @JsonProperty("bugs") + public void setBugs(List bugs) { + this.bugs = bugs; + } + + @JsonProperty("faults") + public List getFaults() { + return faults; + } + + @JsonProperty("faults") + public void setFaults(List faults) { + this.faults = faults; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/CcDetail.java b/src/main/java/org/etsi/osl/bugzilla/model/CcDetail.java new file mode 100644 index 0000000000000000000000000000000000000000..94e5eef821dafc00f165bc972e88b6ac57c2e54f --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/CcDetail.java @@ -0,0 +1,102 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class CcDetail { + + @JsonProperty("email") + private String email; + @JsonProperty("id") + private Integer id; + @JsonProperty("name") + private String name; + @JsonProperty("real_name") + private String realName; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("email") + public String getEmail() { + return email; + } + + @JsonProperty("email") + public void setEmail(String email) { + this.email = email; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("real_name") + public String getRealName() { + return realName; + } + + @JsonProperty("real_name") + public void setRealName(String realName) { + this.realName = realName; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/Comment.java b/src/main/java/org/etsi/osl/bugzilla/model/Comment.java new file mode 100644 index 0000000000000000000000000000000000000000..e7c370c7d05fa4e3434151a5f1faf25551af5e72 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/Comment.java @@ -0,0 +1,175 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class Comment { + +// @JsonProperty("id") +// private int id; + @JsonProperty("bug_id") + private int bug_id; + @JsonProperty("attachment_id") + private int attachment_id; + @JsonProperty("count") + private int count; + @JsonProperty("comment") + private String comment; + @JsonProperty("creator") + private String creator; + @JsonProperty("time") + private String time; + @JsonProperty("creation_time") + private String creation_time; + @JsonProperty("is_private") + private Boolean is_private; + @JsonProperty("is_markdown") + private Boolean is_markdown; + @JsonProperty("tags") + private List tags = null; + +// +// @JsonProperty("id") +// public int getId() { +// return id; +// } +// +// @JsonProperty("id") +// public void setId(int id) { +// this.id = id; +// } + + @JsonProperty("bug_id") + public int getBug_id() { + return bug_id; + } + + @JsonProperty("bug_id") + public void setBug_id(int bug_id) { + this.bug_id = bug_id; + } + + @JsonProperty("attachment_id") + public int getAttachment_id() { + return attachment_id; + } + + @JsonProperty("attachment_id") + public void setAttachment_id(int attachment_id) { + this.attachment_id = attachment_id; + } + + @JsonProperty("count") + public int getCount() { + return count; + } + + @JsonProperty("count") + public void setCount(int count) { + this.count = count; + } + + @JsonProperty("comment") + public String getComment() { + return comment; + } + + @JsonProperty("comment") + public void setComment(String comment) { + this.comment = comment; + } + + @JsonProperty("creator") + public String getCreator() { + return creator; + } + + @JsonProperty("creator") + public void setCreator(String creator) { + this.creator = creator; + } + + @JsonProperty("time") + public String getTime() { + return time; + } + + @JsonProperty("time") + public void setTime(String time) { + this.time = time; + } + + + @JsonProperty("creation_time") + public String getCreation_time() { + return creation_time; + } + + @JsonProperty("creation_time") + public void setCreation_time(String creation_time) { + this.creation_time = creation_time; + } + + @JsonProperty("is_private") + public Boolean getIs_private() { + return is_private; + } + + @JsonProperty("is_private") + public void setIs_private(Boolean is_private) { + this.is_private = is_private; + } + + @JsonProperty("is_markdown") + public Boolean getIs_markdown() { + return is_markdown; + } + + @JsonProperty("is_markdown") + public void setIs_markdown(Boolean is_markdown) { + this.is_markdown = is_markdown; + } + + @JsonProperty("tags") + public List getTags() { + return tags; + } + + @JsonProperty("tags") + public void setTags(List tags) { + this.tags = tags; + } + + + + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/CreatorDetail.java b/src/main/java/org/etsi/osl/bugzilla/model/CreatorDetail.java new file mode 100644 index 0000000000000000000000000000000000000000..e06839d4dbc307dde372bfe2278d5a26d0d976df --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/CreatorDetail.java @@ -0,0 +1,102 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class CreatorDetail { + + @JsonProperty("email") + private String email; + @JsonProperty("id") + private Integer id; + @JsonProperty("name") + private String name; + @JsonProperty("real_name") + private String realName; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("email") + public String getEmail() { + return email; + } + + @JsonProperty("email") + public void setEmail(String email) { + this.email = email; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("real_name") + public String getRealName() { + return realName; + } + + @JsonProperty("real_name") + public void setRealName(String realName) { + this.realName = realName; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/ErrorMsg.java b/src/main/java/org/etsi/osl/bugzilla/model/ErrorMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..a2e1edf90cbd167151ea99e7ba3c7518cb1d15e3 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/ErrorMsg.java @@ -0,0 +1,54 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package org.etsi.osl.bugzilla.model; + +/** + * @author ctranoris + * + */ +public class ErrorMsg { + + String message; + + public ErrorMsg() { + super(); + this.message = ""; + } + + public ErrorMsg(String message) { + super(); + this.message = message; + } + + /** + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * @param message the message to set + */ + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/Group.java b/src/main/java/org/etsi/osl/bugzilla/model/Group.java new file mode 100644 index 0000000000000000000000000000000000000000..76b7380d2c274ccac2daf741df9e416d8adceeae --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/Group.java @@ -0,0 +1,89 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Group { + + @JsonProperty("description") + private String description; + @JsonProperty("id") + private Integer id; + @JsonProperty("name") + private String name; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("description") + public String getDescription() { + return description; + } + + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/User.java b/src/main/java/org/etsi/osl/bugzilla/model/User.java new file mode 100644 index 0000000000000000000000000000000000000000..6825b04aa533407932d56bfd9b39f78139f581f6 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/User.java @@ -0,0 +1,210 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class User { + + @JsonProperty("can_login") + private Boolean canLogin; + @JsonProperty("email") + private String email; + @JsonProperty("login") + private String login; + @JsonProperty("email_enabled") + private Boolean emailEnabled; + @JsonProperty("groups") + private List groups = null; + @JsonProperty("id") + private Integer id; + @JsonProperty("login_denied_text") + private String loginDeniedText; + @JsonProperty("name") + private String name; + @JsonProperty("password") + private String password; + @JsonProperty("real_name") + private String realName; + @JsonProperty("full_name") + private String fullName; + @JsonProperty("saved_reports") + private List savedReports = null; + @JsonProperty("saved_searches") + private List savedSearches = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("can_login") + public Boolean getCanLogin() { + return canLogin; + } + + @JsonProperty("can_login") + public void setCanLogin(Boolean canLogin) { + this.canLogin = canLogin; + } + + @JsonProperty("login") + public String getLogin() { + return login; + } + + @JsonProperty("login") + public void setLogin(String login) { + this.login = login; + } + + @JsonProperty("email") + public String getEmail() { + return email; + } + + @JsonProperty("email") + public void setEmail(String email) { + this.email = email; + } + + @JsonProperty("email_enabled") + public Boolean getEmailEnabled() { + return emailEnabled; + } + + @JsonProperty("email_enabled") + public void setEmailEnabled(Boolean emailEnabled) { + this.emailEnabled = emailEnabled; + } + + @JsonProperty("groups") + public List getGroups() { + return groups; + } + + @JsonProperty("groups") + public void setGroups(List groups) { + this.groups = groups; + } + + @JsonProperty("id") + public Integer getId() { + return id; + } + + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + @JsonProperty("login_denied_text") + public String getLoginDeniedText() { + return loginDeniedText; + } + + @JsonProperty("login_denied_text") + public void setLoginDeniedText(String loginDeniedText) { + this.loginDeniedText = loginDeniedText; + } + + @JsonProperty("password") + public String getPassword() { + return password; + } + + @JsonProperty("password") + public void setPassword(String password) { + this.password = password; + } + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("real_name") + public String getRealName() { + return realName; + } + + @JsonProperty("real_name") + public void setRealName(String realName) { + this.realName = realName; + } + + @JsonProperty("full_name") + public String getFulllName() { + return fullName; + } + + @JsonProperty("full_name") + public void setFullName(String fullName) { + this.fullName = fullName; + } + + @JsonProperty("saved_reports") + public List getSavedReports() { + return savedReports; + } + + @JsonProperty("saved_reports") + public void setSavedReports(List savedReports) { + this.savedReports = savedReports; + } + + @JsonProperty("saved_searches") + public List getSavedSearches() { + return savedSearches; + } + + @JsonProperty("saved_searches") + public void setSavedSearches(List savedSearches) { + this.savedSearches = savedSearches; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/org/etsi/osl/bugzilla/model/Users.java b/src/main/java/org/etsi/osl/bugzilla/model/Users.java new file mode 100644 index 0000000000000000000000000000000000000000..c860e682fb4ced044ea2a1813b7f89447f4cce85 --- /dev/null +++ b/src/main/java/org/etsi/osl/bugzilla/model/Users.java @@ -0,0 +1,68 @@ +/*- + * ========================LICENSE_START================================= + * org.etsi.osl.bugzilla + * %% + * Copyright (C) 2019 openslice.io + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + + + +package org.etsi.osl.bugzilla.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/** + * @author ctranoris + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) + +public class Users { + + @JsonProperty("users") + private List users = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("users") + public List getUsers() { + return users; + } + + @JsonProperty("users") + public void setUsers(List users) { + this.users = users; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0a8ef49652be29eae7befe1f60934babb93d3d5 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,57 @@ + +# For Spring Actuator /info endpoint +info: + artifact: bugzilla-client-service + name: bugzilla-client-service + description: Spring bugzilla-client-service + version: 1.0.0 + +server: + port: 13010 + + +logging: + level: + root: INFO + org.springframework: INFO + org.apache.camel: INFO + + + +spring: + config: + activate: + on-profile: "default" + application: + name: bugzilla-client-service + + + activemq: + brokerUrl: tcp://localhost:61616?jms.watchTopicAdvisories=false + user: artemis + password: artemis + pool: + enabled: true + max-connections: 100 + packages: + trust-all: true + +portaltitle: "openslice" +maindomain: "http://localhost:13000" +main_operations_product: "Openslice Operations" +bugzillaurl: "bugzilla.example.org:443/bugstaging/" +bugzillakey: "" + +#EVENT TOPICS IN Message Bus +EVENT_SERVICE_CREATE: "jms:topic:EVENT.SERVICE.CREATE" +EVENT_SERVICE_STATE_CHANGED: "jms:topic:EVENT.SERVICE.STATECHANGED" +EVENT_SERVICE_DELETE: "jms:topic:EVENT.SERVICE.DELETE" +EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.SERVICE.ATTRCHANGED" +EVENT_SERVICE_ORDER_CREATE: "jms:topic:EVENT.SERVICEORDER.CREATE" +EVENT_SERVICE_ORDER_STATE_CHANGED: "jms:topic:EVENT.SERVICEORDER.STATECHANGED" +EVENT_SERVICE_ORDER_DELETE: "jms:topic:EVENT.SERVICEORDER.DELETE" +EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.SERVICEORDER.ATTRCHANGED" +EVENT_INDIVIDUAL_CREATE: "jms:topic:EVENT.INDIVIDUAL.CREATE" + + + diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000000000000000000000000000000000000..74229cd400fb31f76673214d76c0256f438e4ccc --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,11 @@ + ___ ____ _ _ + / _ \ _ __ ___ _ __ / ___|| (_) ___ ___ + | | | | '_ \ / _ \ '_ \\___ \| | |/ __/ _ \ + | |_| | |_) | __/ | | |___) | | | (_| __/ + \___/| .__/ \___|_| |_|____/|_|_|\___\___| + |_| + __ __________________ + / / __ __ / __/_ __/ __/ _/ + / _ \/ // / / _/ / / _\ \_/ / + /_.__/\_, / /___/ /_/ /___/___/ + /___/ \ No newline at end of file diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391