From ac853c1e7186b10e34e392918af31e4ac62b45c2 Mon Sep 17 00:00:00 2001 From: Michael Hwang Date: Tue, 14 Feb 2017 15:10:16 +0000 Subject: Make first commit Transferring from original dcae project Issue-Id: DCAEGEN2-45 Change-Id: If8500f4a120ec2d27a714c8917f163beb57ee64c Signed-off-by: Michael Hwang --- src/main/java/io/swagger/api/Bootstrap.java | 51 +++ .../DcaeServiceTypesApiServiceFactory.java | 35 ++ .../factories/DcaeServicesApiServiceFactory.java | 47 +++ .../DcaeServicesGroupbyApiServiceFactory.java | 35 ++ .../api/impl/DcaeServiceTypesApiServiceImpl.java | 312 ++++++++++++++++ .../api/impl/DcaeServicesApiServiceImpl.java | 401 +++++++++++++++++++++ .../impl/DcaeServicesGroupbyApiServiceImpl.java | 103 ++++++ 7 files changed, 984 insertions(+) create mode 100644 src/main/java/io/swagger/api/Bootstrap.java create mode 100644 src/main/java/io/swagger/api/factories/DcaeServiceTypesApiServiceFactory.java create mode 100644 src/main/java/io/swagger/api/factories/DcaeServicesApiServiceFactory.java create mode 100644 src/main/java/io/swagger/api/factories/DcaeServicesGroupbyApiServiceFactory.java create mode 100644 src/main/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImpl.java create mode 100644 src/main/java/io/swagger/api/impl/DcaeServicesApiServiceImpl.java create mode 100644 src/main/java/io/swagger/api/impl/DcaeServicesGroupbyApiServiceImpl.java (limited to 'src/main/java/io/swagger') diff --git a/src/main/java/io/swagger/api/Bootstrap.java b/src/main/java/io/swagger/api/Bootstrap.java new file mode 100644 index 0000000..5050ed3 --- /dev/null +++ b/src/main/java/io/swagger/api/Bootstrap.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api; + +import io.swagger.jaxrs.config.SwaggerContextService; +import io.swagger.models.*; + +import io.swagger.models.auth.*; + +import javax.servlet.http.HttpServlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +public class Bootstrap extends HttpServlet { + @Override + public void init(ServletConfig config) throws ServletException { + Info info = new Info() + .title("Swagger Server") + .description("DCAE Inventory is a web service that provides the following:\n\n1. Real-time data on all DCAE services and their components\n2. Comprehensive details on available DCAE service types\n") + .termsOfService("") + .contact(new Contact() + .email("dcae@lists.openecomp.org")) + .license(new License() + .name("") + .url("")); + + ServletContext context = config.getServletContext(); + Swagger swagger = new Swagger().info(info); + + new SwaggerContextService().withServletConfig(config).updateSwagger(swagger); + } +} diff --git a/src/main/java/io/swagger/api/factories/DcaeServiceTypesApiServiceFactory.java b/src/main/java/io/swagger/api/factories/DcaeServiceTypesApiServiceFactory.java new file mode 100644 index 0000000..fecd8fe --- /dev/null +++ b/src/main/java/io/swagger/api/factories/DcaeServiceTypesApiServiceFactory.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.factories; + +import io.swagger.api.DcaeServiceTypesApiService; +import io.swagger.api.impl.DcaeServiceTypesApiServiceImpl; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServiceTypesApiServiceFactory { + + private final static DcaeServiceTypesApiService service = new DcaeServiceTypesApiServiceImpl(); + + public static DcaeServiceTypesApiService getDcaeServiceTypesApi() + { + return service; + } +} diff --git a/src/main/java/io/swagger/api/factories/DcaeServicesApiServiceFactory.java b/src/main/java/io/swagger/api/factories/DcaeServicesApiServiceFactory.java new file mode 100644 index 0000000..47f213d --- /dev/null +++ b/src/main/java/io/swagger/api/factories/DcaeServicesApiServiceFactory.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.factories; + +import org.openecomp.dcae.inventory.clients.DCAEControllerClient; +import org.openecomp.dcae.inventory.clients.DatabusControllerClient; +import io.swagger.api.DcaeServicesApiService; +import io.swagger.api.impl.DcaeServicesApiServiceImpl; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServicesApiServiceFactory { + + // Yes I agree this code is not great and I blame for Swagger for putting me in this spot. + private static DCAEControllerClient dcaeControllerClient; + private static DatabusControllerClient databusControllerClient; + + public static void setDcaeControllerClient(DCAEControllerClient dcaeControllerClient) { + DcaeServicesApiServiceFactory.dcaeControllerClient = dcaeControllerClient; + } + + public static void setDatabusControllerClient(DatabusControllerClient databusControllerClient) { + DcaeServicesApiServiceFactory.databusControllerClient = databusControllerClient; + } + + public static DcaeServicesApiService getDcaeServicesApi() { + return new DcaeServicesApiServiceImpl(dcaeControllerClient, databusControllerClient); + } + +} diff --git a/src/main/java/io/swagger/api/factories/DcaeServicesGroupbyApiServiceFactory.java b/src/main/java/io/swagger/api/factories/DcaeServicesGroupbyApiServiceFactory.java new file mode 100644 index 0000000..041fbaf --- /dev/null +++ b/src/main/java/io/swagger/api/factories/DcaeServicesGroupbyApiServiceFactory.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.factories; + +import io.swagger.api.DcaeServicesGroupbyApiService; +import io.swagger.api.impl.DcaeServicesGroupbyApiServiceImpl; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServicesGroupbyApiServiceFactory { + + private final static DcaeServicesGroupbyApiService service = new DcaeServicesGroupbyApiServiceImpl(); + + public static DcaeServicesGroupbyApiService getDcaeServicesGroupbyApi() + { + return service; + } +} diff --git a/src/main/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImpl.java b/src/main/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImpl.java new file mode 100644 index 0000000..34d8a4b --- /dev/null +++ b/src/main/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImpl.java @@ -0,0 +1,312 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.impl; + +import org.openecomp.dcae.inventory.daos.DCAEServiceTypesDAO; +import org.openecomp.dcae.inventory.daos.DCAEServicesDAO; +import org.openecomp.dcae.inventory.daos.InventoryDAOManager; +import org.openecomp.dcae.inventory.dbthings.mappers.DCAEServiceTypeObjectMapper; +import org.openecomp.dcae.inventory.dbthings.models.DCAEServiceObject; +import org.openecomp.dcae.inventory.dbthings.models.DCAEServiceTypeObject; +import io.swagger.api.*; +import io.swagger.model.*; + +import io.swagger.api.NotFoundException; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.skife.jdbi.v2.Handle; +import org.skife.jdbi.v2.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.core.UriInfo; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServiceTypesApiServiceImpl extends DcaeServiceTypesApiService { + + private final static Logger LOG = LoggerFactory.getLogger(DcaeServiceTypesApiServiceImpl.class); + private static int PAGINATION_PAGE_SIZE = 25; + + private DCAEServiceType createDCAEServiceType(DCAEServiceTypeObject serviceTypeObject, UriInfo uriInfo) { + DCAEServiceType serviceType = new DCAEServiceType(); + serviceType.setSelfLink(DcaeServiceTypesApi.buildLinkForGet(uriInfo, "self", serviceTypeObject.getTypeId())); + serviceType.setTypeId(serviceTypeObject.getTypeId()); + serviceType.setTypeName(serviceTypeObject.getTypeName()); + serviceType.setTypeVersion(serviceTypeObject.getTypeVersion()); + serviceType.setOwner(serviceTypeObject.getOwner()); + serviceType.setVnfTypes(serviceTypeObject.getVnfTypes()); + serviceType.setServiceIds(serviceTypeObject.getServiceIds()); + serviceType.setServiceLocations(serviceTypeObject.getServiceLocations()); + serviceType.setBlueprintTemplate(serviceTypeObject.getBlueprintTemplate()); + serviceType.setAsdcServiceId(serviceTypeObject.getAsdcServiceId()); + serviceType.setAsdcResourceId(serviceTypeObject.getAsdcResourceId()); + // TODO: Construct ASDC service URL somehow + serviceType.setCreated(serviceTypeObject.getCreated().toDate()); + + DateTime deactivated = serviceTypeObject.getDeactivated(); + serviceType.setDeactivated(deactivated == null ? null : deactivated.toDate()); + + return serviceType; + } + + @Override + public Response dcaeServiceTypesGet(String typeName, Boolean onlyLatest, Boolean onlyActive, String vnfType, + String serviceId, String serviceLocation, String asdcServiceId, + String asdcResourceId, Integer offset, UriInfo uriInfo, SecurityContext securityContext) + throws NotFoundException { + List serviceTypeObjects = new ArrayList<>(); + + // TODO: Make this variable also a URL parameter. + DateTime createdCutoff = DateTime.now(DateTimeZone.UTC); + + try (Handle jdbiHandle = InventoryDAOManager.getInstance().getHandle()) { + StringBuilder sb = new StringBuilder("select * from "); + + if (onlyLatest) { + // Use the view which filters types that are of only the latest versions + sb.append("dcae_service_types_latest"); + } else { + sb.append("dcae_service_types"); + } + + List whereClauses = new ArrayList(); + + if (typeName != null) { + whereClauses.add(":typeName = type_name"); + } + + if (vnfType != null) { + whereClauses.add("lower(:vnfType) = any(lower(vnf_types\\:\\:text)\\:\\:text[])"); + } + + if (serviceId != null) { + whereClauses.add("(:serviceId = any(service_ids) or service_ids = \'{}\' or service_ids is null)"); + } + + if (serviceLocation != null) { + whereClauses.add("(:serviceLocation = any(service_locations) or service_locations = \'{}\' or service_locations is null)"); + } + + if (asdcServiceId != null) { + if ("NONE".equals(asdcServiceId.toUpperCase(Locale.ENGLISH))) { + whereClauses.add("asdc_service_id is null"); + } else { + whereClauses.add(":asdcServiceId = asdc_service_id"); + } + } + + if (asdcResourceId != null) { + if ("NONE".equals(asdcResourceId.toUpperCase(Locale.ENGLISH))) { + whereClauses.add("asdc_resource_id is null"); + } else { + whereClauses.add(":asdcResourceId = asdc_resource_id"); + } + } + + whereClauses.add("created < :createdCutoff"); + + if (onlyActive) { + whereClauses.add("deactivated is null"); + } + + if (!whereClauses.isEmpty()) { + sb.append(" where "); + sb.append(String.join(" and ", whereClauses)); + } + + // Sort by created timestamp - always descending. + sb.append(" order by created desc"); + + Query query = jdbiHandle.createQuery(sb.toString()).map(new DCAEServiceTypeObjectMapper()); + + if (typeName != null) { + query.bind("typeName", typeName); + } + + if (vnfType != null) { + query.bind("vnfType", vnfType); + } + + if (serviceId != null) { + query.bind("serviceId", serviceId); + } + + if (serviceLocation != null) { + query.bind("serviceLocation", serviceLocation); + } + + if (asdcServiceId != null && !"NONE".equals(asdcServiceId.toUpperCase(Locale.ENGLISH))) { + query.bind("asdcServiceId", asdcServiceId); + } + + if (asdcResourceId != null && !"NONE".equals(asdcResourceId.toUpperCase(Locale.ENGLISH))) { + query.bind("asdcResourceId", asdcResourceId); + } + + query.bind("createdCutoff", createdCutoff); + + serviceTypeObjects = query.list(); + } + + offset = (offset == null) ? 0 : offset; + + Integer totalCount = serviceTypeObjects.size(); + + // See comment in DcaeServicesApiServiceImpl.java above similar code. + Integer endpoint = Math.min(offset + PAGINATION_PAGE_SIZE, totalCount); + List serviceTypeObjectsSliced = serviceTypeObjects.subList(offset, endpoint); + + List serviceTypes = new ArrayList<>(); + + for (DCAEServiceTypeObject serviceTypeObject : serviceTypeObjectsSliced) { + serviceTypes.add(createDCAEServiceType(serviceTypeObject, uriInfo)); + } + + InlineResponse200 response = new InlineResponse200(); + response.setItems(serviceTypes); + response.setTotalCount(totalCount); + + InlineResponse200Links navigationLinks = new InlineResponse200Links(); + Integer offsetPrev = offset - PAGINATION_PAGE_SIZE; + + // TODO: MUST UPDATE THIS LINK NAV CODE + + if (offsetPrev >= 0) { + navigationLinks.setPreviousLink(DcaeServiceTypesApi.buildLinkForGet(uriInfo, "prev", typeName, onlyLatest, + onlyActive, vnfType, serviceId, serviceLocation, asdcServiceId, asdcResourceId, offsetPrev)); + } + + Integer offsetNext = offset + PAGINATION_PAGE_SIZE; + + if (offsetNext < totalCount) { + navigationLinks.setNextLink(DcaeServiceTypesApi.buildLinkForGet(uriInfo, "next", typeName, onlyLatest, + onlyActive, vnfType, serviceId, serviceLocation, asdcServiceId, asdcResourceId, offsetNext)); + } + + response.setLinks(navigationLinks); + + return Response.ok().entity(response).build(); + } + + @Override + public Response dcaeServiceTypesTypeIdGet(String typeId, UriInfo uriInfo, SecurityContext securityContext) + throws NotFoundException { + DCAEServiceTypesDAO serviceTypesDAO = InventoryDAOManager.getInstance().getDCAEServiceTypesDAO(); + DCAEServiceTypeObject serviceTypeObject = serviceTypesDAO.getByTypeId(typeId); + + if (serviceTypeObject == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + + return Response.ok().entity(createDCAEServiceType(serviceTypeObject, uriInfo)).build(); + } + + /** + * Create a DCAE service type database object + * + * Utility method that takes a DCAE service type request body and creates a database object representation + * to insert. + * + * @param typeId + * @param request + * @return + */ + private static DCAEServiceTypeObject createDCAEServiceTypeDBO(String typeId, DCAEServiceTypeRequest request) { + DCAEServiceTypeObject serviceTypeObject = new DCAEServiceTypeObject(); + serviceTypeObject.setTypeId(typeId); + serviceTypeObject.setTypeName(request.getTypeName()); + serviceTypeObject.setTypeVersion(request.getTypeVersion()); + serviceTypeObject.setOwner(request.getOwner()); + serviceTypeObject.setBlueprintTemplate(request.getBlueprintTemplate()); + serviceTypeObject.setVnfTypes(request.getVnfTypes()); + serviceTypeObject.setServiceIds(request.getServiceIds()); + serviceTypeObject.setServiceLocations(request.getServiceLocations()); + serviceTypeObject.setAsdcServiceId(request.getAsdcServiceId()); + serviceTypeObject.setAsdcResourceId(request.getAsdcResourceId()); + serviceTypeObject.setCreated(DateTime.now(DateTimeZone.UTC)); + + return serviceTypeObject; + } + + @Override + public Response dcaeServiceTypesTypeIdPost(DCAEServiceTypeRequest request, UriInfo uriInfo, + SecurityContext securityContext) { + DCAEServiceTypesDAO serviceTypesDAO = InventoryDAOManager.getInstance().getDCAEServiceTypesDAO(); + // Must query by the implicit composite key: type name, type version, asdc service id, asdc resource id + // Had to split up the queries into two because in SQL selecting by null has to be `some_field is null` + // + // FIXME: There is a race condition here where there could be multiple records with different ids + // for the same implicit composite key. Maybe the answer is to simply add back in a PUT. + DCAEServiceTypeObject serviceTypeObject + = (request.getAsdcServiceId() == null || request.getAsdcResourceId() == null) + ? serviceTypesDAO.getByRequestFromNotASDC(request) : serviceTypesDAO.getByRequestFromASDC(request); + + if (serviceTypeObject == null) { + // Generate a new type id + String typeId = UUID.randomUUID().toString(); + serviceTypeObject = createDCAEServiceTypeDBO(typeId, request); + serviceTypesDAO.insert(serviceTypeObject); + return Response.ok().entity(createDCAEServiceType(serviceTypeObject, uriInfo)).build(); + } + + // Service type with same composite key already exists so try to update + + String typeId = serviceTypeObject.getTypeId(); + DCAEServicesDAO servicesDAO = InventoryDAOManager.getInstance().getDCAEServicesDAO(); + Integer count = servicesDAO.countByType(DCAEServiceObject.DCAEServiceStatus.RUNNING, typeId); + + LOG.info(String.format("Checked num DCAE services running: %s, %d", typeId, count)); + + // Allow the updating of an existing DCAE service type IFF there are no running DCAE services for this type + + if (count > 0) { + String message = String.format("DCAE services of type %s are still running: %d", typeId, count); + ApiResponseMessage entity = new ApiResponseMessage(ApiResponseMessage.ERROR, message); + return Response.status(Response.Status.CONFLICT).entity(entity).build(); + } else { + serviceTypeObject = createDCAEServiceTypeDBO(typeId, request); + serviceTypesDAO.update(serviceTypeObject); + return Response.ok().entity(serviceTypeObject).build(); + } + } + + @Override + public Response dcaeServiceTypesTypeIdDelete(String typeId, UriInfo uriInfo, SecurityContext securityContext) + throws NotFoundException { + DCAEServiceTypesDAO serviceTypesDAO = InventoryDAOManager.getInstance().getDCAEServiceTypesDAO(); + + if (serviceTypesDAO.getByTypeId(typeId) == null) { + throw new NotFoundException(1, String.format("DCAE service type not found: %s", typeId)); + } else if (serviceTypesDAO.getByTypeIdActiveOnly(typeId) == null) { + return Response.status(Response.Status.GONE).build(); + } + + serviceTypesDAO.deactivateExisting(typeId); + return Response.ok().build(); + } + +} diff --git a/src/main/java/io/swagger/api/impl/DcaeServicesApiServiceImpl.java b/src/main/java/io/swagger/api/impl/DcaeServicesApiServiceImpl.java new file mode 100644 index 0000000..d1e790c --- /dev/null +++ b/src/main/java/io/swagger/api/impl/DcaeServicesApiServiceImpl.java @@ -0,0 +1,401 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.impl; + +import org.openecomp.dcae.inventory.clients.DCAEControllerClient; +import org.openecomp.dcae.inventory.clients.DatabusControllerClient; +import org.openecomp.dcae.inventory.daos.DCAEServiceComponentsDAO; +import org.openecomp.dcae.inventory.daos.DCAEServiceTransactionDAO; +import org.openecomp.dcae.inventory.daos.DCAEServicesDAO; +import org.openecomp.dcae.inventory.daos.InventoryDAOManager; +import org.openecomp.dcae.inventory.dbthings.mappers.DCAEServiceObjectMapper; +import org.openecomp.dcae.inventory.dbthings.models.DCAEServiceComponentObject; +import org.openecomp.dcae.inventory.dbthings.models.DCAEServiceObject; +import org.openecomp.dcae.inventory.exceptions.DCAEControllerClientException; +import org.openecomp.dcae.inventory.exceptions.DatabusControllerClientException; +import io.swagger.api.*; +import io.swagger.model.*; + +import io.swagger.api.NotFoundException; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.skife.jdbi.v2.Handle; +import org.skife.jdbi.v2.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.*; +import javax.ws.rs.core.Link; +import java.util.*; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServicesApiServiceImpl extends DcaeServicesApiService { + + private final static Logger LOG = LoggerFactory.getLogger(DcaeServicesApiServiceImpl.class); + private static int PAGINATION_PAGE_SIZE = 25; + private static String COMPONENT_SOURCE_DCAE_CONTROLLER = "DCAECONTROLLER"; + private static String COMPONENT_SOURCE_DATA_BUS_CONTROLLER = "DMAAPCONTROLLER"; + + private final DCAEControllerClient dcaeControllerClient; + private final DatabusControllerClient databusControllerClient; + + private DCAEService createDCAEService(DCAEServiceObject serviceObject, Collection componentObjects, + UriInfo uriInfo) { + // TODO: Complete links: come back and do links for vnf + DCAEService service = new DCAEService(); + service.setServiceId(serviceObject.getServiceId()); + service.setSelfLink(DcaeServicesApi.buildLinkForGet(uriInfo, "self", serviceObject.getServiceId())); + service.setTypeLink(DcaeServiceTypesApi.buildLinkForGet(uriInfo, "type", serviceObject.getTypeId())); + service.setCreated(serviceObject.getCreated().toDate()); + service.setModified(serviceObject.getModified().toDate()); + service.setVnfId(serviceObject.getVnfId()); + //service.setVnfLink(vnfLink); + service.setVnfType(serviceObject.getVnfType()); + service.setVnfLocation(serviceObject.getVnfLocation()); + service.setDeploymentRef(serviceObject.getDeploymentRef()); + + List serviceComponents = new ArrayList(); + + for (DCAEServiceComponentObject sco : componentObjects) { + DCAEServiceComponent component = new DCAEServiceComponent(); + component.setComponentId(sco.getComponentId()); + component.setComponentType(sco.getComponentType()); + component.setComponentSource(sco.getComponentSource()); + component.setShareable(sco.getShareable()); + component.setCreated(sco.getCreated().toDate()); + component.setModified(sco.getModified().toDate()); + + // TODO: When putting together the components fail. Should this be a 500 case? + // For now, this is just logged as a warning. + + if (COMPONENT_SOURCE_DCAE_CONTROLLER.equals(sco.getComponentSource().toUpperCase(Locale.ENGLISH))) { + if (this.dcaeControllerClient != null) { + try { + DCAEControllerClient.ServiceInstance serviceInstance + = this.dcaeControllerClient.getServiceInstance(component.getComponentId()); + component.setStatus(serviceInstance.getStatus()); + // There's no specific location rather its inferred from the AIC tenant + component.setLocation(this.dcaeControllerClient.getLocation(serviceInstance)); + Link componentLink = Link.fromUri(this.dcaeControllerClient.constructResourceURI(sco.getComponentId())) + .rel("component").title(component.getComponentId()).build(); + component.setComponentLink(componentLink); + } catch (DCAEControllerClientException e) { + LOG.warn(String.format("%s, %s", e.getMessage(), sco.toString())); + } + } + } else if (COMPONENT_SOURCE_DATA_BUS_CONTROLLER.equals(sco.getComponentSource().toUpperCase(Locale.ENGLISH))) { + if (this.databusControllerClient != null) { + try { + if (this.databusControllerClient.isExists(sco.getComponentId())) { + Link componentLink = Link.fromUri(this.databusControllerClient.constructResourceURI(sco.getComponentId())) + .rel("component").title(component.getComponentId()).build(); + component.setComponentLink(componentLink); + } else { + LOG.warn(String.format("Feed/topic does not exist: %s", sco.getComponentId())); + } + } catch (DatabusControllerClientException e) { + LOG.warn(String.format("%s, %s", e.getMessage(), sco.toString())); + } + } + } else { + LOG.warn(String.format("Handling unknown component source: %s", sco.getComponentSource())); + } + + serviceComponents.add(component); + } + + service.components(serviceComponents); + + return service; + } + + @Override + public Response dcaeServicesGet(String typeId, String vnfId, String vnfType, String vnfLocation, + String componentType, Boolean shareable, DateTime created, Integer offset, + UriInfo uriInfo, SecurityContext securityContext) { + List serviceObjects = new ArrayList<>(); + DateTime createdCutoff = (created == null ? DateTime.now(DateTimeZone.UTC) : created); + + LOG.info(String.format("Create time upper bound cutoff: %s", createdCutoff.toString())); + + // Offset is zero-based index + offset = (offset == null) ? 0 : offset; + LOG.info(String.format("Query offset: %d", offset)); + + try (Handle jdbiHandle = InventoryDAOManager.getInstance().getHandle()) { + // WATCH! There is the use of "distinct" here. + StringBuilder sb = new StringBuilder("select distinct ds.* from dcae_services ds"); + sb.append(" join dcae_services_components_maps m on ds.service_id = m.service_id "); + sb.append(" join dcae_service_components dsc on m.component_id = dsc.component_id"); + + List whereClauses = new ArrayList(); + + if (typeId != null) { + whereClauses.add("ds.type_id = :typeId"); + } + + if (vnfId != null) { + whereClauses.add("ds.vnf_id = :vnfId"); + } + + if (vnfType != null) { + whereClauses.add("lower(ds.vnf_type) = lower(:vnfType)"); + } + + if (vnfLocation != null) { + whereClauses.add("ds.vnf_location = :vnfLocation"); + } + + if (componentType != null) { + whereClauses.add("dsc.component_type = :componentType"); + } + + if (shareable != null) { + whereClauses.add("dsc.shareable = :shareable"); + } + + whereClauses.add("ds.created < :createdCutoff"); + whereClauses.add("ds.status = :serviceStatus"); + + if (!whereClauses.isEmpty()) { + sb.append(" where "); + sb.append(String.join(" and ", whereClauses)); + } + + // Sort by created timestamp - always descending. + sb.append(" order by created desc"); + + Query query = jdbiHandle.createQuery(sb.toString()).map(new DCAEServiceObjectMapper()); + + if (typeId != null) { + query.bind("typeId", typeId); + } + + if (vnfId != null) { + query.bind("vnfId", vnfId); + } + + if (vnfType != null) { + query.bind("vnfType", vnfType); + } + + if (vnfLocation != null) { + query.bind("vnfLocation", vnfLocation); + } + + if (componentType != null) { + query.bind("componentType", componentType); + } + + if (shareable != null) { + // NOTE: That the shareable field in the database is actually an integer. + query.bind("shareable", (shareable ? 1 : 0)); + } + + query.bind("createdCutoff", createdCutoff); + // NOTE: This is hardcoded because service status is only used internally. + query.bind("serviceStatus", DCAEServiceObject.DCAEServiceStatus.RUNNING); + + serviceObjects = query.list(); + } + + // NOTE: Chose to do the pagination via in code here rather than in SQL using LIMIT and OFFSET constraints + // because of the need for the global total number of result items. SQL approach would require two queries. + // Going forward, I think the better approach is using SQL because the resultsets may become very large. + // For now I think this approach is OK and actually we do less SQL querying. + Integer endpoint = Math.min(offset + PAGINATION_PAGE_SIZE, serviceObjects.size()); + List serviceObjectsSliced = serviceObjects.subList(offset, endpoint); + + DCAEServiceComponentsDAO componentsDAO = InventoryDAOManager.getInstance().getDCAEServiceComponentsDAO(); + List services = new ArrayList(); + + for (DCAEServiceObject so : serviceObjectsSliced) { + List components = componentsDAO.getByServiceId(so.getServiceId()); + services.add(createDCAEService(so, components, uriInfo)); + } + + InlineResponse2001 response = new InlineResponse2001(); + response.setItems(services); + response.setTotalCount(serviceObjects.size()); + // TODO: Show the total count of items in this response i.e. local count? + + InlineResponse200Links navigationLinks = new InlineResponse200Links(); + Integer offsetPrev = offset - PAGINATION_PAGE_SIZE; + + if (offsetPrev >= 0) { + navigationLinks.setPreviousLink(DcaeServicesApi.buildLinkForGet(uriInfo, "prev", typeId, vnfId, vnfType, + vnfLocation, componentType, shareable, created, offsetPrev)); + } + + Integer offsetNext = offset + PAGINATION_PAGE_SIZE; + + if (offsetNext < serviceObjects.size()) { + navigationLinks.setNextLink(DcaeServicesApi.buildLinkForGet(uriInfo, "next", typeId, vnfId, vnfType, + vnfLocation, componentType, shareable, created, offsetNext)); + } + + response.setLinks(navigationLinks); + + return Response.ok().entity(response).build(); + } + + @Override + public Response dcaeServicesServiceIdGet(String serviceId, UriInfo uriInfo, SecurityContext securityContext) + throws NotFoundException { + DCAEServicesDAO servicesDAO = InventoryDAOManager.getInstance().getDCAEServicesDAO(); + DCAEServiceComponentsDAO componentsDAO = InventoryDAOManager.getInstance().getDCAEServiceComponentsDAO(); + + DCAEServiceObject serviceObject = servicesDAO.getByServiceId(DCAEServiceObject.DCAEServiceStatus.RUNNING, serviceId); + + if (serviceObject == null) { + throw new NotFoundException(1, String.format("DCAEService not found: %s", serviceId)); + } + + List componentObjects = componentsDAO.getByServiceId(serviceId); + DCAEService service = createDCAEService(serviceObject, componentObjects, uriInfo); + + return Response.ok().entity(service).build(); + } + + @Override + public Response dcaeServicesServiceIdPut(String serviceId, DCAEServiceRequest request, UriInfo uriInfo, + SecurityContext securityContext) { + // Check to make sure that the DCAE service type exists + if (InventoryDAOManager.getInstance().getDCAEServiceTypesDAO().getByTypeIdActiveOnly(request.getTypeId()) == null) { + String errorMessage = String.format("DCAE service type does not exist: %s", request.getTypeId()); + ApiResponseMessage message = new ApiResponseMessage(ApiResponseMessage.ERROR, errorMessage); + return Response.status(422).entity(message).build(); + } + + // TODO: Check DCAE service components against source services i.e. DCAE controller and data bus controller + // Possibly refuse to process if that check fails. + + DCAEServicesDAO servicesDAO = InventoryDAOManager.getInstance().getDCAEServicesDAO(); + DCAEServiceComponentsDAO componentsDAO = InventoryDAOManager.getInstance().getDCAEServiceComponentsDAO(); + + // NOTE: 1607 is using Postgres v9.3 which does NOT have the upgrade to the INSERT operation that allows for UPSERTs + // Challenge here is make this entire PUT operation atomic. + // TODO: 1607 we are actually using v9.5 which has the UPSERT. Migrate this code to use the UPSERT. + + // Watch! We have to query for services regardless of status because we need to account for "removed" instances + // that get resurrected. + final DCAEServiceObject serviceObjectFromStore = servicesDAO.getByServiceId(serviceId); + final Map componentObjectsFromStore = new HashMap(); + + for (DCAEServiceComponentObject componentObject : componentsDAO.getByServiceId(serviceId)) { + componentObjectsFromStore.put(componentObject.getComponentId(), componentObject); + } + + DateTime modified = DateTime.now(DateTimeZone.UTC); + + DCAEServiceTransactionDAO.DCAEServiceTransactionContext transactionContext + = new DCAEServiceTransactionDAO.DCAEServiceTransactionContext(serviceId, modified); + + // 1) Insert/update for DCAEServiceObject + + DCAEServiceObject serviceObjectToSendBack = serviceObjectFromStore; + + if (serviceObjectFromStore == null) { + serviceObjectToSendBack = new DCAEServiceObject(serviceId, request); + serviceObjectToSendBack.setModified(modified); + transactionContext.setServiceObjectToInsert(serviceObjectToSendBack); + } else { + LOG.info(String.format("DCAEServiceObject already exists - updating: %s, %s", + serviceObjectFromStore.getCreated().toString(), + serviceObjectFromStore.getModified().toString())); + + serviceObjectToSendBack = new DCAEServiceObject(serviceObjectFromStore, request); + serviceObjectToSendBack.setModified(modified); + transactionContext.setServiceObjectToUpdate(serviceObjectToSendBack); + } + + // 2) Insert/update DCAEServiceComponentObjects. Components exist independent of the associated DCAE service. + + Map componentObjectsToSendBack = new HashMap(); + + for (DCAEServiceComponentRequest requestComponent : request.getComponents()) { + // Have to query the database rather than checking the result of getting by service id because of the + // independence of components and services. A component may already exist even though from a service + // perspective it is seen as "new". + final DCAEServiceComponentObject coExisting = componentsDAO.getByComponentId(requestComponent.getComponentId()); + DCAEServiceComponentObject coToSendBack = null; + + if (coExisting == null) { + // Add new component + coToSendBack = new DCAEServiceComponentObject(requestComponent); + coToSendBack.setModified(modified); + transactionContext.addComponentObjectToInsert(coToSendBack); + } else { + // TODO: Check if the mutable fields have changed before doing the update. + // Update existing component + coToSendBack = new DCAEServiceComponentObject(coExisting, requestComponent); + coToSendBack.setModified(modified); + transactionContext.addComponentObjectToUpdate(coToSendBack); + } + + if (coToSendBack != null) { + componentObjectsToSendBack.put(coToSendBack.getComponentId(), coToSendBack); + } + } + + // 3) Update relationships: add ones that don't exist, delete ones that do exist but no longer should not + + // Add relationships that didn't exist before + for (String componentId : componentObjectsToSendBack.keySet()) { + if (!componentObjectsFromStore.containsKey(componentId)) { + transactionContext.addMappingsToInsert(componentId); + } + } + + // Remove relationships that have been removed + for (String componentId : componentObjectsFromStore.keySet()) { + if (!componentObjectsToSendBack.containsKey(componentId)) { + transactionContext.addMappingsToDelete(componentId); + } + } + + DCAEServiceTransactionDAO transactionDAO = InventoryDAOManager.getInstance().getDCAEServiceTransactionDAO(); + transactionDAO.insert(transactionContext); + + DCAEService service = createDCAEService(serviceObjectToSendBack, componentObjectsToSendBack.values(), uriInfo); + + return Response.ok().entity(service).build(); + } + + public Response dcaeServicesServiceIdDelete(String serviceId, SecurityContext securityContext) throws NotFoundException { + DCAEServicesDAO servicesDAO = InventoryDAOManager.getInstance().getDCAEServicesDAO(); + + if (servicesDAO.getByServiceId(DCAEServiceObject.DCAEServiceStatus.RUNNING, serviceId) == null) { + throw new NotFoundException(ApiResponseMessage.ERROR, String.format("DCAE service not found: %s", serviceId)); + } + + servicesDAO.updateStatusByServiceId(DateTime.now(DateTimeZone.UTC), DCAEServiceObject.DCAEServiceStatus.REMOVED, + serviceId); + + return Response.ok().build(); + } + + public DcaeServicesApiServiceImpl(DCAEControllerClient dcaeControllerClient, DatabusControllerClient databusControllerClient) { + this.dcaeControllerClient = dcaeControllerClient; + this.databusControllerClient = databusControllerClient; + } + +} diff --git a/src/main/java/io/swagger/api/impl/DcaeServicesGroupbyApiServiceImpl.java b/src/main/java/io/swagger/api/impl/DcaeServicesGroupbyApiServiceImpl.java new file mode 100644 index 0000000..09d3143 --- /dev/null +++ b/src/main/java/io/swagger/api/impl/DcaeServicesGroupbyApiServiceImpl.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * dcae-inventory + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package io.swagger.api.impl; + +import org.openecomp.dcae.inventory.daos.InventoryDAOManager; +import org.openecomp.dcae.inventory.dbthings.models.DCAEServiceObject; +import io.swagger.api.*; +import io.swagger.model.DCAEServiceGroupByResults; +import io.swagger.model.DCAEServiceGroupByResultsPropertyValues; +import org.skife.jdbi.v2.Handle; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.core.UriInfo; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2016-04-18T20:16:22.119Z") +public class DcaeServicesGroupbyApiServiceImpl extends DcaeServicesGroupbyApiService { + + @Override + public Response dcaeServicesGroupbyPropertyNameGet(String propertyName, UriInfo uriInfo, SecurityContext securityContext) { + String columnName = ""; + + switch (propertyName) { + case "type": + columnName = "type_id"; + break; + case "vnfLocation": + columnName = "vnf_location"; + break; + case "vnfType": + columnName = "vnf_type"; + break; + default: + return Response.status(Response.Status.BAD_REQUEST).build(); + } + + List> results = new ArrayList<>(); + + try (Handle jdbiHandle = InventoryDAOManager.getInstance().getHandle()) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("select %s, count(1) as num ", columnName)); + sb.append(" from dcae_services where status = :serviceStatus"); + sb.append(String.format(" group by %s order by count(1) desc", columnName)); + String queryString = sb.toString(); + + // NOTE: This is hardcoded because service status is only used internally. + results = jdbiHandle.createQuery(queryString).bind("serviceStatus", DCAEServiceObject.DCAEServiceStatus.RUNNING) + .list(); + } + + DCAEServiceGroupByResults response = new DCAEServiceGroupByResults(); + response.setPropertyName(propertyName); + + for (Map result : results) { + DCAEServiceGroupByResultsPropertyValues value = new DCAEServiceGroupByResultsPropertyValues(); + value.setCount(((Long) result.get("num")).intValue()); + String propertyValue = (String) result.get(columnName); + value.setPropertyValue(propertyValue); + + switch (propertyName) { + case "type": + value.setDcaeServiceQueryLink(DcaeServicesApi.buildLinkForGetByTypeId(uriInfo, "dcae_services", + propertyValue)); + break; + case "vnfLocation": + value.setDcaeServiceQueryLink(DcaeServicesApi.buildLinkForGetByVnfLocation(uriInfo, "dcae_services", + propertyValue)); + break; + case "vnfType": + value.setDcaeServiceQueryLink(DcaeServicesApi.buildLinkForGetByVnfType(uriInfo, "dcae_services", + propertyValue)); + break; + default: + return Response.status(Response.Status.BAD_REQUEST).build(); + } + + response.getPropertyValues().add(value); + } + + return Response.ok().entity(response).build(); + } +} -- cgit 1.2.3-korg